ax-agent
This skill helps an LLM generate correct AxAgent code using @ax-llm/ax. Use when the user asks about agent(), child agents, namespaced functions, discovery mode, shared fields, llmQuery(...), or RLM code execution.
- License 许可
- MIT
- 所属仓库
- marolinik/waggle
- 最近更新
- 2026-03-25
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- ax-agent
- version
- 19.0.13
- description
- This skill helps an LLM generate correct AxAgent code using @ax-llm/ax. Use when the user asks about agent(), child agents, namespaced functions, discovery mode, shared fields, llmQuery(...), or RLM code execution.
03 SKILL.md 正文
AxAgent Codegen Rules (@ax-llm/ax)
Use this skill to generate AxAgent code. Prefer short, modern, copyable patterns. Do not write tutorial prose unless the user explicitly asks for explanation.
Use These Defaults
- Use
agent(...), notnew AxAgent(...). - Prefer namespaced functions such as
utils.search(...)orkb.find(...). - Assume the child-agent module is
agentsunlessagentIdentity.namespaceis set. - If
functions.discoveryistrue, discover callables from modules before using them. - In stdout-mode RLM, use one observable
console.log(...)step per non-final actor turn.
Critical Rules
- Use
agent(...)factory syntax for new code. - If
agentIdentity.namespaceis set, call child agents through that module, notagents. - If
functions.discoveryistrue, calllistModuleFunctions(...)first, thengetFunctionDefinitions(...), then call only discovered functions. - In stdout-mode RLM, non-final turns must emit exactly one
console.log(...)and stop immediately after it. - Never combine
console.log(...)withfinal(...)orask_clarification(...)in the same actor turn. - If a child agent needs parent inputs such as
audience, usefields.sharedorfields.globallyShared. llmQuery(...)failures may come back as[ERROR] ...; do not assume success.
Canonical Pattern
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);
Child Agents And Module Namespace
Default child-agent module:
const writer = agent('draft:string -> revision:string', {
agentIdentity: {
name: 'Writer',
description: 'Polishes drafts',
},
contextFields: [],
});
const coordinator = agent('query:string -> answer:string', {
agents: { local: [writer] },
contextFields: [],
});
Generated runtime call:
const result = await agents.writer({ draft: '...' });
Custom child-agent module:
const writer = agent('draft:string -> revision:string', {
agentIdentity: {
name: 'Writer',
description: 'Polishes drafts',
},
contextFields: [],
});
const coordinator = agent('query:string -> answer:string', {
agentIdentity: {
name: 'Coordinator',
description: 'Routes work',
namespace: 'team',
},
agents: { local: [writer] },
contextFields: [],
});
Generated runtime call:
const result = await team.writer({ draft: '...' });
Rules:
- Default child-agent module is
agents. - If
agentIdentity.namespaceis set, that becomes the child-agent module. - Do not hardcode
agents.<name>(...)when a custom namespace is configured.
Tool Functions And Namespaces
import type { AxFunction } from '@ax-llm/ax';
const tools: AxFunction[] = [
{
name: 'findSnippets',
namespace: 'kb',
description: 'Find handbook snippets by topic',
parameters: {
type: 'object',
properties: {
topic: { type: 'string', description: 'Topic keyword' },
},
required: ['topic'],
},
returns: {
type: 'array',
items: { type: 'string' },
},
func: async ({ topic }) => [],
},
];
const analyst = agent('query:string -> answer:string', {
functions: { local: tools },
contextFields: [],
});
Generated runtime call:
const snippets = await kb.findSnippets({ topic: 'severity' });
Rules:
- Prefer namespaced functions.
- Default function namespace is
utilswhen no namespace is set. - Use the runtime call shape
await <namespace>.<name>({...}).
Discovery Mode
Enable discovery mode when you want the actor to discover modules and fetch callable definitions on demand:
const analyst = agent('context:string, query:string -> answer:string', {
agentIdentity: {
name: 'Analyst',
description: 'Analyzes long context',
namespace: 'team',
},
contextFields: ['context'],
agents: { local: [writer] },
functions: {
discovery: true,
local: tools,
},
});
Discovery APIs:
await listModuleFunctions(modules: string | string[])await getFunctionDefinitions(functions: string | string[])
Both return Markdown.
Rules:
- Call
listModuleFunctions(...). - Inspect the logged result.
- Call
getFunctionDefinitions(...)for only the callables you plan to use. - Inspect the logged result.
- Call discovered functions and child agents.
Examples:
const modules = await listModuleFunctions(['team', 'kb', 'utils']);
console.log(modules);
const defs = await getFunctionDefinitions(['team.writer', 'kb.findSnippets']);
console.log(defs);
Do not:
- Do not guess callable names when discovery mode is on.
- Do not assume sub-agents live under
agentsifagentIdentity.namespaceis configured. - Do not dump large pre-known tool definitions into actor code when discovery mode is enabled.
RLM Actor Code Rules
Use these rules when generating actor JavaScript for RLM in stdout mode:
- Treat each actor turn as exactly one observable step.
- If you need to inspect a value, compute it,
console.log(...)it, and stop immediately after thatconsole.log(...). - On the next turn, read the logged result from
Action Logbefore writing more code that depends on it. - Errors from child-agent or tool calls appear in
Action Log; inspect them and fix the code on the next turn. - Non-final turns should contain exactly one
console.log(...). - Final turns should call
final(...)orask_clarification(...)withoutconsole.log(...). - Do not write a complete multi-step program in one actor turn.
Good pattern:
Turn 1:
const defs = await getFunctionDefinitions(['kb.findSnippets']);
console.log(defs);
Turn 2:
const snippets = await kb.findSnippets({ topic: 'severity' });
console.log(snippets);
Turn 3:
final({ answer: '...' });
Invalid pattern:
const defs = await getFunctionDefinitions(['kb.findSnippets']);
console.log(defs);
const snippets = await kb.findSnippets({ topic: 'severity' });
final(snippets);
Reason: this mixes observation and follow-up work in one turn.
Shared Fields
If a child agent requires a parent field such as audience, prefer shared fields:
const writingCoach = agent(
'draft:string, audience:string -> revision:string',
{
agentIdentity: {
name: 'Writing Coach',
description: 'Polishes summaries for a target audience',
},
contextFields: [],
}
);
const analyst = agent(
'context:string, audience:string, query:string -> answer:string',
{
agents: { local: [writingCoach] },
fields: { shared: ['audience'] },
contextFields: ['context'],
}
);
Generated runtime call:
const polished = await agents.writingCoach({ draft: summary });
Rules:
- Use
fields.sharedfor direct children. - Use
fields.globallySharedfor all descendants. - Do not manually thread a parent field on every child call when shared fields fit the use case.
Shared Agents And Shared Functions
Use grouped config:
const parent = agent('query:string -> answer:string', {
agents: {
local: [worker],
shared: [logger],
globallyShared: [auditor],
},
functions: {
local: [searchTool],
shared: [scoreTool],
globallyShared: [traceTool],
},
contextFields: [],
});
Rules:
agents.sharedandfunctions.sharedpropagate one level down.agents.globallySharedandfunctions.globallySharedpropagate to all descendants.- Use
excludedwhen a child should not receive a propagated field, agent, or function.
llmQuery(...) Rules
Available forms:
await llmQuery(query, context?)await llmQuery({ query, context? })await llmQuery([{ query, context }, ...])
Rules:
llmQuery(...)forwards only the explicitcontextargument.- Parent inputs are not automatically available to
llmQuery(...)children. - Single-call
llmQuery(...)may return[ERROR] ...on non-abort failures. - Batched
llmQuery([...])returns per-item[ERROR] .... - If a result starts with
[ERROR], inspect or branch on it instead of assuming success.
Example:
const summary = await llmQuery('Summarize this incident', inputs.context);
if (summary.startsWith('[ERROR]')) {
console.log(summary);
} else {
console.log(summary);
}
Short API Reference
agentIdentity
agentIdentity?: {
name: string;
description: string;
namespace?: string;
}
nameis normalized to camelCase for child-agent function names.namespacechanges the child-agent module from defaultagentsto a custom module such asteam.
AxAgentOptions
{
contextFields: readonly (string | { field: string; promptMaxChars?: number })[];
agents?: {
local?: AxAnyAgentic[];
shared?: AxAnyAgentic[];
globallyShared?: AxAnyAgentic[];
excluded?: string[];
};
fields?: {
local?: string[];
shared?: string[];
globallyShared?: string[];
excluded?: string[];
};
functions?: {
local?: AxFunction[];
shared?: AxFunction[];
globallyShared?: AxFunction[];
excluded?: string[];
discovery?: boolean;
};
runtime?: AxCodeRuntime;
maxSubAgentCalls?: number;
maxRuntimeChars?: number;
maxBatchedLlmQueryConcurrency?: number;
maxTurns?: number;
contextManagement?: AxContextManagementConfig;
actorFields?: string[];
actorCallback?: (result: Record<string, unknown>) => void | Promise<void>;
inputUpdateCallback?: (currentInputs: Record<string, unknown>) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined;
mode?: 'simple' | 'advanced';
recursionOptions?: Partial<Omit<AxProgramForwardOptions, 'functions'>> & {
maxDepth?: number;
};
actorOptions?: Partial<AxProgramForwardOptions & { description?: string }>;
responderOptions?: Partial<AxProgramForwardOptions & { description?: string }>;
}
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.
- Do not combine
console.log(...)withfinal(...). - Do not forget
fields.sharedwhen child agents depend on parent inputs.
04 同仓库更多 Skills
summarize
Summarize text or conversation into key points
classify
Classify user intent or categorize text
ax
This skill helps with using the @ax-llm/ax TypeScript library for building LLM applications. Use when the user asks about ax(), ai(), f(), s(), agent(), flow(), AxGen, AxAgent, AxFlow, signatures, streaming, or mentions @ax-llm/ax.