This skill helps an LLM generate correct core AxAgent code using @ax-llm/ax. Use when the user asks about agent(), child agents, namespaced functions, discovery mode, clarification, bubbleErrors, host-side final/clarification protocol, or ordinary agent runtime behavior. For MCP clients, native runtime modules, subscriptions, tasks, or authentication use ax-mcp alongside this skill. For RLM/code-runtime work use ax-agent-rlm; for callbacks and telemetry use ax-agent-observability; for recall/...
Scanned 9/4/2026
Install to Claude Code
npx -y skills add ax-llm/ax --skill ax-agent --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ax Agent?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/ax-llm-ax-agent)More formats (shields.io, HTML) on the badges page.
---
name: ax-agent
description: This skill helps an LLM generate correct core AxAgent code using @ax-llm/ax. Use when the user asks about agent(), child agents, namespaced functions, discovery mode, clarification, bubbleErrors, host-side final/clarification protocol, or ordinary agent runtime behavior. For MCP clients, native runtime modules, subscriptions, tasks, or authentication use ax-mcp alongside this skill. For RLM/code-runtime work use ax-agent-rlm; for callbacks and telemetry use ax-agent-observability; for recall/memory/skill loading use ax-agent-memory-skills; for agent.optimize(...) use ax-agent-optimize.
version: "24.0.16"
---
# AxAgent Codegen Rules (@ax-llm/ax)
Use this skill to generate small, correct `AxAgent` code. Prefer modern factory-style APIs and copyable patterns. Do not write tutorial prose unless the user explicitly asks for explanation.
Your job is to choose the smallest correct `AxAgent` shape for the user's needs:
- If the user wants a normal tool-using assistant, keep the config minimal.
- If the user wants long-running code execution, use the `ax-agent-rlm` skill.
- If the user wants callbacks, logs, tracing, or usage data, use the `ax-agent-observability` skill.
- If the user wants dynamic memory retrieval or skill-guide loading, use the `ax-agent-memory-skills` skill.
- If the user wants tuning or eval with `agent.optimize(...)`, use the `ax-agent-optimize` skill.
- If the user wants MCP transports, authentication, catalogs, subscriptions,
tasks, Apps, or event-driven wake/resume, use the `ax-mcp` skill.
## Use These Defaults
- Use `agent(...)`, not `new AxAgent(...)`.
- Prefer string signatures or `f()` signatures over hand-written signature objects.
- Put `ai`, `judgeAI`, and `agentIdentity` on the `agent(...)` config when you want instance defaults or child-agent metadata.
- Prefer `fn(...)` for host-side function definitions instead of hand-writing JSON Schema objects.
- Prefer namespaced functions such as `utils.search(...)` or `kb.find(...)`.
- Pass child agents directly in `functions: [...]`. They land under their `agentIdentity.namespace` (or `utils` if unset), exactly like a `fn()` tool.
- If discovery is enabled, call `discover(...)` before using callables whose docs are not already in the prompt.
- Use explicit child agents in `functions: [...]` for specialist delegation; do not model that as recursive `llmQuery(...)`.
- Add `bubbleErrors` only for fatal infrastructure errors that should abort `.forward()`.
## Decision Guide
Map user intent to agent shape before writing code:
- "Use tools and answer" -> plain `agent(...)` with local functions, no extra observability.
- "Need child agents with distinct responsibilities" -> add child agents to the parent's `functions: [...]` list and set each child's `agentIdentity.namespace` when you want a specific runtime call site such as `team.writer(...)`.
- "Need tool discovery because names/schemas are not stable" -> enable discovery and generate discovery-first actor code.
- "Need certain errors to escape the agent loop" -> add `bubbleErrors` with error classes; those errors propagate through function handlers, actor code, and `llmQuery(...)` sub-queries to `.forward()`.
- "Inspect large context with code", "RLM", or "`llmQuery(...)`" -> use `ax-agent-rlm`.
- "Need debugging, traces, progress updates, tool-call logs, chat logs, or usage" -> use `ax-agent-observability`.
- "Need memories, recall, dynamic skill guides, `discover({ skills })`, or loaded/used tracking" -> use `ax-agent-memory-skills`.
## Critical Rules
- Use `agent(...)` factory syntax for new code.
- If an actor response contains multiple fenced code blocks, the runtime rejects the whole turn without executing any block and asks for one executable program.
- Add child agents to the parent's `functions: [...]` list. Each child's `agentIdentity.namespace` (or `utils`, the default) determines the runtime call site, e.g. `await team.writer({...})`.
- If discovery is enabled, call `discover(...)` before using callables whose docs are not already in the prompt.
- `autoUpgrade` is ON by default: large tool catalogs auto-enable discovery, and oversized undeclared input values are auto-kept runtime-only with a truncated prompt preview. Explicit `functionDiscovery` and declared `contextFields` always win; set `autoUpgrade: false` to opt out.
- `directResponse` is ON by default (`'auto'`): when a task needs no executor authority, the distiller ends the run with `respond(task, evidence)` and the executor stage is skipped (zero executor model calls). Static agents with no functions, child agents, or native MCP/UCP operations run respond-only every time. Agents with any of those authorities retain the executor and offer `respond` under a conservative covenant (no live/fresh-state asks, no side effects, nothing a listed function/module domain covers). Set `directResponse: 'off'` to always run the executor.
- If a host-side `AxAgentFunction` needs to end the current actor turn, use `extra.protocol.final(...)` or `extra.protocol.askClarification(...)`.
- In public `forward()` and `streamingForward()` flows, `askClarification(...)` throws `AxAgentClarificationError`; it does not go through the responder.
- When resuming after clarification, prefer `error.getState()` from the thrown `AxAgentClarificationError`, then call `agent.setState(savedState)` before the next `forward(...)`.
- Errors listed in `bubbleErrors` bypass actor-loop catch blocks and propagate directly to the caller of `.forward()`.
- Child agents receive only the arguments the actor passes. Pass parent fields explicitly via `inputs.<field>` or use `inputUpdateCallback` when many calls need the same value.
- Audio input fields are transcribed before agent planner/executor/responder stages by default; internal agent stages receive text transcripts, not base64 audio.
- Actor code stages force structured generation around the exact `javascriptCode` wire key. Native-capable providers keep strict `json_schema`; providers such as DeepSeek use validated `json_object` and do not need provider-visible tools for runtime execution.
- In generated Go, Python, Java, C++, and Rust packages, distiller/executor validation uses `validation_retries` with one correction attempt by default. Set it to `0` to fail on the first invalid response.
## Canonical Pattern
```typescript
import { agent, ai, f } from '@ax-llm/ax';
const llm = ai({
name: 'openai',
apiKey: process.env.OPENAI_APIKEY!,
});
const assistant = agent(
f()
.input('query', f.string())
.output('answer', f.string())
.build(),
{
agentIdentity: {
name: 'Assistant',
description: 'Answers user questions',
},
contextFields: [],
}
);
const result = await assistant.forward(llm, { query: 'What is TypeScript?' });
console.log(result.answer);
```
## Audio Inputs And Speech Outputs
Agents can accept audio inputs and return scripted speech artifacts. The runtime transcribes audio input fields before internal stages run, then synthesizes `:audio` outputs after the final structured response is selected.
```typescript
const voiceAgent = agent(
'recording:audio, question:string -> speech:audio, summary:string',
{
agentIdentity: {
name: 'Voice Assistant',
description: 'Answers spoken requests',
},
contextFields: [],
}
);
const result = await voiceAgent.forward(
llm,
{
recording: { data: base64Wav, format: 'wav' },
question: 'What should I do next?',
},
{
speech: {
transcribe: { model: 'gpt-4o-mini-transcribe' },
speak: { voice: 'alloy', format: 'mp3' },
},
}
);
console.log(result.summary);
console.log(result.speech.data);
```
Use direct `ax(...)` or `.chat()` if the model should receive native audio instead of a transcript-first agent pipeline.
## Child Agents As Tools
Child agents are passed in the parent's `functions` list. There is no separate `agents` option for new code. Each child agent's `agentIdentity.namespace` (or `utils`, the default) determines where it lands in the actor runtime. With `AxJSRuntime`, that produces JavaScript call sites such as `team.writer(...)`:
```typescript
const writer = agent('draft:string -> revision:string', {
agentIdentity: {
name: 'Writer',
description: 'Polishes drafts',
namespace: 'team',
},
contextFields: [],
});
const coordinator = agent('query:string -> answer:string', {
functions: [writer],
contextFields: [],
});
```
Generated runtime call:
```javascript
const result = await team.writer({ draft: '...' });
```
Without `agentIdentity.namespace`, the child lands under `utils.<name>` like any other tool:
```javascript
const result = await utils.writer({ draft: '...' });
```
Rules:
- Add child agents to `functions: [...]`, the same array as `fn(...)` tools.
- Set `agentIdentity.namespace` on the child to control its runtime call site.
- `onFunctionCall` observers receive `kind: 'internal'` for agent-derived calls and `kind: 'external'` for user-registered tools.
### Reserved namespace names
The agent runtime injects a fixed set of globals into the runtime session. These names cannot be used as `agentIdentity.namespace` values or as agent-function namespaces.
```text
inputs
llmQuery
final
askClarification
reportSuccess
reportFailure
inspectRuntime
discover
recall
```
Pick any other lowercase identifier such as `utils`, `kb`, `tools`, `team`, or `db`.
## Tool Functions And Namespaces
```typescript
import { agent, f, fn } from '@ax-llm/ax';
const findSnippets = fn('findSnippets')
.description('Find handbook snippets by topic')
.namespace('kb')
.arg('topic', f.string('Topic keyword'))
.returns(f.string('Matching snippet').array())
.example({
title: 'Find severity guidance',
code: 'await kb.findSnippets({ topic: "severity" });',
})
.handler(async ({ topic }) => [])
.build();
const analyst = agent('query:string -> answer:string', {
functions: [findSnippets],
contextFields: [],
});
```
Generated runtime call:
```javascript
const snippets = await kb.findSnippets({ topic: 'severity' });
```
Rules:
- Prefer namespaced functions.
- Default function namespace is `utils` when no namespace is set.
- With `AxJSRuntime`, use the runtime call shape `await <namespace>.<name>({...})`. Custom runtimes should expose equivalent namespaced calls through their own `formatCallable()` guidance.
- `.arg()` and `.returns()` can use Ax field helpers or any Standard Schema v1 validator directly.
## Grouped Function Modules
For discovery mode, group functions into modules using the `AxAgentFunctionGroup` shape when you want a clean namespace tree such as `kb.find(...)` or `metrics.score(...)` without setting `namespace` on every individual `fn(...)`:
```typescript
const parent = agent('query:string -> answer:string', {
functions: [
{
namespace: 'kb',
title: 'Knowledge Base',
selectionCriteria: 'Use for handbook and documentation lookups.',
description: 'Knowledge base lookups',
functions: [findSnippetsFn, searchPagesFn],
},
{
namespace: 'workflow',
title: 'Workflow Controls',
description: 'Small control functions the actor should always see',
alwaysInclude: true,
functions: [completeFn],
},
],
functionDiscovery: true,
contextFields: [],
});
```
Attach MCP/UCP clients through the native execution context. Ax initializes them once, exposes `mcp.<namespace>` / `ucp.<namespace>` runtime modules, and propagates them through actor stages, `llmQuery`, RLM, and child agents:
Use `ax-mcp` for constructing those clients, transport/authentication policy,
server-initiated handlers, resource subscriptions, task continuations, and
recording/replay. Keep this section focused on Agent attachment and discovery.
```typescript
const parent = agent('query:string -> answer:string', {
mcp: [memoryClient, searchClient],
mcpInheritance: 'all',
functionDiscovery: true,
contextFields: [],
});
// A child can restrict inheritance to selected namespaces or `none`.
await parent.forward(llm, { query }, { mcpInheritance: ['memory'] });
```
Rules:
- A group is `{ namespace, title, description, functions: [...] }`.
- `selectionCriteria` is optional but useful in discovery mode; it tells the actor when to choose that module.
- The group's `namespace`, `title`, `selectionCriteria`, and `description` show up in `discover(...)` module docs.
- `relevanceRanking` (default ON — set `false` to opt out): a deterministic local ranker that injects an advisory `### Likely Relevant` shortlist into the executor turn (dynamic, non-cached field — the cached prompt stays byte-stable). Enabled by default after its A/B gate passed on both small and frontier models and implemented in the generated language ports through AxIR Core. Details in `ax-agent-memory-skills`; outcomes observable via the `relevance_ranking` context event (`ax-agent-observability`).
- Add `alwaysInclude: true` to a group when discovery mode is on but the actor should always see that group's full callable definitions inline in the prompt.
- Keep `functions: [...]` either flat or grouped. Runtime validation rejects mixed plain function entries and group objects.
- In flat mode, pass `fn(...)` tools and child agents directly.
- In grouped mode, put callable entries inside groups. To expose a child agent inside a group, use `childAgent.getFunction()`.
- Do not place MCP clients in `functions`; use `mcp` so tasks, resources, subscriptions, elicitation, sampling, authorization, cancellation, and protocol metadata remain available.
- To wake an Agent from a resource subscription, use `AxMCPEventSource` and an
explicit authenticated `wake` route. MCP sessions are not tenant identity;
supply identity from the application's authenticated token mapping.
- An endpoint does not imply a resource URI. Inspect `client.inspectCatalog()`
and choose an explicit `resourceSubscriptions` policy. Omission means none;
`'all'` selects all discovered concrete resources; selectors can use names,
descriptions, MIME types, URIs, and annotations. Templates are not expanded.
- Map the event with a signature-aware `.wakeInput(...)` plan, or reuse an
`eventInput()` plan. Callback `mapInput` is still signature-validated and
cannot inject undeclared Agent fields. Use multiple matching routes to wake
multiple Agents with independent state, authorization, retries, and runs.
- To wake from a UCP lifecycle webhook, use `AxUCPWebhookEventSource` and map
verified profile/account state to Ax tenant identity after request
verification. Never derive tenant identity from the order payload.
## Host-Side Completion From Functions
Use this pattern when the actor should call a namespaced function, but the host-side function implementation should decide to end the turn:
```typescript
import { f, fn } from '@ax-llm/ax';
const finishReply = fn('finishReply')
.description('Complete the actor turn with the final reply text')
.namespace('workflow')
.arg('reply', f.string('Final reply text'))
.returns(f.string('Final reply text'))
.handler(async ({ reply }, extra) => {
extra?.protocol?.final(reply);
return reply;
})
.build();
const askForOrderId = fn('askForOrderId')
.description('Complete the actor turn by requesting clarification')
.namespace('workflow')
.arg('question', f.string('Clarification question'))
.returns(f.string('Clarification question'))
.handler(async ({ question }, extra) => {
extra?.protocol?.askClarification(question);
return question;
})
.build();
```
Rules:
- `extra.protocol` is only available when the function call comes from an active AxAgent actor runtime session.
- Use `extra.protocol.final(...)`, `extra.protocol.askClarification(...)`, or `extra.protocol.guideAgent(...)` only inside host-side function handlers.
- Inside actor-authored runtime code, use the runtime globals `final(...)` and `askClarification(...)` with the syntax documented by the active runtime.
- `extra.protocol.guideAgent(...)` is handler-only internal control flow. It stops the current actor turn and appends trusted guidance to `guidanceLog` for the next iteration.
- `askClarification(...)` accepts either a simple string or a structured object with `question` plus optional UI hints such as `type: 'date' | 'number' | 'single_choice' | 'multiple_choice'` and `choices`.
## Clarification And Resume State
Use this pattern when the actor should pause for user input and continue later from the same runtime state.
```typescript
import {
AxAgentClarificationError,
AxJSRuntime,
agent,
ai,
} from '@ax-llm/ax';
const llm = ai({
name: 'openai',
apiKey: process.env.OPENAI_APIKEY!,
});
const tripAgent = agent('request:string, answer?:string -> reply:string', {
contextFields: [],
runtime: new AxJSRuntime(),
});
let savedState = tripAgent.getState();
try {
await tripAgent.forward(llm, {
request: 'Plan a Lisbon trip',
});
} catch (error) {
if (error instanceof AxAgentClarificationError) {
console.log(error.question);
savedState = error.getState();
} else {
throw error;
}
}
if (savedState) {
tripAgent.setState(savedState);
const resumed = await tripAgent.forward(llm, {
request: 'Plan a Lisbon trip',
answer: 'June 1-5',
});
console.log(resumed.reply);
}
```
Public flow rules:
- `forward()` and `streamingForward()` throw `AxAgentClarificationError` when the actor calls `askClarification(...)`.
- Successful `final(...)` completions always continue through the responder in public flows.
- `AxAgentClarificationError.question` is the user-facing question text.
- `AxAgentClarificationError.clarification` is the normalized structured payload.
- `AxAgentClarificationError.getState()` returns the saved continuation state captured at throw time.
- `agent.getState()` and `agent.setState(...)` export or restore continuation state on the agent instance.
- `test(...)` is different: it returns structured completion payloads for harness/debug use instead of throwing clarification exceptions.
Structured clarification payloads:
- String shorthand is allowed: `askClarification("What dates should I use?")`.
- Structured form is preferred for richer chat UIs:
```javascript
askClarification({
question: 'Which route should I use?',
type: 'single_choice',
choices: ['Fastest', 'Scenic'],
});
```
- Supported `type` values are `text`, `number`, `date`, `single_choice`, and `multiple_choice`.
- `single_choice` payloads with missing, empty, or malformed `choices` are downgraded to a plain clarification question instead of failing the turn.
- `multiple_choice` payloads must include at least two valid choices; otherwise the actor turn fails with a corrective runtime error.
- Choice entries may be strings or `{ label, value? }` objects.
- Invalid clarification payloads such as a missing `question` are actor-turn runtime errors, not successful clarification completions.
State notes:
- `runtimeBindings` restores execution state; `runtimeEntries`, `actionLogEntries`, and `checkpointState` restore prompt context.
- Resume does not create a fake rehydration action-log turn; provenance still points to the original actor code that set the value.
- Only serializable/structured-clone-friendly values are guaranteed to round-trip through `getState()` / `setState(...)`.
- Reserved runtime globals such as `inputs`, tools, and protocol helpers are rebuilt fresh and are not part of saved state.
- Treat one agent instance as conversation-scoped when using `setState(...)`; do not share one mutable resumed instance across unrelated concurrent conversations.
## Bubble Errors
Use `bubbleErrors` when certain exceptions thrown inside function handlers or `llmQuery(...)` sub-query calls should propagate all the way out to `.forward()` instead of being caught by the actor loop and returned as `[ERROR]` strings.
```typescript
import { agent, f, fn } from '@ax-llm/ax';
class DatabaseError extends Error {
constructor(message: string) {
super(message);
this.name = 'DatabaseError';
}
}
const dbTool = fn('queryUsers')
.description('Query the user database')
.namespace('db')
.arg('filter', f.string('Filter expression'))
.returns(f.string('JSON result'))
.handler(async ({ filter }) => {
if (!isConnected()) throw new DatabaseError('DB connection refused');
return JSON.stringify(await db.query(filter));
})
.build();
const myAgent = agent('query:string -> answer:string', {
contextFields: [],
functions: [dbTool],
bubbleErrors: [DatabaseError],
});
```
Rules:
- `bubbleErrors` takes an array of Error constructor classes, checked via `instanceof`.
- A matching error thrown inside a function handler, during actor code execution, or inside an `llmQuery(...)` sub-query propagates immediately to `.forward()`.
- Use `bubbleErrors` for fatal infrastructure errors such as DB down, auth failure, or quota exceeded.
- Do not use `bubbleErrors` for expected recoverable errors; let those return as `[ERROR] ...` strings so the actor can handle them.
- `AxAgentClarificationError` and `AxAIServiceAbortedError` always bubble up unconditionally.
## Unified Final Signal
There are two ways to end a successful run through the responder:
1. In actor JS code, call `final(message)` when no extra context object is needed, or `final(task, context)` when you gathered evidence.
2. In function handlers, use `extra.protocol.final(...)` with the same one-arg or two-arg forms.
Rules:
- Use `final(message)` when the actor already knows the answer and no extra context object is needed.
- Use `final(task, context)` when context was gathered and needs synthesis into output fields.
- In function handlers, use `extra.protocol.final(...)` instead of a separate respond API.
- The responder still runs for both successful `final(...)` forms.
- Use `askClarification(...)` when the user must provide more information to continue.
## Discovery Mode
Enable discovery mode when you want the actor to discover modules and fetch callable definitions on demand:
```typescript
const analyst = agent('context:string, query:string -> answer:string', {
agentIdentity: {
name: 'Analyst',
description: 'Analyzes long context',
namespace: 'team',
},
contextFields: ['context'],
functions: [writer, ...tools],
functionDiscovery: true,
});
```
Discovery API:
- `await discover(item: string): void`
- `await discover(items: string[]): void`
- `await discover({ tools?: string | string[], skills?: string | string[] }): void` when `onSkillsSearch` is configured
Discovery returns `void`; fetched docs render in the next executor prompt.
Rules:
- `discover('kb')` loads a module callable list when `kb` is a discoverable module.
- `discover('kb.findSnippets')` loads a full callable definition.
- `discover('lookup')` resolves as `utils.lookup`.
- `discover({ tools: ['kb'], skills: ['release-checklist'] })` loads tool docs and skill bodies in one turn.
- Call one batched `discover(...)` with every module, callable, and skill you need.
- Do not split discovery into separate calls or wrap discovery in `Promise.all(...)`.
- Read the next prompt's "Discovered Tool Docs" and "Loaded Skills" sections.
- If a guessed call fails, stop guessing nearby names. Run `discover(...)` for that module or function and call only the exact discovered qualified name.
## Threading Parent Fields Into Child Agents
If a child agent requires a parent field such as `audience`, declare it on the child's signature and pass it explicitly when calling the child from the actor:
```typescript
const writingCoach = agent('draft:string, audience:string -> revision:string', {
agentIdentity: {
name: 'Writing Coach',
description: 'Polishes summaries for a target audience',
namespace: 'team',
},
contextFields: [],
});
const analyst = agent('context:string, audience:string, query:string -> answer:string', {
functions: [writingCoach],
contextFields: ['context'],
});
```
Generated runtime call:
```javascript
const polished = await team.writingCoach({
draft: summary,
audience: inputs.audience,
});
```
Rules:
- Pass parent fields explicitly via the call site.
- If many children need the same field on every call, use `inputUpdateCallback` to inject the value before each executor turn.
- Do not assume auto-propagation; child agents receive only the args the actor passes.
## Core API Reference
Factory shape:
```typescript
agent(signature, {
ai,
judgeAI,
agentIdentity,
contextFields,
functions,
functionDiscovery,
autoUpgrade,
playbook,
citations,
...agentOptions,
});
```
- `ai` is an optional default service for the agent instance; `.forward(ai, ...)` can still pass the runtime service.
- `judgeAI` is the optional default judge/teacher service used by optimize flows.
- `agentIdentity` controls the user-facing agent identity and child-agent function metadata.
```typescript
agentIdentity?: {
name: string;
description: string;
namespace?: string;
}
```
- `name` is normalized to camelCase for child-agent function names.
- `name` and `description` are included in the actor and responder prompts as the user-facing agent identity.
- `namespace` changes the child-agent module from default `utils` to a custom module such as `team`.
Each `contextFields` entry is either a plain field name string or an object controlling how much of the value is inlined into the distiller prompt:
- `{ field, promptMaxChars: N }`: inline only when the serialized value is at most `N` chars; otherwise omit it from the prompt and keep it runtime-only.
- `{ field, keepInPromptChars: N, reverseTruncate?: boolean }`: always inline a truncated string excerpt; `reverseTruncate: true` keeps the last `N` chars.
Use `promptMaxChars` when partial data is worse than no data. Use `keepInPromptChars` when a prefix or suffix alone is useful. The two options are mutually exclusive on one field.
### Auto-upgrade defaults
`autoUpgrade` is ON by default: the agent applies both knobs above on the user's behalf based on character counts, so forgetting them no longer floods prompts.
- Function discovery: when `functionDiscovery` is left unset and the estimated inline docs of discoverable functions exceed ~10k chars, discovery is enabled automatically. An explicit `functionDiscovery: true | false` always wins.
- Context fields: per run, an undeclared input value whose serialized size exceeds 8k chars is kept runtime-only like a declared context field — the prompt gets a 1,200-char truncated preview plus a `contextMetadata` entry, while the full value stays addressable as `inputs.<field>` in the code runtime (the responder stage gets the same preview). Fields declared in `contextFields` keep their declared config.
```typescript
autoUpgrade?: boolean | {
functionDiscovery?: boolean | { aboveFunctionDocChars?: number }; // default 10_000
contextFields?: boolean | { promoteAboveChars?: number; previewChars?: number }; // 8_000 / 1_200
}
```
Rules:
- Set `autoUpgrade: false` (or disable one side) to restore fully manual behavior.
- Values in required non-string fields (arrays, objects, numbers, media) are never auto-promoted — declare those in `contextFields` explicitly when they can be large.
- Each promotion emits a `field_auto_promoted` context event (`onContextEvent`) with the field name, original size, and preview size; use it to observe what was kept out of the prompt.
### Learning And Citations
These construction-time options are portable across TypeScript and the generated
Python, Java, C++, Go, and Rust packages (both default off):
- `playbook`: attach an ACE playbook at construction. `learn` is on by default — after each run that produced failure signals (error turns, dead-ends, failing tool calls) one bounded update curates durable avoidance rules that ride the next run's actor prompt; zero LLM cost on clean runs. TypeScript seeds a prior session with `playbook: { playbook: snapshot }`; generated packages accept their full `{ playbook, artifact }` snapshot under `seed`. Persist via `onUpdate`, read the live handle with `getPlaybook()` (or the language-shaped equivalent), gate with `learn: { minSignals, dedupe }`, or disable with `learn: false`. To grow the same playbook from a task set with a held-out verify gate, use the agent-bound playbook evolve method — see `ax-playbook`.
- `citations`: add an optional `evidenceCitations: string[]` responder output listing which evidence entries (top-level keys of the curated evidence, plus memory ids) the answer relied on. Validated in-pipeline — the model cannot cite evidence it never collected (existence, not entailment). Pass `true`, or `{ field?, surface?: 'output' | 'hidden', includeMemoryIds?, onCitations? }`.
Stage guidance is portable too. `setInstruction` replaces the stage-owned actor
instruction and `addActorInstruction` appends an additive rule. Both are real
optimization components; rebuilding the split programs no longer discards them.
Generated packages use their normal casing conventions (`set_instruction` in
Python/C++/Rust and `SetInstruction` in Go).
The generated-language observer and evolve spellings are:
| Language | Citations observer | Verified agent playbook evolve |
|---|---|---|
| Python | `citations.onCitations` | `agent.playbook().evolve(dataset, options)` |
| Java | `citations.onCitations` (`Consumer`) | `agent.playbook(null).evolve(dataset, options)` |
| C++ | `set_citations_observer(...)` | `agent.get_playbook()->evolve(dataset, options)` |
| Go | `citations.onCitations` (`func([]Value)`) | `agent.GetPlaybook().EvolveAgent(ctx, dataset, options)` |
| Rust | `set_citations_observer(...)` | `playbook.evolve_agent(&mut agent, client, dataset, options)` |
C++ and Rust use `set_playbook_observer(...)` for construction-time learning
updates; Python, Java, and Go accept the `playbook.onUpdate` callback in their
native configuration map.
## Public Surface
Use these method groups as the compact AxAgent surface map:
- Running: `forward(ai, values, options?)` and `streamingForward(ai, values, options?)`.
- Forward-time agent options: `skills`, `onUsedMemories`, and `onUsedSkills`; use `ax-agent-memory-skills` for details.
- State and control: `getState()`, `setState(state?)`, `getContextMap()`, `setContextMap(map?)`, `stop()`, `getSignature()`, `setSignature(signature)`, `getFunction()`, `getId()`, and `setId(id)`. Context-map evolve policy lives on `AxAgentContextMap` (`infiniteEvolve`, `evolveSteps`, `maxChars`), not on the agent config. See [`src/examples/rlm-context-map-live.ts`](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/rlm-context-map-live.ts) for provider-backed persistence and finite-evolve usage.
- Observability: `getChatLog()`, `getUsage()`, `getStagedUsage()`, `resetUsage()`, and `getTraces()`; use `ax-agent-observability` for details.
- Demos and tuning: `setDemos(...)`, `namedPrograms()`, `namedProgramInstances()`, `optimize(...)`, `applyOptimization(...)`, `getOptimizableComponents()`, and `applyOptimizedComponents(...)`; use `ax-agent-optimize` for tuning details.
- Learning: `playbook()` returns an agent-aware playbook handle (`update(...)`, `render()`, state/load methods, and verified dataset evolution); `getPlaybook()` reads the current handle. Generated packages expose the same behavior with language-shaped method names. Use `ax-playbook` for details.
Rules:
- `getFunction()` requires `agentIdentity` because the agent needs function metadata when used as a child tool.
- Prefer `.forward(...)` for normal runs and `.streamingForward(...)` only when the caller needs streamed responder output.
- `setSignature(...)` must preserve configured `contextFields`; it throws if a configured context field is missing from the new signature.
- Treat low-level optimization component methods as advanced hooks; normal examples should use `agent.optimize(...)` and `agent.applyOptimization(...)`.
## Tuning Hand-off
When the user wants `agent.optimize(...)`, judge configuration, eval datasets, saved optimization artifacts, or optimization guidance, use `ax-agent-optimize`.
Keep this skill focused on building and running agents. For tuning work:
- use eval-safe tools
- treat `judgeOptions` as part of the optimize workflow
- choose an objective `metric` when scoring is mechanical; use the built-in judge only when run quality needs qualitative review
- keep runtime authoring guidance here and optimization guidance in `ax-agent-optimize`
## Examples
Fetch these for full working code:
- [Agent](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/agent.ts) - basic agent
- [Functions](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/function.ts) - function validation
- [Food Search](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/food-search.ts) - API tools
- [Smart Home](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/smart-home.ts) - state management
- [Customer Support](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/customer-support.ts) - classification agent
- [Abort Patterns](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/abort-patterns.ts) - abort handling
- [Smart Defaults Agent](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/typescript/long-agents/smart-defaults-agent.ts) - auto-upgrade context promotion, relevance hints, and runtime tools
- [Portable Playbook Evolve](https://raw.githubusercontent.com/ax-llm/ax/refs/heads/main/src/examples/python/optimization/agent-playbook-evolve.py) - Python construction-time learning, validated citations, stage guidance, and verified task-set evolution (parallel Java/C++/Go/Rust examples live beside it)
RLM examples are listed in `ax-agent-rlm`. Memory/skills examples are listed in `ax-agent-memory-skills`.
## Event-Driven Agents
`AxEventRuntime` can wake or resume an Agent while preserving its logical
state. Use `createProgram(instance)` for multi-tenant Agents; one mutable Agent
object must not serve multiple instance keys concurrently. Clarification and
remote task completion are represented as owned continuations, not synthetic
user turns.
Declare the Agent signature on
`eventTarget('id').createProgram(signature, factory)` and map event values with
`eventPath`. The runtime verifies every created Agent against that signature
before invoking it. Fan-out uses multiple matching routes so each Agent keeps
its own authorization, instance serialization, retry policy, and run record.
## Do Not Generate
- Do not use `new AxAgent(...)` for new code unless explicitly required.
- Do not assume child agents are always under `agents.*`.
- Do not guess function names in discovery mode.
- Do not write a full multi-step RLM actor program in one turn; use `ax-agent-rlm`.
- Do not combine `console.log(...)` with `final(...)`.
- Do not add `bubbleErrors` for ordinary recoverable tool errors.
- Do not call `discover()` from the distiller or responder stages.
- Do not assign or inspect the return value of `await discover(...)`; read the next prompt instead.
- Do not loop `discover()` calls or wrap them in `Promise.all`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!