@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ax-llm/ax",
3
- "version": "18.0.0",
3
+ "version": "18.0.2",
4
4
  "type": "module",
5
5
  "description": "The best library to work with LLMs",
6
6
  "repository": {
@@ -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 skillTargetDir = join(projectRoot, '.claude', 'skills', 'ax');
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 skillTarget = join(skillTargetDir, file);
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(skillTargetDir)) {
222
- mkdirSync(skillTargetDir, { recursive: true });
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
 
@@ -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.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('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
+ 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 string signature:
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('userQuestion:string -> responseText:string', {
44
- name: 'helpfulAgent',
45
- description: 'An agent that provides helpful responses to user questions',
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('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
- 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
- A short description of what the agent does. Minimum 20 characters. This is shown to parent agents when they decide which child to call.
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
- ### `definition`
100
+ ### `agentIdentity`
98
101
 
99
- An optional detailed system prompt for the LLM. Minimum 100 characters if provided. If omitted, the `description` is used as the prompt.
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('input:string -> output:string', {
124
- name: 'myAgent',
125
- description: 'An agent that processes inputs reliably',
126
- ai: llm,
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('question:string -> answer:string', {
172
- name: 'myAgent',
173
- description: 'An agent that answers questions thoroughly',
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('topic:string -> summary:string');
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('query:string -> response:string', {
262
- name: 'weatherAssistant',
263
- description: 'An assistant that helps with weather queries',
264
- functions: [getCurrentWeather]
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
- 'question:string, physicsQuestion:string -> answer:string',
309
+ f()
310
+ .input('question', f.string())
311
+ .input('physicsQuestion', f.string())
312
+ .output('answer', f.string())
313
+ .build(),
278
314
  {
279
- name: 'Physics Researcher',
280
- description: 'Researcher for physics questions can answer questions about advanced physics',
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
- 'answer:string -> shortSummary:string',
323
+ f()
324
+ .input('answer', f.string())
325
+ .output('shortSummary', f.string())
326
+ .build(),
286
327
  {
287
- name: 'Science Summarizer',
288
- description: 'Summarizer can write short summaries of advanced science topics',
289
- definition: '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.',
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
- const scientist = agent('question:string -> answer:string', {
294
- name: 'Scientist',
295
- description: 'An agent that can answer advanced science questions',
296
- agents: [researcher, summarizer],
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
- 'context:string, query:string -> answer:string, evidence:string[]',
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
- name: 'documentAnalyzer',
335
- description: 'Analyzes long documents using code interpreter and sub-LM queries',
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, s } from '@ax-llm/ax';
445
+ import { agent, f } from '@ax-llm/ax';
387
446
  import { AxJSRuntime } from '@ax-llm/ax';
388
447
 
389
- const sig = s('query:string -> answer:string, evidence:string[]')
390
- .appendInputField('documents', f.object({
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
- name: 'structuredAnalyzer',
398
- description: 'Analyzes structured document collections using RLM',
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
- 'context:string, query:string -> answer:string, reasoning:string',
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('context:string, query:string -> answer:string', {
467
- rlm: {
468
- contextFields: ['context'],
469
- actorCallback: async (result) => {
470
- console.log('Actor code:', result.javascriptCode);
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('context:string, query:string -> answer:string', {
482
- rlm: { contextFields: ['context'] },
483
- actorOptions: {
484
- model: 'fast-model',
485
- thinkingTokenBudget: 1024,
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
- responderOptions: {
488
- model: 'smart-model',
489
- thinkingTokenBudget: 4096,
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
- Priority order (low to high): constructor base options < `actorOptions`/`responderOptions` < forward-time options.
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