@@ -190,6 +190,160 @@ params by using the associated [`.with_()`][rigging.chat.ChatPipeline.with_] fun
190
190
print(chat.last.content)
191
191
```
192
192
193
+ ## HTTP Generator
194
+
195
+ The [ ` HTTPGenerator ` ] [ rigging.generator.http.HTTPGenerator ] allows you to wrap any HTTP endpoint as a generator,
196
+ making it easy to integrate external LLMs or AI services into your Rigging pipelines. It works by
197
+ defining a specification that maps message content into HTTP requests and parses responses back into
198
+ messages.
199
+
200
+ The specification is assigned to the [ ` .spec ` ] [ rigging.generator.http.HTTPGenerator.spec ] field on the generator,
201
+ and can be applied as a Python dictionary, JSON string, YAML string, or base64 encoded JSON/YAML string.
202
+
203
+ This flexibility allows you to easily share and reuse specifications across different parts of your application.
204
+
205
+ ``` python
206
+ import rigging as rg
207
+
208
+ spec = r """
209
+ request:
210
+ url: "https://{{ model }}. crucible. dreadnode. io/submit"
211
+ headers:
212
+ "X-Api-Key": "{{ api_key }}"
213
+ "Content-Type": "application/json"
214
+ transforms:
215
+ - type: "json"
216
+ pattern: {
217
+ "data": "$ content"
218
+ }
219
+ response:
220
+ transforms:
221
+ - type: "jsonpath"
222
+ pattern: $ . flag,output,message
223
+ """
224
+
225
+ crucible = rg.get_generator(" http!spanglish,api_key=<key>" ) # (1)
226
+ crucible.spec = spec
227
+
228
+ chat = await crucible.chat(" A flag please" ).run()
229
+
230
+ print (chat.conversation)
231
+ # [user]: A flag please
232
+ #
233
+ # [assistant]: Una bandera, por favor.
234
+ ```
235
+
236
+ 1 . Were are using the ` .model ` field on the generator to carry our crucible challenge
237
+
238
+ !!! tip "Saving schemas"
239
+
240
+ Encoded YAML is the default storage when an HTTP generator is serialized to an indentifier using
241
+ [`to_identifier`][rigging.generator.Generator.to_identifier]. This also means that when we save
242
+ our chats to storage, they maintain their http specification.
243
+
244
+ ```py
245
+ print(crucible.to_identifier())
246
+ # http!spanglish,spec=eyJyZXF1ZXN0Ijp7InVyb...
247
+ ```
248
+
249
+ ### Specification
250
+
251
+ The [ specification (` HTTPSpec ` )] [ rigging.generator.http.HTTPSpec ] controls how messages are transformed around HTTP interactions. It supports:
252
+
253
+ - Template-based URLs
254
+ - Template-based header generation
255
+ - Configurable timeouts and HTTP methods
256
+ - Status code validation
257
+ - Flexible body transformations for both the request and response
258
+
259
+ When building requests, the following [ context variables (` RequestTransformContext ` )] [ rigging.generator.http.RequestTransformContext ]
260
+ are available in your transform patterns:
261
+
262
+ - ` role ` - Role of the last message (user/assistant/system)
263
+ - ` content ` - Content of the last message
264
+ - ` all_content ` - Concatenated content of all messages
265
+ - ` messages ` - List of all message objects
266
+ - ` params ` - Generation parameters (temperature, max_tokens, etc.)
267
+ - ` api_key ` - API key from the generator
268
+ - ` model ` - Model identifier from the generator
269
+
270
+ For both request and response transform chains, the previous result of each transform is
271
+ provided to the next transform via any of ` data ` , ` output ` , ` result ` , or ` body ` .
272
+
273
+ ### Transforms
274
+
275
+ The HTTP generator supports different types of transforms for both request building and response parsing.
276
+ Each serves a specific purpose and has its own pattern syntax.
277
+
278
+ !!! tip "Transform Chaining"
279
+
280
+ Transforms are applied in sequence, with each transform's output becoming the input for the next.
281
+ This allows you to build complex processing pipelines:
282
+
283
+ ```yaml
284
+ transforms:
285
+ - type: "jsonpath"
286
+ pattern: "$.data" # Extract data object
287
+ - type: "jinja"
288
+ pattern: "{{ result | tojson }}" # Convert to string
289
+ - type: "regex"
290
+ pattern: "message: (.*)" # Extract specific field
291
+ ```
292
+
293
+ ** Jinja (request + response)**
294
+
295
+ The ` jinja ` transform type provides full Jinja2 template syntax. Access context variables directly
296
+ and use Jinja2 filters and control structures.
297
+
298
+ ``` yaml
299
+ transforms :
300
+ - type : " jinja"
301
+ pattern : >
302
+ {
303
+ "content": "{{ all_content }}",
304
+ "timestamp": "{{ now() }}",
305
+ {% if params.temperature > 0.5 %}
306
+ "mode": "creative"
307
+ {% endif %}
308
+ }
309
+ ` ` `
310
+
311
+ **JSON (request only)**
312
+
313
+ The ` json` transform type lets you build JSON request bodies using a template object. Use `$` prefix
314
+ to reference context variables, with dot notation for nested access :
315
+
316
+ ` ` ` yaml
317
+ transforms:
318
+ - type: "json"
319
+ pattern: {
320
+ "messages": "$messages",
321
+ "temperature": "$params.temperature",
322
+ "content": "$content",
323
+ "static_field": "hello"
324
+ }
325
+ ` ` `
326
+
327
+ **JSONPath (response only)**
328
+
329
+ The `jsonpath` transform type uses [JSONPath](https://github.com/h2non/jsonpath-ng) expressions to extract data from JSON responses :
330
+
331
+ ` ` ` yaml
332
+ transforms:
333
+ - type: "jsonpath"
334
+ pattern: "$.choices[0].message.content"
335
+ ` ` `
336
+
337
+ **Regex (response only)**
338
+
339
+ The `regex` transform type uses regular expressions to extract content from text responses :
340
+
341
+ ` ` ` yaml
342
+ transforms:
343
+ - type: "regex"
344
+ pattern: "<output>(.*?)</output>"
345
+ ` ` `
346
+
193
347
# # Writing a Generator
194
348
195
349
All generators should inherit from the [`Generator`][rigging.generator.Generator] base class, and
0 commit comments