@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.
- package/cli/index.mjs +85 -37
- package/index.cjs +205 -274
- package/index.cjs.map +1 -1
- package/index.d.cts +169 -192
- package/index.d.ts +169 -192
- package/index.global.js +207 -276
- package/index.global.js.map +1 -1
- package/index.js +207 -276
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.mjs +64 -9
- package/skills/ax-agent.md +248 -151
- package/skills/ax-llm.md +479 -244
package/skills/ax-agent.md
CHANGED
|
@@ -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,
|
|
4
|
-
version: "
|
|
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,
|
|
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(
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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(
|
|
44
|
-
|
|
45
|
-
|
|
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(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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(
|
|
174
|
-
|
|
175
|
-
|
|
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(
|
|
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(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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. **
|
|
352
|
-
-
|
|
353
|
-
-
|
|
354
|
-
3. **Sub-LM queries** —
|
|
355
|
-
4. **
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
|
433
|
+
import { agent, f } from '@ax-llm/ax';
|
|
418
434
|
import { AxJSRuntime } from '@ax-llm/ax';
|
|
419
435
|
|
|
420
|
-
const sig =
|
|
421
|
-
.
|
|
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
|
|
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
|
-
|
|
496
|
+
### Actor Fields
|
|
460
497
|
|
|
461
|
-
|
|
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
|
-
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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
|
|
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
|
|