@ax-llm/ax 17.0.11 → 18.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,31 @@
1
1
  ---
2
2
  name: ax-agent
3
- description: This skill helps with building AxAgent-based agents using @ax-llm/ax. Use when the user asks about agent(), AxAgent, child agents, tool functions, smart model routing, RLM mode, stopping agents, or composing multi-agent hierarchies.
4
- version: "17.0.11"
3
+ description: This skill helps with building AxAgent-based agents using @ax-llm/ax. Use when the user asks about agent(), AxAgent, child agents, tool functions, RLM mode, stopping agents, or composing multi-agent hierarchies.
4
+ version: "18.0.1"
5
5
  ---
6
6
 
7
7
  # AxAgent Guide (@ax-llm/ax)
8
8
 
9
- AxAgent is the agent framework in Ax. It wraps AxGen with support for child agents, tool use, smart model routing, and RLM (Recursive Language Model) mode for processing long contexts through runtime-backed code execution.
9
+ AxAgent is the agent framework in Ax. It wraps AxGen with support for child agents, tool use, and RLM (Recursive Language Model) mode for processing long contexts through runtime-backed code execution.
10
10
 
11
11
  ## Quick Reference
12
12
 
13
13
  ```typescript
14
- import { agent, ai } from '@ax-llm/ax';
14
+ import { agent, ai, f } from '@ax-llm/ax';
15
15
 
16
16
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! });
17
17
 
18
18
  // Create and run an agent
19
- const myAgent = agent('userQuestion:string -> responseText:string', {
20
- name: 'helpfulAgent',
21
- description: 'An agent that provides helpful responses to user questions',
22
- });
19
+ const myAgent = agent(
20
+ f()
21
+ .input('userQuestion', f.string())
22
+ .output('responseText', f.string())
23
+ .build(),
24
+ {
25
+ name: 'helpfulAgent',
26
+ description: 'An agent that provides helpful responses to user questions',
27
+ }
28
+ );
23
29
 
24
30
  const result = await myAgent.forward(llm, { userQuestion: 'What is TypeScript?' });
25
31
  console.log(result.responseText);
@@ -33,59 +39,57 @@ for await (const chunk of stream) {
33
39
 
34
40
  ## Creating Agents
35
41
 
36
- Use the `agent()` factory function with a string signature:
42
+ Use the `agent()` factory function with a signature built using `f()`:
37
43
 
38
44
  ```typescript
39
- import { agent, ai } from '@ax-llm/ax';
45
+ import { agent, ai, f } from '@ax-llm/ax';
40
46
 
41
47
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! });
42
48
 
43
- const myAgent = agent('userQuestion:string -> responseText:string', {
44
- name: 'helpfulAgent',
45
- description: 'An agent that provides helpful responses to user questions',
46
- });
49
+ const myAgent = agent(
50
+ f()
51
+ .input('userQuestion', f.string())
52
+ .output('responseText', f.string())
53
+ .build(),
54
+ {
55
+ name: 'helpfulAgent',
56
+ description: 'An agent that provides helpful responses to user questions',
57
+ }
58
+ );
47
59
 
48
60
  const result = await myAgent.forward(llm, { userQuestion: 'What is TypeScript?' });
49
61
  console.log(result.responseText);
50
62
  ```
51
63
 
52
- The `agent()` function accepts both string signatures and `AxSignature` objects:
53
-
54
- ```typescript
55
- import { agent, s } from '@ax-llm/ax';
56
-
57
- const sig = s('userQuestion:string -> responseText:string');
58
- const myAgent = agent(sig, {
59
- name: 'helpfulAgent',
60
- description: 'An agent that provides helpful responses to user questions',
61
- });
62
- ```
63
-
64
64
  ## Agent Options
65
65
 
66
66
  The `agent()` factory accepts a configuration object:
67
67
 
68
68
  ```typescript
69
- const myAgent = agent('input:string -> output:string', {
70
- // Required
71
- name: 'myAgent', // Agent name (min 5 chars)
72
- description: 'Does something useful and interesting with inputs', // Min 20 chars
73
-
74
- // Optional
75
- ai: llm, // Bind a specific AI service
76
- definition: 'You are a helpful assistant that... (detailed prompt)', // Min 100 chars if provided
77
- functions: [searchTool, calcTool], // Tool functions
78
- agents: [childAgent1, childAgent2], // Child agents
79
- maxSteps: 25, // Max reasoning steps (default: 25)
80
- maxRetries: 3, // Retries on assertion failures
81
- temperature: 0.7, // Sampling temperature
82
- disableSmartModelRouting: false, // Disable automatic model selection
83
- excludeFieldsFromPassthrough: [], // Fields NOT passed to child agents
84
- debug: false, // Debug logging
85
-
86
- // RLM mode (see RLM section below)
87
- rlm: { ... },
88
- });
69
+ const myAgent = agent(
70
+ f()
71
+ .input('input', f.string())
72
+ .output('output', f.string())
73
+ .build(),
74
+ {
75
+ // Required
76
+ name: 'myAgent', // Agent name (min 5 chars)
77
+ description: 'Does something useful and interesting with inputs', // Min 20 chars
78
+
79
+ // Optional
80
+ ai: llm, // Bind a specific AI service
81
+ definition: 'You are a helpful assistant that... (detailed prompt)', // Min 100 chars if provided
82
+ functions: [searchTool, calcTool], // Tool functions
83
+ agents: [childAgent1, childAgent2], // Child agents
84
+ maxSteps: 25, // Max reasoning steps (default: 25)
85
+ maxRetries: 3, // Retries on assertion failures
86
+ temperature: 0.7, // Sampling temperature
87
+ debug: false, // Debug logging
88
+
89
+ // RLM mode (see RLM section below)
90
+ rlm: { ... },
91
+ }
92
+ );
89
93
  ```
90
94
 
91
95
  ### `name`
@@ -122,11 +126,17 @@ console.log(result.responseText);
122
126
  If the agent was created with `ai` bound, the parent AI is used as fallback:
123
127
 
124
128
  ```typescript
125
- const myAgent = agent('input:string -> output:string', {
126
- name: 'myAgent',
127
- description: 'An agent that processes inputs reliably',
128
- ai: llm,
129
- });
129
+ const myAgent = agent(
130
+ f()
131
+ .input('input', f.string())
132
+ .output('output', f.string())
133
+ .build(),
134
+ {
135
+ name: 'myAgent',
136
+ description: 'An agent that processes inputs reliably',
137
+ ai: llm,
138
+ }
139
+ );
130
140
 
131
141
  // Can also pass a different AI to override
132
142
  const result = await myAgent.forward(differentLlm, { input: 'test' });
@@ -170,10 +180,16 @@ const result = await myAgent.forward(llm, values, {
170
180
  Call `stop()` from any context — a timer, event handler, or another async task — to halt the multi-step loop. `stop()` aborts all in-flight calls started by the same `AxAgent` instance (including retry backoff waits):
171
181
 
172
182
  ```typescript
173
- const myAgent = agent('question:string -> answer:string', {
174
- name: 'myAgent',
175
- description: 'An agent that answers questions thoroughly',
176
- });
183
+ const myAgent = agent(
184
+ f()
185
+ .input('question', f.string())
186
+ .output('answer', f.string())
187
+ .build(),
188
+ {
189
+ name: 'myAgent',
190
+ description: 'An agent that answers questions thoroughly',
191
+ }
192
+ );
177
193
 
178
194
  const timer = setTimeout(() => myAgent.stop(), 5_000);
179
195
 
@@ -194,7 +210,12 @@ try {
194
210
  `stop()` is also available on `AxGen` and `AxFlow` instances:
195
211
 
196
212
  ```typescript
197
- const gen = ax('topic:string -> summary:string');
213
+ const gen = ax(
214
+ f()
215
+ .input('topic', f.string())
216
+ .output('summary', f.string())
217
+ .build()
218
+ );
198
219
  setTimeout(() => gen.stop(), 3_000);
199
220
 
200
221
  try {
@@ -242,7 +263,7 @@ try {
242
263
  Define tool functions with a name, description, JSON Schema parameters, and implementation:
243
264
 
244
265
  ```typescript
245
- import { ai, agent } from '@ax-llm/ax';
266
+ import { ai, agent, f } from '@ax-llm/ax';
246
267
 
247
268
  const getCurrentWeather = {
248
269
  name: 'getCurrentWeather',
@@ -260,11 +281,17 @@ const getCurrentWeather = {
260
281
  }
261
282
  };
262
283
 
263
- const weatherAgent = agent('query:string -> response:string', {
264
- name: 'weatherAssistant',
265
- description: 'An assistant that helps with weather queries',
266
- functions: [getCurrentWeather]
267
- });
284
+ const weatherAgent = agent(
285
+ f()
286
+ .input('query', f.string())
287
+ .output('response', f.string())
288
+ .build(),
289
+ {
290
+ name: 'weatherAssistant',
291
+ description: 'An assistant that helps with weather queries',
292
+ functions: [getCurrentWeather]
293
+ }
294
+ );
268
295
 
269
296
  const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! });
270
297
  const result = await weatherAgent.forward(llm, { query: 'Weather in Tokyo?' });
@@ -276,7 +303,11 @@ Agents can compose other agents as children. The parent agent sees each child as
276
303
 
277
304
  ```typescript
278
305
  const researcher = agent(
279
- 'question:string, physicsQuestion:string -> answer:string',
306
+ f()
307
+ .input('question', f.string())
308
+ .input('physicsQuestion', f.string())
309
+ .output('answer', f.string())
310
+ .build(),
280
311
  {
281
312
  name: 'Physics Researcher',
282
313
  description: 'Researcher for physics questions can answer questions about advanced physics',
@@ -284,7 +315,10 @@ const researcher = agent(
284
315
  );
285
316
 
286
317
  const summarizer = agent(
287
- 'answer:string -> shortSummary:string',
318
+ f()
319
+ .input('answer', f.string())
320
+ .output('shortSummary', f.string())
321
+ .build(),
288
322
  {
289
323
  name: 'Science Summarizer',
290
324
  description: 'Summarizer can write short summaries of advanced science topics',
@@ -292,48 +326,23 @@ const summarizer = agent(
292
326
  }
293
327
  );
294
328
 
295
- const scientist = agent('question:string -> answer:string', {
296
- name: 'Scientist',
297
- description: 'An agent that can answer advanced science questions',
298
- agents: [researcher, summarizer],
299
- });
329
+ const scientist = agent(
330
+ f()
331
+ .input('question', f.string())
332
+ .output('answer', f.string())
333
+ .build(),
334
+ {
335
+ name: 'Scientist',
336
+ description: 'An agent that can answer advanced science questions',
337
+ agents: [researcher, summarizer],
338
+ }
339
+ );
300
340
 
301
341
  const result = await scientist.forward(llm, {
302
342
  question: 'Why is gravity not a real force?',
303
343
  });
304
344
  ```
305
345
 
306
- ### Value Passthrough
307
-
308
- When a parent and child agent share input field names, the parent automatically passes those values to the child. Control which fields are excluded from passthrough:
309
-
310
- ```typescript
311
- const myAgent = agent('context:string, query:string -> answer:string', {
312
- name: 'myAgent',
313
- description: 'An agent that processes queries with context provided',
314
- agents: [childAgent],
315
- excludeFieldsFromPassthrough: ['context'],
316
- });
317
- ```
318
-
319
- ## Smart Model Routing
320
-
321
- When an AI service is configured with multiple models, agents automatically expose a `model` parameter to parent agents. The parent LLM can choose which model to use for each child call based on task complexity.
322
-
323
- ```typescript
324
- const llm = ai({
325
- name: 'openai',
326
- apiKey: process.env.OPENAI_APIKEY!,
327
- models: [
328
- { key: 'dumb', model: 'gpt-3.5-turbo', description: 'Simple questions' },
329
- { key: 'smart', model: 'gpt-4o-mini', description: 'Advanced questions' },
330
- { key: 'smartest', model: 'gpt-4o', description: 'Most complex questions' },
331
- ],
332
- });
333
- ```
334
-
335
- Disable smart routing per-agent with `disableSmartModelRouting: true`.
336
-
337
346
  ## RLM Mode
338
347
 
339
348
  RLM (Recursive Language Model) mode lets agents process arbitrarily long documents without hitting context window limits. Instead of stuffing the entire document into the LLM prompt, RLM loads it into a code interpreter session and gives the LLM tools to analyze it programmatically.
@@ -348,34 +357,41 @@ When you pass a long document to an LLM, you face:
348
357
  ### How It Works
349
358
 
350
359
  1. **Context extraction** — Fields listed in `contextFields` are removed from the LLM prompt and loaded into a runtime session as variables.
351
- 2. **Execution mode**
352
- - `mode: 'inline'` (default): the LLM emits helper output fields (`<language>Code`, `llmQuery`, `resultReady`) that are processed via field processors.
353
- - `mode: 'function'`: the LLM uses the `codeInterpreter` tool.
354
- 3. **Sub-LM queries** — Runtime calls use `llmQuery(...)` for semantic analysis.
355
- 4. **Final answer** — When done, the LLM provides its final answer with the required output fields.
360
+ 2. **Actor/Responder split** — The agent uses two internal programs:
361
+ - **Actor** A code generation agent that writes JavaScript to analyze context data. It NEVER generates final answers directly.
362
+ - **Responder** An answer synthesis agent that produces the final answer from the Actor's action log. It NEVER generates code.
363
+ 3. **Sub-LM queries** — Inside code, `llmQuery(...)` delegates semantic work to a sub-model.
364
+ 4. **Completion** — The Actor signals done by calling `done()` (standalone or inline with other code), then the Responder synthesizes the final answer.
356
365
 
357
- The LLM writes code to inspect, filter, and iterate over the document. If useful, it can chunk data manually in code before calling `llmQuery`.
366
+ The Actor writes JavaScript code to inspect, filter, and iterate over the document. It uses `llmQuery` for semantic analysis and can chunk data in code before querying.
358
367
 
359
368
  ### Configuration
360
369
 
361
370
  ```typescript
362
- import { agent, ai } from '@ax-llm/ax';
363
- import { AxJSRuntime } from '@ax-llm/ax';
371
+ import { agent, ai, f } from '@ax-llm/ax';
364
372
 
365
373
  const analyzer = agent(
366
- 'context:string, query:string -> answer:string, evidence:string[]',
374
+ f()
375
+ .input('context', f.string())
376
+ .input('query', f.string())
377
+ .output('answer', f.string())
378
+ .output('evidence', f.string().array())
379
+ .build(),
367
380
  {
368
381
  name: 'documentAnalyzer',
369
382
  description: 'Analyzes long documents using code interpreter and sub-LM queries',
370
- maxSteps: 15,
371
383
  rlm: {
372
- mode: 'inline', // 'inline' (default) | 'function'
373
- language: 'javascript', // Used for inline helper field naming (default: 'javascript')
374
- contextFields: ['context'], // Fields to load into runtime session
375
- runtime: new AxJSRuntime(), // Code runtime implementation
376
- maxLlmCalls: 30, // Cap on sub-LM calls (default: 50)
377
- maxRuntimeChars: 2_000, // Shared cap for llmQuery context + interpreter output (default: 2_000)
378
- subModel: 'gpt-4o-mini', // Model for llmQuery (default: same as parent)
384
+ contextFields: ['context'], // Fields to load into runtime session
385
+ runtime: new AxJSRuntime(), // Code runtime (default: AxJSRuntime)
386
+ maxLlmCalls: 30, // Cap on sub-LM calls (default: 50)
387
+ maxRuntimeChars: 2_000, // Cap for llmQuery context + code output (default: 5000)
388
+ maxBatchedLlmQueryConcurrency: 6, // Max parallel batched llmQuery calls (default: 8)
389
+ subModel: 'gpt-4o-mini', // Model for llmQuery (default: same as parent)
390
+ maxTurns: 10, // Max Actor turns before forcing Responder (default: 10)
391
+ actorFields: ['reasoning'], // Output fields produced by Actor instead of Responder
392
+ actorCallback: async (result) => { // Called after each Actor turn
393
+ console.log('Actor turn:', result);
394
+ },
379
395
  },
380
396
  }
381
397
  );
@@ -414,15 +430,19 @@ Available permissions:
414
430
  Context fields aren't limited to plain strings. You can pass structured data — objects and arrays with typed sub-fields:
415
431
 
416
432
  ```typescript
417
- import { agent, f, s } from '@ax-llm/ax';
433
+ import { agent, f } from '@ax-llm/ax';
418
434
  import { AxJSRuntime } from '@ax-llm/ax';
419
435
 
420
- const sig = s('query:string -> answer:string, evidence:string[]')
421
- .appendInputField('documents', f.object({
436
+ const sig = f()
437
+ .input('query', f.string())
438
+ .input('documents', f.object({
422
439
  id: f.number('Document ID'),
423
440
  title: f.string('Document title'),
424
441
  content: f.string('Document body'),
425
- }).array('Source documents'));
442
+ }).array('Source documents'))
443
+ .output('answer', f.string())
444
+ .output('evidence', f.string().array())
445
+ .build();
426
446
 
427
447
  const analyzer = agent(sig, {
428
448
  name: 'structuredAnalyzer',
@@ -454,22 +474,100 @@ const summaries = await llmQuery(
454
474
 
455
475
  Structured fields are loaded as native JavaScript objects in the interpreter, preserving their full structure for programmatic access.
456
476
 
457
- ### The REPL Loop
477
+ ### The Actor Loop
478
+
479
+ The Actor generates JavaScript code in a `javascriptCode` output field. Each turn:
480
+
481
+ 1. The Actor emits `javascriptCode` containing JavaScript to execute
482
+ 2. The runtime executes the code and returns the result
483
+ 3. The result is appended to the action log
484
+ 4. The Actor sees the updated action log and decides what to do next
485
+ 5. When the Actor calls `done()` (standalone or inline with other code), the loop ends and the Responder takes over
486
+
487
+ The Actor's typical workflow:
488
+
489
+ 1. Explore context structure (typeof, length, slice)
490
+ 2. Plan a chunking strategy based on what it observes
491
+ 3. Use code for structural work (filter, map, regex, property access)
492
+ 4. Use llmQuery for semantic work (summarization, interpretation)
493
+ 5. Build up answers in variables across turns
494
+ 6. Signal done by calling `done()` — can be standalone or combined with final code
458
495
 
459
- In `mode: 'function'`, the agent gets a `codeInterpreter` tool.
496
+ ### Actor Fields
460
497
 
461
- In `mode: 'inline'`, the model emits helper output fields:
462
- - `<language>Code` (for example `javascriptCode`) for runtime code execution
463
- - `llmQuery` (`string[]`) for batched sub-LM queries
464
- - `resultReady` (`boolean`) to signal completion
498
+ By default, all output fields from the signature go to the Responder. Use `actorFields` to route specific output fields to the Actor instead. The Actor produces these fields each turn (alongside `javascriptCode`), and their values are included in the action log for context. The last Actor turn's values are merged into the final output.
465
499
 
466
- The LLM's typical workflow:
500
+ ```typescript
501
+ const analyzer = agent(
502
+ f()
503
+ .input('context', f.string())
504
+ .input('query', f.string())
505
+ .output('answer', f.string())
506
+ .output('reasoning', f.string())
507
+ .build(),
508
+ {
509
+ name: 'reasoningAnalyzer',
510
+ description: 'Analyzes context with explicit reasoning steps',
511
+ rlm: {
512
+ contextFields: ['context'],
513
+ actorFields: ['reasoning'], // Actor produces 'reasoning', Responder produces 'answer'
514
+ },
515
+ }
516
+ );
517
+ ```
518
+
519
+ ### Actor Callback
467
520
 
468
- 1. Peek at context structure (typeof, length, slice)
469
- 2. Filter/select relevant slices (chunk manually only when needed)
470
- 3. Use llmQuery for semantic analysis of selected context
471
- 4. Aggregate results
472
- 5. Provide the final answer with the required output fields
521
+ Use `actorCallback` to observe each Actor turn. It receives the full Actor result (including `javascriptCode` and any `actorFields`) and fires every turn, including the done() turn.
522
+
523
+ ```typescript
524
+ const analyzer = agent(
525
+ f()
526
+ .input('context', f.string())
527
+ .input('query', f.string())
528
+ .output('answer', f.string())
529
+ .build(),
530
+ {
531
+ name: 'callbackAnalyzer',
532
+ description: 'Analyzes context with observable actor turns',
533
+ rlm: {
534
+ contextFields: ['context'],
535
+ actorCallback: async (result) => {
536
+ console.log('Actor code:', result.javascriptCode);
537
+ },
538
+ },
539
+ }
540
+ );
541
+ ```
542
+
543
+ ### Actor/Responder Forward Options
544
+
545
+ Use `actorOptions` and `responderOptions` to set different forward options (model, thinking budget, etc.) for the Actor and Responder sub-programs. These are set at construction time and act as defaults that can still be overridden at forward time.
546
+
547
+ ```typescript
548
+ const analyzer = agent(
549
+ f()
550
+ .input('context', f.string())
551
+ .input('query', f.string())
552
+ .output('answer', f.string())
553
+ .build(),
554
+ {
555
+ name: 'dualModelAnalyzer',
556
+ description: 'Analyzes context using different models for actor and responder',
557
+ rlm: { contextFields: ['context'] },
558
+ actorOptions: {
559
+ model: 'fast-model',
560
+ thinkingTokenBudget: 1024,
561
+ },
562
+ responderOptions: {
563
+ model: 'smart-model',
564
+ thinkingTokenBudget: 4096,
565
+ },
566
+ }
567
+ );
568
+ ```
569
+
570
+ Priority order (low to high): constructor base options < `actorOptions`/`responderOptions` < forward-time options.
473
571
 
474
572
  ### Available APIs in the Sandbox
475
573
 
@@ -477,6 +575,8 @@ The LLM's typical workflow:
477
575
  |-----|-------------|
478
576
  | `await llmQuery(query, context?)` | Ask a sub-LM a question, optionally with a context string. Returns a string. Oversized context is truncated to `maxRuntimeChars` |
479
577
  | `await llmQuery([{ query, context? }, ...])` | Run multiple sub-LM queries in parallel. Returns string[]. Failed items return `[ERROR] ...` |
578
+ | `await agents.<name>({...})` | Call a child agent by name. Parameters match the agent's JSON schema. Returns a string |
579
+ | `await <toolName>({...})` | Call a tool function by name. Parameters match the tool's JSON schema |
480
580
  | `print(...args)` | Available in `AxJSRuntime` when `outputMode: 'stdout'`; captured output appears in the function result |
481
581
  | Context variables | All fields listed in `contextFields` are available by name |
482
582
 
@@ -486,7 +586,7 @@ By default, `AxJSRuntime` uses `outputMode: 'stdout'`, where visible output come
486
586
 
487
587
  `AxJSRuntime` state is session-scoped. Values survive across `execute()` calls only while you keep using the same session.
488
588
 
489
- - `mode: 'inline'` and `mode: 'function'` in RLM both run in a persistent runtime session.
589
+ - The Actor loop runs in a persistent runtime session variables survive across turns.
490
590
  - `runtime.toFunction()` is different: it creates a new session per tool call, then closes it, so state does not persist across calls.
491
591
 
492
592
  When code contains `await`, the runtime compiles it as an async function so top-level `await` works. In that async path, local declarations (`const`/`let`/`var`) are function-scoped and should not be relied on for cross-call state.
@@ -544,8 +644,6 @@ The built-in `AxJSRuntime` uses Web Workers for sandboxed code execution. For ot
544
644
  import type { AxCodeRuntime, AxCodeSession } from '@ax-llm/ax';
545
645
 
546
646
  class MyBrowserInterpreter implements AxCodeRuntime {
547
- readonly language = 'JavaScript';
548
-
549
647
  getUsageInstructions?(): string {
550
648
  return 'Runtime-specific guidance for writing code in this environment.';
551
649
  }
@@ -566,6 +664,8 @@ class MyBrowserInterpreter implements AxCodeRuntime {
566
664
  The `globals` object passed to `createSession` includes:
567
665
  - All context field values (by field name)
568
666
  - `llmQuery` function (supports both single and batched queries)
667
+ - `agents` namespace object with child agent functions (e.g., `agents.summarize(...)`)
668
+ - Tool functions as flat globals
569
669
  - `print` function when supported by the runtime (for `AxJSRuntime`, set `outputMode: 'stdout'`)
570
670
 
571
671
  If provided, `getUsageInstructions()` is appended to the RLM system prompt as runtime-specific guidance. Use it for semantics that differ by runtime (for example state persistence or async execution behavior).
@@ -580,17 +680,15 @@ RLM mode does not support true streaming. When using `streamingForward`, RLM run
580
680
 
581
681
  ```typescript
582
682
  interface AxRLMConfig {
583
- mode?: 'function' | 'inline'; // RLM execution mode (default: 'inline')
584
- language?: string; // Inline helper field prefix (default: 'javascript')
585
- contextFields: string[]; // Input fields holding long context
586
- runtime?: AxCodeRuntime; // Preferred runtime key
587
- interpreter?: AxCodeRuntime; // Legacy alias (deprecated)
588
- maxLlmCalls?: number; // Cap on sub-LM calls (default: 50)
589
- maxRuntimeChars?: number; // Shared cap for llmQuery context + interpreter output (default: 2_000)
590
- maxSubQueryContextChars?: number; // Deprecated alias for maxRuntimeChars
591
- maxBatchedLlmQueryConcurrency?: number; // Max parallel batched llmQuery calls (default: 8)
592
- maxInterpreterOutputChars?: number; // Deprecated alias for maxRuntimeChars
593
- subModel?: string; // Model for llmQuery sub-calls
683
+ contextFields: string[]; // Input fields holding long context
684
+ runtime?: AxCodeRuntime; // Code runtime (default: AxJSRuntime)
685
+ maxLlmCalls?: number; // Cap on sub-LM calls (default: 50)
686
+ maxRuntimeChars?: number; // Cap for llmQuery context + code output (default: 5000)
687
+ maxBatchedLlmQueryConcurrency?: number; // Max parallel batched llmQuery calls (default: 8)
688
+ subModel?: string; // Model for llmQuery sub-calls
689
+ maxTurns?: number; // Max Actor turns before forcing Responder (default: 10)
690
+ actorFields?: string[]; // Output fields produced by Actor instead of Responder
691
+ actorCallback?: (result: Record<string, unknown>) => void | Promise<void>; // Called after each Actor turn
594
692
  }
595
693
  ```
596
694
 
@@ -598,7 +696,6 @@ interface AxRLMConfig {
598
696
 
599
697
  ```typescript
600
698
  interface AxCodeRuntime {
601
- readonly language: string;
602
699
  getUsageInstructions?(): string;
603
700
  createSession(globals?: Record<string, unknown>): AxCodeSession;
604
701
  }
@@ -632,10 +729,10 @@ Extends `AxProgramForwardOptions` (without `functions`) with:
632
729
 
633
730
  ```typescript
634
731
  {
635
- disableSmartModelRouting?: boolean;
636
- excludeFieldsFromPassthrough?: string[];
637
732
  debug?: boolean;
638
- rlm?: AxRLMConfig;
733
+ rlm: AxRLMConfig;
734
+ actorOptions?: Partial<AxProgramForwardOptions>; // Default forward options for Actor
735
+ responderOptions?: Partial<AxProgramForwardOptions>; // Default forward options for Responder
639
736
  }
640
737
  ```
641
738