@ax-llm/ax 18.0.0 → 18.0.2
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 +54 -54
- package/index.cjs.map +1 -1
- package/index.d.cts +23 -3
- package/index.d.ts +23 -3
- package/index.global.js +57 -57
- package/index.global.js.map +1 -1
- package/index.js +59 -59
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.mjs +38 -6
- package/skills/ax-agent.md +286 -111
- package/skills/ax-llm.md +479 -244
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -19,9 +19,10 @@ import {
|
|
|
19
19
|
mkdirSync,
|
|
20
20
|
readFileSync,
|
|
21
21
|
readdirSync,
|
|
22
|
+
rmSync,
|
|
22
23
|
writeFileSync,
|
|
23
24
|
} from 'node:fs';
|
|
24
|
-
import { dirname, join, sep } from 'node:path';
|
|
25
|
+
import { basename, dirname, join, sep } from 'node:path';
|
|
25
26
|
import { fileURLToPath } from 'node:url';
|
|
26
27
|
|
|
27
28
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -118,6 +119,20 @@ function getInstalledVersion(targetPath) {
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Get the skill name from YAML frontmatter, falling back to filename without .md
|
|
124
|
+
*/
|
|
125
|
+
function getSkillName(filePath) {
|
|
126
|
+
try {
|
|
127
|
+
const content = readFileSync(filePath, 'utf8');
|
|
128
|
+
const match = content.match(/^name:\s*["']?([^"'\n\r]+)/m);
|
|
129
|
+
if (match) return match[1].trim();
|
|
130
|
+
} catch {
|
|
131
|
+
// Fall through to fallback
|
|
132
|
+
}
|
|
133
|
+
return basename(filePath, '.md');
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
/**
|
|
122
137
|
* Get the package version from the skill source file
|
|
123
138
|
*/
|
|
@@ -173,7 +188,7 @@ function install() {
|
|
|
173
188
|
// Paths
|
|
174
189
|
const skillsSourceDir = join(__dirname, '..', 'skills');
|
|
175
190
|
const projectRoot = findProjectRoot();
|
|
176
|
-
const
|
|
191
|
+
const skillsBaseDir = join(projectRoot, '.claude', 'skills');
|
|
177
192
|
|
|
178
193
|
// Discover all *.md skill files
|
|
179
194
|
if (!existsSync(skillsSourceDir)) {
|
|
@@ -188,11 +203,28 @@ function install() {
|
|
|
188
203
|
return;
|
|
189
204
|
}
|
|
190
205
|
|
|
206
|
+
// Clean up legacy flat file structure (.claude/skills/ax/*.md except SKILL.md)
|
|
207
|
+
const legacyDir = join(skillsBaseDir, 'ax');
|
|
208
|
+
if (existsSync(legacyDir)) {
|
|
209
|
+
try {
|
|
210
|
+
const legacyFiles = readdirSync(legacyDir).filter(
|
|
211
|
+
(f) => f.endsWith('.md') && f !== 'SKILL.md'
|
|
212
|
+
);
|
|
213
|
+
for (const f of legacyFiles) {
|
|
214
|
+
rmSync(join(legacyDir, f), { force: true });
|
|
215
|
+
}
|
|
216
|
+
} catch {
|
|
217
|
+
// Ignore cleanup errors
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
191
221
|
const results = [];
|
|
192
222
|
|
|
193
223
|
for (const file of skillFiles) {
|
|
194
224
|
const skillSource = join(skillsSourceDir, file);
|
|
195
|
-
const
|
|
225
|
+
const skillName = getSkillName(skillSource);
|
|
226
|
+
const skillDir = join(skillsBaseDir, skillName);
|
|
227
|
+
const skillTarget = join(skillDir, 'SKILL.md');
|
|
196
228
|
|
|
197
229
|
const packageVersion = getPackageVersion(skillSource);
|
|
198
230
|
const installedVersion = getInstalledVersion(skillTarget);
|
|
@@ -218,13 +250,13 @@ function install() {
|
|
|
218
250
|
}
|
|
219
251
|
|
|
220
252
|
if (shouldInstallFile) {
|
|
221
|
-
if (!existsSync(
|
|
222
|
-
mkdirSync(
|
|
253
|
+
if (!existsSync(skillDir)) {
|
|
254
|
+
mkdirSync(skillDir, { recursive: true });
|
|
223
255
|
}
|
|
224
256
|
|
|
225
257
|
const content = readFileSync(skillSource, 'utf8');
|
|
226
258
|
writeFileSync(skillTarget, content, 'utf8');
|
|
227
|
-
results.push({ file, action, versionInfo });
|
|
259
|
+
results.push({ file: skillName, action, versionInfo });
|
|
228
260
|
}
|
|
229
261
|
}
|
|
230
262
|
|
package/skills/ax-agent.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ax-agent
|
|
3
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.
|
|
4
|
+
version: "18.0.2"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# AxAgent Guide (@ax-llm/ax)
|
|
@@ -11,15 +11,23 @@ AxAgent is the agent framework in Ax. It wraps AxGen with support for child agen
|
|
|
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
|
+
agentIdentity: {
|
|
26
|
+
name: 'helpfulAgent',
|
|
27
|
+
description: 'An agent that provides helpful responses to user questions',
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
);
|
|
23
31
|
|
|
24
32
|
const result = await myAgent.forward(llm, { userQuestion: 'What is TypeScript?' });
|
|
25
33
|
console.log(result.responseText);
|
|
@@ -33,70 +41,65 @@ for await (const chunk of stream) {
|
|
|
33
41
|
|
|
34
42
|
## Creating Agents
|
|
35
43
|
|
|
36
|
-
Use the `agent()` factory function with a
|
|
44
|
+
Use the `agent()` factory function with a signature built using `f()`:
|
|
37
45
|
|
|
38
46
|
```typescript
|
|
39
|
-
import { agent, ai } from '@ax-llm/ax';
|
|
47
|
+
import { agent, ai, f } from '@ax-llm/ax';
|
|
40
48
|
|
|
41
49
|
const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! });
|
|
42
50
|
|
|
43
|
-
const myAgent = agent(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const myAgent = agent(
|
|
52
|
+
f()
|
|
53
|
+
.input('userQuestion', f.string())
|
|
54
|
+
.output('responseText', f.string())
|
|
55
|
+
.build(),
|
|
56
|
+
{
|
|
57
|
+
agentIdentity: {
|
|
58
|
+
name: 'helpfulAgent',
|
|
59
|
+
description: 'An agent that provides helpful responses to user questions',
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
);
|
|
47
63
|
|
|
48
64
|
const result = await myAgent.forward(llm, { userQuestion: 'What is TypeScript?' });
|
|
49
65
|
console.log(result.responseText);
|
|
50
66
|
```
|
|
51
67
|
|
|
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
68
|
## Agent Options
|
|
65
69
|
|
|
66
70
|
The `agent()` factory accepts a configuration object:
|
|
67
71
|
|
|
68
72
|
```typescript
|
|
69
|
-
const myAgent = agent(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
maxRetries: 3, // Retries on assertion failures
|
|
81
|
-
temperature: 0.7, // Sampling temperature
|
|
82
|
-
debug: false, // Debug logging
|
|
83
|
-
|
|
84
|
-
// RLM mode (see RLM section below)
|
|
85
|
-
rlm: { ... },
|
|
86
|
-
});
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### `name`
|
|
90
|
-
|
|
91
|
-
The agent's name, used as the function name when called as a child agent. Minimum 5 characters. Converted to camelCase automatically (e.g. `'Physics Researcher'` becomes `physicsResearcher`).
|
|
92
|
-
|
|
93
|
-
### `description`
|
|
73
|
+
const myAgent = agent(
|
|
74
|
+
f()
|
|
75
|
+
.input('input', f.string())
|
|
76
|
+
.output('output', f.string())
|
|
77
|
+
.build(),
|
|
78
|
+
{
|
|
79
|
+
// Agent identity (required when used as a child agent)
|
|
80
|
+
agentIdentity: {
|
|
81
|
+
name: 'myAgent', // Agent name (converted to camelCase)
|
|
82
|
+
description: 'Does something useful and interesting with inputs',
|
|
83
|
+
},
|
|
94
84
|
|
|
95
|
-
|
|
85
|
+
// Optional
|
|
86
|
+
ai: llm, // Bind a specific AI service
|
|
87
|
+
functions: [searchTool, calcTool], // Tool functions
|
|
88
|
+
agents: [childAgent1, childAgent2], // Child agents
|
|
89
|
+
maxSteps: 25, // Max reasoning steps (default: 25)
|
|
90
|
+
maxRetries: 3, // Retries on assertion failures
|
|
91
|
+
temperature: 0.7, // Sampling temperature
|
|
92
|
+
debug: false, // Debug logging
|
|
93
|
+
|
|
94
|
+
// RLM mode (see RLM section below)
|
|
95
|
+
rlm: { ... },
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
```
|
|
96
99
|
|
|
97
|
-
### `
|
|
100
|
+
### `agentIdentity`
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
Required when the agent is used as a child agent. Contains `name` (converted to camelCase for the function name, e.g. `'Physics Researcher'` becomes `physicsResearcher`) and `description` (shown to parent agents when they decide which child to call).
|
|
100
103
|
|
|
101
104
|
### `functions`
|
|
102
105
|
|
|
@@ -120,11 +123,19 @@ console.log(result.responseText);
|
|
|
120
123
|
If the agent was created with `ai` bound, the parent AI is used as fallback:
|
|
121
124
|
|
|
122
125
|
```typescript
|
|
123
|
-
const myAgent = agent(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
const myAgent = agent(
|
|
127
|
+
f()
|
|
128
|
+
.input('input', f.string())
|
|
129
|
+
.output('output', f.string())
|
|
130
|
+
.build(),
|
|
131
|
+
{
|
|
132
|
+
agentIdentity: {
|
|
133
|
+
name: 'myAgent',
|
|
134
|
+
description: 'An agent that processes inputs reliably',
|
|
135
|
+
},
|
|
136
|
+
ai: llm,
|
|
137
|
+
}
|
|
138
|
+
);
|
|
128
139
|
|
|
129
140
|
// Can also pass a different AI to override
|
|
130
141
|
const result = await myAgent.forward(differentLlm, { input: 'test' });
|
|
@@ -168,10 +179,18 @@ const result = await myAgent.forward(llm, values, {
|
|
|
168
179
|
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):
|
|
169
180
|
|
|
170
181
|
```typescript
|
|
171
|
-
const myAgent = agent(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
const myAgent = agent(
|
|
183
|
+
f()
|
|
184
|
+
.input('question', f.string())
|
|
185
|
+
.output('answer', f.string())
|
|
186
|
+
.build(),
|
|
187
|
+
{
|
|
188
|
+
agentIdentity: {
|
|
189
|
+
name: 'myAgent',
|
|
190
|
+
description: 'An agent that answers questions thoroughly',
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
);
|
|
175
194
|
|
|
176
195
|
const timer = setTimeout(() => myAgent.stop(), 5_000);
|
|
177
196
|
|
|
@@ -192,7 +211,12 @@ try {
|
|
|
192
211
|
`stop()` is also available on `AxGen` and `AxFlow` instances:
|
|
193
212
|
|
|
194
213
|
```typescript
|
|
195
|
-
const gen = ax(
|
|
214
|
+
const gen = ax(
|
|
215
|
+
f()
|
|
216
|
+
.input('topic', f.string())
|
|
217
|
+
.output('summary', f.string())
|
|
218
|
+
.build()
|
|
219
|
+
);
|
|
196
220
|
setTimeout(() => gen.stop(), 3_000);
|
|
197
221
|
|
|
198
222
|
try {
|
|
@@ -240,7 +264,7 @@ try {
|
|
|
240
264
|
Define tool functions with a name, description, JSON Schema parameters, and implementation:
|
|
241
265
|
|
|
242
266
|
```typescript
|
|
243
|
-
import { ai, agent } from '@ax-llm/ax';
|
|
267
|
+
import { ai, agent, f } from '@ax-llm/ax';
|
|
244
268
|
|
|
245
269
|
const getCurrentWeather = {
|
|
246
270
|
name: 'getCurrentWeather',
|
|
@@ -258,11 +282,19 @@ const getCurrentWeather = {
|
|
|
258
282
|
}
|
|
259
283
|
};
|
|
260
284
|
|
|
261
|
-
const weatherAgent = agent(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
285
|
+
const weatherAgent = agent(
|
|
286
|
+
f()
|
|
287
|
+
.input('query', f.string())
|
|
288
|
+
.output('response', f.string())
|
|
289
|
+
.build(),
|
|
290
|
+
{
|
|
291
|
+
agentIdentity: {
|
|
292
|
+
name: 'weatherAssistant',
|
|
293
|
+
description: 'An assistant that helps with weather queries',
|
|
294
|
+
},
|
|
295
|
+
functions: [getCurrentWeather]
|
|
296
|
+
}
|
|
297
|
+
);
|
|
266
298
|
|
|
267
299
|
const llm = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! });
|
|
268
300
|
const result = await weatherAgent.forward(llm, { query: 'Weather in Tokyo?' });
|
|
@@ -274,27 +306,47 @@ Agents can compose other agents as children. The parent agent sees each child as
|
|
|
274
306
|
|
|
275
307
|
```typescript
|
|
276
308
|
const researcher = agent(
|
|
277
|
-
|
|
309
|
+
f()
|
|
310
|
+
.input('question', f.string())
|
|
311
|
+
.input('physicsQuestion', f.string())
|
|
312
|
+
.output('answer', f.string())
|
|
313
|
+
.build(),
|
|
278
314
|
{
|
|
279
|
-
|
|
280
|
-
|
|
315
|
+
agentIdentity: {
|
|
316
|
+
name: 'Physics Researcher',
|
|
317
|
+
description: 'Researcher for physics questions can answer questions about advanced physics',
|
|
318
|
+
},
|
|
281
319
|
}
|
|
282
320
|
);
|
|
283
321
|
|
|
284
322
|
const summarizer = agent(
|
|
285
|
-
|
|
323
|
+
f()
|
|
324
|
+
.input('answer', f.string())
|
|
325
|
+
.output('shortSummary', f.string())
|
|
326
|
+
.build(),
|
|
286
327
|
{
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
328
|
+
agentIdentity: {
|
|
329
|
+
name: 'Science Summarizer',
|
|
330
|
+
description: 'Summarizer can write short summaries of advanced science topics',
|
|
331
|
+
},
|
|
290
332
|
}
|
|
291
333
|
);
|
|
292
334
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
335
|
+
summarizer.setActorDescription('You are a science summarizer. You can write short summaries of advanced science topics. Use numbered bullet points to summarize the answer in order of importance.');
|
|
336
|
+
|
|
337
|
+
const scientist = agent(
|
|
338
|
+
f()
|
|
339
|
+
.input('question', f.string())
|
|
340
|
+
.output('answer', f.string())
|
|
341
|
+
.build(),
|
|
342
|
+
{
|
|
343
|
+
agentIdentity: {
|
|
344
|
+
name: 'Scientist',
|
|
345
|
+
description: 'An agent that can answer advanced science questions',
|
|
346
|
+
},
|
|
347
|
+
agents: [researcher, summarizer],
|
|
348
|
+
}
|
|
349
|
+
);
|
|
298
350
|
|
|
299
351
|
const result = await scientist.forward(llm, {
|
|
300
352
|
question: 'Why is gravity not a real force?',
|
|
@@ -326,13 +378,20 @@ The Actor writes JavaScript code to inspect, filter, and iterate over the docume
|
|
|
326
378
|
### Configuration
|
|
327
379
|
|
|
328
380
|
```typescript
|
|
329
|
-
import { agent, ai } from '@ax-llm/ax';
|
|
381
|
+
import { agent, ai, f } from '@ax-llm/ax';
|
|
330
382
|
|
|
331
383
|
const analyzer = agent(
|
|
332
|
-
|
|
384
|
+
f()
|
|
385
|
+
.input('context', f.string())
|
|
386
|
+
.input('query', f.string())
|
|
387
|
+
.output('answer', f.string())
|
|
388
|
+
.output('evidence', f.string().array())
|
|
389
|
+
.build(),
|
|
333
390
|
{
|
|
334
|
-
|
|
335
|
-
|
|
391
|
+
agentIdentity: {
|
|
392
|
+
name: 'documentAnalyzer',
|
|
393
|
+
description: 'Analyzes long documents using code interpreter and sub-LM queries',
|
|
394
|
+
},
|
|
336
395
|
rlm: {
|
|
337
396
|
contextFields: ['context'], // Fields to load into runtime session
|
|
338
397
|
runtime: new AxJSRuntime(), // Code runtime (default: AxJSRuntime)
|
|
@@ -383,19 +442,25 @@ Available permissions:
|
|
|
383
442
|
Context fields aren't limited to plain strings. You can pass structured data — objects and arrays with typed sub-fields:
|
|
384
443
|
|
|
385
444
|
```typescript
|
|
386
|
-
import { agent, f
|
|
445
|
+
import { agent, f } from '@ax-llm/ax';
|
|
387
446
|
import { AxJSRuntime } from '@ax-llm/ax';
|
|
388
447
|
|
|
389
|
-
const sig =
|
|
390
|
-
.
|
|
448
|
+
const sig = f()
|
|
449
|
+
.input('query', f.string())
|
|
450
|
+
.input('documents', f.object({
|
|
391
451
|
id: f.number('Document ID'),
|
|
392
452
|
title: f.string('Document title'),
|
|
393
453
|
content: f.string('Document body'),
|
|
394
|
-
}).array('Source documents'))
|
|
454
|
+
}).array('Source documents'))
|
|
455
|
+
.output('answer', f.string())
|
|
456
|
+
.output('evidence', f.string().array())
|
|
457
|
+
.build();
|
|
395
458
|
|
|
396
459
|
const analyzer = agent(sig, {
|
|
397
|
-
|
|
398
|
-
|
|
460
|
+
agentIdentity: {
|
|
461
|
+
name: 'structuredAnalyzer',
|
|
462
|
+
description: 'Analyzes structured document collections using RLM',
|
|
463
|
+
},
|
|
399
464
|
rlm: {
|
|
400
465
|
contextFields: ['documents'],
|
|
401
466
|
runtime: new AxJSRuntime(),
|
|
@@ -448,8 +513,17 @@ By default, all output fields from the signature go to the Responder. Use `actor
|
|
|
448
513
|
|
|
449
514
|
```typescript
|
|
450
515
|
const analyzer = agent(
|
|
451
|
-
|
|
516
|
+
f()
|
|
517
|
+
.input('context', f.string())
|
|
518
|
+
.input('query', f.string())
|
|
519
|
+
.output('answer', f.string())
|
|
520
|
+
.output('reasoning', f.string())
|
|
521
|
+
.build(),
|
|
452
522
|
{
|
|
523
|
+
agentIdentity: {
|
|
524
|
+
name: 'reasoningAnalyzer',
|
|
525
|
+
description: 'Analyzes context with explicit reasoning steps',
|
|
526
|
+
},
|
|
453
527
|
rlm: {
|
|
454
528
|
contextFields: ['context'],
|
|
455
529
|
actorFields: ['reasoning'], // Actor produces 'reasoning', Responder produces 'answer'
|
|
@@ -463,14 +537,25 @@ const analyzer = agent(
|
|
|
463
537
|
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.
|
|
464
538
|
|
|
465
539
|
```typescript
|
|
466
|
-
const analyzer = agent(
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
540
|
+
const analyzer = agent(
|
|
541
|
+
f()
|
|
542
|
+
.input('context', f.string())
|
|
543
|
+
.input('query', f.string())
|
|
544
|
+
.output('answer', f.string())
|
|
545
|
+
.build(),
|
|
546
|
+
{
|
|
547
|
+
agentIdentity: {
|
|
548
|
+
name: 'callbackAnalyzer',
|
|
549
|
+
description: 'Analyzes context with observable actor turns',
|
|
471
550
|
},
|
|
472
|
-
|
|
473
|
-
|
|
551
|
+
rlm: {
|
|
552
|
+
contextFields: ['context'],
|
|
553
|
+
actorCallback: async (result) => {
|
|
554
|
+
console.log('Actor code:', result.javascriptCode);
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
}
|
|
558
|
+
);
|
|
474
559
|
```
|
|
475
560
|
|
|
476
561
|
### Actor/Responder Forward Options
|
|
@@ -478,20 +563,96 @@ const analyzer = agent('context:string, query:string -> answer:string', {
|
|
|
478
563
|
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.
|
|
479
564
|
|
|
480
565
|
```typescript
|
|
481
|
-
const analyzer = agent(
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
566
|
+
const analyzer = agent(
|
|
567
|
+
f()
|
|
568
|
+
.input('context', f.string())
|
|
569
|
+
.input('query', f.string())
|
|
570
|
+
.output('answer', f.string())
|
|
571
|
+
.build(),
|
|
572
|
+
{
|
|
573
|
+
agentIdentity: {
|
|
574
|
+
name: 'dualModelAnalyzer',
|
|
575
|
+
description: 'Analyzes context using different models for actor and responder',
|
|
576
|
+
},
|
|
577
|
+
rlm: { contextFields: ['context'] },
|
|
578
|
+
actorOptions: {
|
|
579
|
+
model: 'fast-model',
|
|
580
|
+
thinkingTokenBudget: 1024,
|
|
581
|
+
},
|
|
582
|
+
responderOptions: {
|
|
583
|
+
model: 'smart-model',
|
|
584
|
+
thinkingTokenBudget: 4096,
|
|
585
|
+
},
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Priority order (low to high): constructor base options < `actorOptions`/`responderOptions` < forward-time options.
|
|
591
|
+
|
|
592
|
+
### Actor/Responder Descriptions
|
|
593
|
+
|
|
594
|
+
Use `setActorDescription()` and `setResponderDescription()` to append additional instructions to the Actor or Responder system prompts. The base RLM prompts are preserved; your text is appended after them.
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
const analyzer = agent(
|
|
598
|
+
f()
|
|
599
|
+
.input('context', f.string())
|
|
600
|
+
.input('query', f.string())
|
|
601
|
+
.output('answer', f.string())
|
|
602
|
+
.build(),
|
|
603
|
+
{
|
|
604
|
+
agentIdentity: {
|
|
605
|
+
name: 'customAnalyzer',
|
|
606
|
+
description: 'Analyzes context with custom actor and responder instructions',
|
|
607
|
+
},
|
|
608
|
+
rlm: { contextFields: ['context'] },
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
// Add domain-specific instructions to the Actor (code generation agent)
|
|
613
|
+
analyzer.setActorDescription('Focus on numerical data. Use precise calculations.');
|
|
614
|
+
|
|
615
|
+
// Add domain-specific instructions to the Responder (answer synthesis agent)
|
|
616
|
+
analyzer.setResponderDescription('Format answers as bullet points. Cite evidence.');
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
> **Note:** Signature-level descriptions (via `.description()` on the signature) are not supported on `AxAgent`. Use these methods instead to customize each sub-program independently.
|
|
620
|
+
|
|
621
|
+
### Few-Shot Demos
|
|
622
|
+
|
|
623
|
+
Use `setDemos()` to provide few-shot examples that guide the Actor and Responder. Demos are keyed by program ID — use `namedPrograms()` to discover available IDs.
|
|
624
|
+
|
|
625
|
+
Each demo trace must include at least one input field AND one output field. The Actor's input fields are `contextMetadata`, `actionLog`, and any non-context inputs from the original signature. The Responder's input fields are the same.
|
|
626
|
+
|
|
627
|
+
```typescript
|
|
628
|
+
analyzer.setDemos([
|
|
629
|
+
{
|
|
630
|
+
programId: 'root.actor',
|
|
631
|
+
traces: [
|
|
632
|
+
{
|
|
633
|
+
actionLog: '(no actions yet)',
|
|
634
|
+
javascriptCode: 'console.log(context.slice(0, 200))',
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
actionLog: 'Step 1 | console.log(context.slice(0, 200))\n→ Chapter 1: ...',
|
|
638
|
+
javascriptCode: 'done()',
|
|
639
|
+
},
|
|
640
|
+
],
|
|
486
641
|
},
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
642
|
+
{
|
|
643
|
+
programId: 'root.responder',
|
|
644
|
+
traces: [
|
|
645
|
+
{
|
|
646
|
+
query: 'What are the main arguments?',
|
|
647
|
+
answer: 'The document presents arguments about distributed systems.',
|
|
648
|
+
evidence: ['Chapter 1 discusses scalability'],
|
|
649
|
+
},
|
|
650
|
+
],
|
|
490
651
|
},
|
|
491
|
-
|
|
652
|
+
]);
|
|
492
653
|
```
|
|
493
654
|
|
|
494
|
-
|
|
655
|
+
Demo values are validated against the target program's signature. Invalid values or missing input/output fields throw an error at `setDemos()` time.
|
|
495
656
|
|
|
496
657
|
### Available APIs in the Sandbox
|
|
497
658
|
|
|
@@ -639,9 +800,7 @@ interface AxCodeSession {
|
|
|
639
800
|
```typescript
|
|
640
801
|
interface AxAgentConfig<IN, OUT> extends AxAgentOptions {
|
|
641
802
|
ai?: AxAIService;
|
|
642
|
-
name: string;
|
|
643
|
-
description: string;
|
|
644
|
-
definition?: string;
|
|
803
|
+
agentIdentity?: { name: string; description: string };
|
|
645
804
|
agents?: AxAgentic<IN, OUT>[];
|
|
646
805
|
functions?: AxInputFunctionType;
|
|
647
806
|
}
|
|
@@ -660,6 +819,22 @@ Extends `AxProgramForwardOptions` (without `functions`) with:
|
|
|
660
819
|
}
|
|
661
820
|
```
|
|
662
821
|
|
|
822
|
+
### `setActorDescription()`
|
|
823
|
+
|
|
824
|
+
```typescript
|
|
825
|
+
public setActorDescription(additionalText: string): void
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
Appends additional text to the Actor's RLM system prompt. The base prompt is preserved; the additional text is appended after it.
|
|
829
|
+
|
|
830
|
+
### `setResponderDescription()`
|
|
831
|
+
|
|
832
|
+
```typescript
|
|
833
|
+
public setResponderDescription(additionalText: string): void
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
Appends additional text to the Responder's RLM system prompt. The base prompt is preserved; the additional text is appended after it.
|
|
837
|
+
|
|
663
838
|
### `stop()`
|
|
664
839
|
|
|
665
840
|
```typescript
|