@amitdeshmukh/ax-crew 8.5.0 → 8.7.0
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/.claude/settings.local.json +3 -1
- package/.claude/skills/ax-crew/SKILL.md +466 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +7 -7
- package/examples/run-crew-workflow.ts +2 -2
- package/package.json +3 -1
- package/scripts/install-skills.mjs +59 -0
- package/scripts/uninstall-skills.mjs +25 -0
- package/src/skills/ax-crew-ace.md +165 -0
- package/src/skills/ax-crew-agent-config.md +181 -0
- package/src/skills/ax-crew-code-execution.md +166 -0
- package/src/skills/ax-crew-execution-modes.md +287 -0
- package/src/skills/ax-crew-few-shot.md +165 -0
- package/src/skills/ax-crew-functions.md +218 -0
- package/src/skills/ax-crew-mcp.md +221 -0
- package/src/skills/ax-crew-metrics.md +170 -0
- package/src/skills/ax-crew-patterns.md +286 -0
- package/src/skills/ax-crew-providers.md +204 -0
- package/src/skills/ax-crew-signatures.md +169 -0
- package/src/skills/ax-crew-state.md +168 -0
- package/src/skills/ax-crew-streaming.md +143 -0
- package/src/skills/ax-crew-sub-agents.md +203 -0
- package/src/skills/ax-crew-telemetry.md +161 -0
- package/src/skills/ax-crew.md +124 -0
- package/examples/run-manager.ts +0 -98
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-execution-modes
|
|
3
|
+
version: "__VERSION__"
|
|
4
|
+
description: "ax-crew execution modes: execution mode, axgen, axagent, RLM, runtime, contextFields, AxJSRuntime, contextManagement, fields, shared, globallyShared, excluded, maxTurns, maxSubAgentCalls"
|
|
5
|
+
argument-hint: [topic]
|
|
6
|
+
allowed-tools: Read, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# ax-crew Execution Modes
|
|
10
|
+
|
|
11
|
+
## axgen (default)
|
|
12
|
+
|
|
13
|
+
Uses `AxGen` for structured generation. Single-pass, deterministic. Sub-agents become callable tool functions. Best for straightforward input-to-output tasks.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
{
|
|
17
|
+
name: "SimpleAgent",
|
|
18
|
+
executionMode: "axgen", // default, can be omitted
|
|
19
|
+
signature: "query:string -> answer:string",
|
|
20
|
+
// ...
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## axagent
|
|
25
|
+
|
|
26
|
+
Uses `AxAgent` with RLM (Runtime Language Model). Multi-step agentic reasoning loop. Supports context management, tombstoning, and state inspection.
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
{
|
|
30
|
+
name: "ReasoningAgent",
|
|
31
|
+
executionMode: "axagent",
|
|
32
|
+
signature: "context:string, query:string -> answer:string",
|
|
33
|
+
// ...
|
|
34
|
+
axAgentOptions: {
|
|
35
|
+
contextFields: ["context"], // required for axagent (can be empty [])
|
|
36
|
+
runtime: new AxJSRuntime({ permissions: [AxJSRuntimePermission.TIMING] }),
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Both modes use the same `forward()` / `streamingForward()` API.
|
|
42
|
+
|
|
43
|
+
## axAgentOptions Full Reference
|
|
44
|
+
|
|
45
|
+
Type: `AxCrewAxAgentOptions` (extends `Partial<AxAgentOptions>`)
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
axAgentOptions: {
|
|
49
|
+
// Required: which input fields contain context for RLM processing
|
|
50
|
+
contextFields: string[],
|
|
51
|
+
|
|
52
|
+
// Runtime for code execution in RLM
|
|
53
|
+
runtime?: AxJSRuntime,
|
|
54
|
+
|
|
55
|
+
// Max reasoning turns before stopping
|
|
56
|
+
maxTurns?: number,
|
|
57
|
+
|
|
58
|
+
// Max sub-agent delegations
|
|
59
|
+
maxSubAgentCalls?: number,
|
|
60
|
+
|
|
61
|
+
// RLM mode
|
|
62
|
+
mode?: "simple" | "full",
|
|
63
|
+
|
|
64
|
+
// Context management strategies
|
|
65
|
+
contextManagement?: {
|
|
66
|
+
errorPruning?: boolean, // prune context on errors
|
|
67
|
+
hindsightEvaluation?: boolean, // evaluate context relevance
|
|
68
|
+
pruneRank?: number, // ranking threshold for pruning
|
|
69
|
+
tombstoning?: { // summarize pruned context
|
|
70
|
+
model: string,
|
|
71
|
+
modelConfig?: { maxTokens?: number },
|
|
72
|
+
},
|
|
73
|
+
stateInspection?: {
|
|
74
|
+
contextThreshold?: number, // token count threshold
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
// Sub-agents and functions (can also be set via top-level agents/functions)
|
|
79
|
+
agents?: AxAgentOptions['agents'],
|
|
80
|
+
functions?: AxAgentOptions['functions'],
|
|
81
|
+
|
|
82
|
+
// Field sharing between parent and sub-agents
|
|
83
|
+
fields?: {
|
|
84
|
+
shared?: string[], // fields shared with sub-agents
|
|
85
|
+
globallyShared?: string[], // fields shared with all descendants
|
|
86
|
+
excluded?: string[], // opt out of parent's shared fields
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## fields: shared, globallyShared, excluded
|
|
92
|
+
|
|
93
|
+
Control how input/output fields propagate between parent and sub-agents in `axagent` mode.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// Parent agent shares knowledgeBase and userId with sub-agents
|
|
97
|
+
{
|
|
98
|
+
name: "CustomerSupportAgent",
|
|
99
|
+
executionMode: "axagent",
|
|
100
|
+
signature: "query:string, knowledgeBase:string, userId:string -> answer:string",
|
|
101
|
+
agents: ["PolicyLookupAgent", "BillingHelperAgent", "SentimentClassifierAgent"],
|
|
102
|
+
axAgentOptions: {
|
|
103
|
+
contextFields: ["knowledgeBase"],
|
|
104
|
+
fields: { shared: ["knowledgeBase", "userId"] },
|
|
105
|
+
runtime,
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Sub-agent that opts OUT of receiving shared fields
|
|
110
|
+
{
|
|
111
|
+
name: "SentimentClassifierAgent",
|
|
112
|
+
executionMode: "axagent",
|
|
113
|
+
signature: 'question:string -> sentiment:string "positive, negative, or neutral"',
|
|
114
|
+
axAgentOptions: {
|
|
115
|
+
contextFields: [],
|
|
116
|
+
fields: { excluded: ["knowledgeBase", "userId"] }, // won't receive these
|
|
117
|
+
runtime,
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Canonical Pattern: RLM with Context Management
|
|
123
|
+
|
|
124
|
+
From `rlm-long-task.ts`:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { AxJSRuntime, AxJSRuntimePermission } from '@ax-llm/ax';
|
|
128
|
+
import { AxCrew } from '@amitdeshmukh/ax-crew';
|
|
129
|
+
import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
|
|
130
|
+
|
|
131
|
+
const runtime = new AxJSRuntime({
|
|
132
|
+
permissions: [AxJSRuntimePermission.TIMING],
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const config: AxCrewConfig = {
|
|
136
|
+
crew: [
|
|
137
|
+
{
|
|
138
|
+
name: "Analyzer",
|
|
139
|
+
description: "Analyzes a large dataset with semantic context management.",
|
|
140
|
+
executionMode: "axagent",
|
|
141
|
+
signature:
|
|
142
|
+
'context:string, query:string -> answer:string, keyFindings:string[] "Analyzes context and returns findings"',
|
|
143
|
+
provider: "google-gemini",
|
|
144
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
145
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
146
|
+
axAgentOptions: {
|
|
147
|
+
contextFields: ["context"],
|
|
148
|
+
runtime,
|
|
149
|
+
maxTurns: 20,
|
|
150
|
+
maxSubAgentCalls: 40,
|
|
151
|
+
mode: "simple",
|
|
152
|
+
contextManagement: {
|
|
153
|
+
errorPruning: true,
|
|
154
|
+
hindsightEvaluation: true,
|
|
155
|
+
pruneRank: 2,
|
|
156
|
+
tombstoning: {
|
|
157
|
+
model: "gemini-2.5-flash",
|
|
158
|
+
modelConfig: { maxTokens: 60 },
|
|
159
|
+
},
|
|
160
|
+
stateInspection: { contextThreshold: 3000 },
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
async function main() {
|
|
168
|
+
const crew = new AxCrew(config);
|
|
169
|
+
try {
|
|
170
|
+
await crew.addAllAgents();
|
|
171
|
+
|
|
172
|
+
const analyzer = crew.agents?.get("Analyzer");
|
|
173
|
+
if (!analyzer) throw new Error("Failed to initialize Analyzer");
|
|
174
|
+
|
|
175
|
+
const result = await analyzer.forward({
|
|
176
|
+
context: "Region,Month,Product,Units,Revenue\nNorth,Jan,Widget-A,1200,48000\n...",
|
|
177
|
+
query: "Which region has the highest revenue growth from Jan to Mar?",
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
console.log("Answer:", result.answer);
|
|
181
|
+
console.log("Key Findings:", result.keyFindings);
|
|
182
|
+
|
|
183
|
+
console.log("Agent Metrics:", JSON.stringify(analyzer.getMetrics?.(), null, 2));
|
|
184
|
+
console.log("Crew Metrics:", JSON.stringify(crew.getCrewMetrics(), null, 2));
|
|
185
|
+
} finally {
|
|
186
|
+
crew.destroy();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
main().catch(console.error);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Canonical Pattern: Shared Fields Between Agents
|
|
194
|
+
|
|
195
|
+
From `rlm-shared-fields.ts`:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { AxJSRuntime, AxJSRuntimePermission } from '@ax-llm/ax';
|
|
199
|
+
import { AxCrew } from '@amitdeshmukh/ax-crew';
|
|
200
|
+
import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
|
|
201
|
+
|
|
202
|
+
const runtime = new AxJSRuntime({
|
|
203
|
+
permissions: [AxJSRuntimePermission.TIMING],
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const config: AxCrewConfig = {
|
|
207
|
+
crew: [
|
|
208
|
+
{
|
|
209
|
+
name: "PolicyLookupAgent",
|
|
210
|
+
description: "Looks up policy details in the provided knowledge base.",
|
|
211
|
+
executionMode: "axagent",
|
|
212
|
+
signature: 'question:string -> answer:string',
|
|
213
|
+
provider: "google-gemini",
|
|
214
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
215
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
216
|
+
axAgentOptions: { contextFields: [], runtime },
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "SentimentClassifierAgent",
|
|
220
|
+
description: "Classifies customer message sentiment.",
|
|
221
|
+
executionMode: "axagent",
|
|
222
|
+
signature: 'question:string -> sentiment:string "positive, negative, or neutral"',
|
|
223
|
+
provider: "google-gemini",
|
|
224
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
225
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
226
|
+
axAgentOptions: {
|
|
227
|
+
contextFields: [],
|
|
228
|
+
fields: { excluded: ["knowledgeBase", "userId"] },
|
|
229
|
+
runtime,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "CustomerSupportAgent",
|
|
234
|
+
description: "Routes queries to specialists and returns a final answer.",
|
|
235
|
+
executionMode: "axagent",
|
|
236
|
+
signature: "query:string, knowledgeBase:string, userId:string -> answer:string",
|
|
237
|
+
provider: "google-gemini",
|
|
238
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
239
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
240
|
+
agents: ["PolicyLookupAgent", "SentimentClassifierAgent"],
|
|
241
|
+
axAgentOptions: {
|
|
242
|
+
contextFields: ["knowledgeBase"],
|
|
243
|
+
fields: { shared: ["knowledgeBase", "userId"] },
|
|
244
|
+
runtime,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
async function main() {
|
|
251
|
+
const crew = new AxCrew(config);
|
|
252
|
+
try {
|
|
253
|
+
await crew.addAllAgents();
|
|
254
|
+
|
|
255
|
+
const supportAgent = crew.agents?.get("CustomerSupportAgent");
|
|
256
|
+
if (!supportAgent) throw new Error("Failed to initialize");
|
|
257
|
+
|
|
258
|
+
const result = await supportAgent.forward({
|
|
259
|
+
query: "I want to return the Smart Lamp. Am I eligible for a full refund?",
|
|
260
|
+
knowledgeBase: "REFUND POLICY: Full refund within 30 days...",
|
|
261
|
+
userId: "cust-42",
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
console.log("Answer:", result.answer);
|
|
265
|
+
} finally {
|
|
266
|
+
crew.destroy();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
main().catch(console.error);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Do Not Generate
|
|
274
|
+
|
|
275
|
+
- Do NOT use `axAgentOptions` without setting `executionMode: "axagent"` -- it is ignored in `axgen` mode.
|
|
276
|
+
- Do NOT omit `contextFields` when using `axagent` mode -- it is required (use `[]` if no context fields).
|
|
277
|
+
- Do NOT omit `runtime` when using RLM features -- `AxJSRuntime` is required for code execution.
|
|
278
|
+
- Do NOT confuse `fields.shared` with `contextFields` -- `shared` controls field propagation to sub-agents, `contextFields` identifies which fields contain context for RLM processing.
|
|
279
|
+
- Do NOT set `fields.excluded` on a parent agent -- it is for sub-agents opting out of the parent's shared fields.
|
|
280
|
+
- Do NOT use `axAgentOptions.agents` or `axAgentOptions.functions` unless you need the AxAgent-native format -- prefer the top-level `agents` and `functions` config fields.
|
|
281
|
+
|
|
282
|
+
## References
|
|
283
|
+
|
|
284
|
+
- [rlm-long-task.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/rlm-long-task.ts)
|
|
285
|
+
- [rlm-shared-fields.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/rlm-shared-fields.ts)
|
|
286
|
+
- [Source: AxCrewAxAgentOptions type](https://github.com/amitdeshmukh/ax-crew/blob/main/src/types.ts)
|
|
287
|
+
- [Source: StatefulAxAgent execution mode handling](https://github.com/amitdeshmukh/ax-crew/blob/main/src/agents/index.ts)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-few-shot
|
|
3
|
+
description: AxCrew few-shot examples via examples[] field in AgentConfig. Covers in-context learning, demonstration structure, input/output field matching, setExamplesCompat() for dynamic updates, and when to use examples vs definition/prompt.
|
|
4
|
+
version: "__VERSION__"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AxCrew Few-Shot Examples
|
|
8
|
+
|
|
9
|
+
The `examples[]` field in `AgentConfig` provides DSPy-style few-shot demonstrations. Each example contains input AND output field values matching the agent's signature.
|
|
10
|
+
|
|
11
|
+
## Basic Structure
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
{
|
|
15
|
+
name: "Agent",
|
|
16
|
+
signature: "question:string -> answer:string",
|
|
17
|
+
// ...
|
|
18
|
+
examples: [
|
|
19
|
+
{ question: "What is 2+2?", answer: "4" },
|
|
20
|
+
{ question: "Capital of France?", answer: "Paris" },
|
|
21
|
+
],
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Every key in the example object must match a field name from the signature (inputs and/or outputs).
|
|
26
|
+
|
|
27
|
+
## Full Example
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { AxCrew } from 'ax-crew';
|
|
31
|
+
import type { AxCrewConfig } from 'ax-crew';
|
|
32
|
+
|
|
33
|
+
const config: AxCrewConfig = {
|
|
34
|
+
crew: [
|
|
35
|
+
{
|
|
36
|
+
name: "SupportAgent",
|
|
37
|
+
description: "Customer support agent that follows company tone",
|
|
38
|
+
signature:
|
|
39
|
+
"ticket:string, standardPolicies:string[] -> politeSupportResponse:string, decision:string, policyApplied:string",
|
|
40
|
+
provider: "google-gemini",
|
|
41
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
42
|
+
ai: { model: "gemini-2.5-flash", temperature: 0.7 },
|
|
43
|
+
examples: [
|
|
44
|
+
{
|
|
45
|
+
ticket: "I want to return my laptop purchased 10 days ago.",
|
|
46
|
+
standardPolicies: ["Returns within 30 days only"],
|
|
47
|
+
politeSupportResponse:
|
|
48
|
+
"Of course! Your laptop is within our 30-day return window. I'll process that right away.",
|
|
49
|
+
decision: "approved",
|
|
50
|
+
policyApplied: "Returns within 30 days only",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
ticket: "Refund my sale item please.",
|
|
54
|
+
standardPolicies: ["Sale items: no returns, no refunds"],
|
|
55
|
+
politeSupportResponse:
|
|
56
|
+
"I understand your frustration. Unfortunately, sale items are final sale per our policy. I'd be happy to help with an exchange instead.",
|
|
57
|
+
decision: "denied",
|
|
58
|
+
policyApplied: "Sale items: no returns, no refunds",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
async function main() {
|
|
66
|
+
const crew = new AxCrew(config);
|
|
67
|
+
await crew.addAllAgents();
|
|
68
|
+
|
|
69
|
+
const agent = crew.agents?.get("SupportAgent");
|
|
70
|
+
const result = await agent!.forward({
|
|
71
|
+
ticket: "I bought headphones 15 days ago and they broke.",
|
|
72
|
+
standardPolicies: ["Returns within 30 days only", "Defective items replaced free"],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log(result.politeSupportResponse);
|
|
76
|
+
console.log(result.decision);
|
|
77
|
+
crew.destroy();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main().catch(console.error);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Multi-Field Examples
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
{
|
|
87
|
+
name: "Planner",
|
|
88
|
+
description: "Creates execution plans",
|
|
89
|
+
signature: "task:string, context:string -> plan:string, steps:string[]",
|
|
90
|
+
provider: "openai",
|
|
91
|
+
ai: { model: "gpt-4o" },
|
|
92
|
+
examples: [
|
|
93
|
+
{
|
|
94
|
+
task: "Deploy new API version",
|
|
95
|
+
context: "Kubernetes cluster, 3 environments",
|
|
96
|
+
plan: "Blue-green deployment with canary rollout",
|
|
97
|
+
steps: [
|
|
98
|
+
"Run integration tests",
|
|
99
|
+
"Deploy to staging",
|
|
100
|
+
"Canary 10% traffic",
|
|
101
|
+
"Full rollout",
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
task: "Migrate database",
|
|
106
|
+
context: "PostgreSQL 14 to 16, 500GB data",
|
|
107
|
+
plan: "Logical replication with minimal downtime",
|
|
108
|
+
steps: [
|
|
109
|
+
"Set up PG16 replica",
|
|
110
|
+
"Enable logical replication",
|
|
111
|
+
"Sync and verify",
|
|
112
|
+
"Switch over",
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Dynamic Example Updates (setExamplesCompat)
|
|
120
|
+
|
|
121
|
+
Update examples at runtime after agent initialization:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const crew = new AxCrew(config);
|
|
125
|
+
await crew.addAllAgents();
|
|
126
|
+
|
|
127
|
+
const agent = crew.agents?.get("SupportAgent");
|
|
128
|
+
|
|
129
|
+
// Update examples dynamically
|
|
130
|
+
(agent as any).setExamplesCompat([
|
|
131
|
+
{
|
|
132
|
+
ticket: "My order never arrived.",
|
|
133
|
+
standardPolicies: ["Reship if not delivered in 14 days"],
|
|
134
|
+
politeSupportResponse: "I'm sorry about that! Let me reship your order immediately.",
|
|
135
|
+
decision: "approved",
|
|
136
|
+
policyApplied: "Reship if not delivered in 14 days",
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`setExamplesCompat()` replaces all current examples. It is preferred over `setExamples()` (deprecated) for compatibility across Ax runtime versions.
|
|
142
|
+
|
|
143
|
+
## When to Use examples[] vs definition/prompt
|
|
144
|
+
|
|
145
|
+
| Use `examples[]` | Use `definition` / `prompt` |
|
|
146
|
+
|---|---|
|
|
147
|
+
| Structured output consistency | System persona / role description |
|
|
148
|
+
| Demonstrate tone, format, style | Complex multi-paragraph instructions |
|
|
149
|
+
| Classification patterns | Domain context / background knowledge |
|
|
150
|
+
| Input-output mappings | Behavioral constraints |
|
|
151
|
+
|
|
152
|
+
Best practice: use `definition`/`prompt` for WHO the agent is, `examples[]` for HOW it should respond.
|
|
153
|
+
|
|
154
|
+
## Do Not Generate
|
|
155
|
+
|
|
156
|
+
- Do NOT embed examples as text in `definition` or `prompt` -- use the `examples[]` field for structured few-shot learning
|
|
157
|
+
- Do NOT include fields in examples that are not in the signature -- keys must match signature field names
|
|
158
|
+
- Do NOT provide only input fields in examples -- include BOTH input and output fields to demonstrate expected behavior
|
|
159
|
+
- Do NOT use `setExamples()` directly -- use `setExamplesCompat()` for cross-version compatibility
|
|
160
|
+
- Do NOT add excessive examples (2-5 is typical) -- too many increase token usage without proportional quality gain
|
|
161
|
+
|
|
162
|
+
## References
|
|
163
|
+
|
|
164
|
+
- [ace-customer-support.ts](../examples/ace-customer-support.ts) -- agent with structured examples and ACE feedback
|
|
165
|
+
- [basic-researcher-writer.ts](../examples/basic-researcher-writer.ts) -- simple agent config
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-functions
|
|
3
|
+
version: __VERSION__
|
|
4
|
+
description: "Functions and tools: FunctionRegistryType, AxFunction, toFunction, custom functions, AxCrewFunctions, class-based functions with state"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Functions
|
|
8
|
+
|
|
9
|
+
Agents call tools via a `FunctionRegistryType` -- a map of function names to either plain `AxFunction` objects or class-based constructors that receive shared state.
|
|
10
|
+
|
|
11
|
+
## Two Patterns
|
|
12
|
+
|
|
13
|
+
### Object-based (plain AxFunction)
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import type { AxFunction } from '@ax-llm/ax';
|
|
17
|
+
|
|
18
|
+
const MyTool: AxFunction = {
|
|
19
|
+
name: 'MyTool',
|
|
20
|
+
description: 'Does something useful',
|
|
21
|
+
parameters: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
input: { type: 'string', description: 'The input value' }
|
|
25
|
+
},
|
|
26
|
+
required: ['input']
|
|
27
|
+
},
|
|
28
|
+
func: ({ input }: { input: string }) => {
|
|
29
|
+
return `Processed: ${input}`;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Class-based (with state access)
|
|
35
|
+
|
|
36
|
+
Constructor receives shared state. Must implement `toFunction()` returning an `AxFunction`.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import type { AxFunction } from '@ax-llm/ax';
|
|
40
|
+
|
|
41
|
+
class WordPressPost {
|
|
42
|
+
private state: Record<string, any>;
|
|
43
|
+
|
|
44
|
+
constructor(state: Record<string, any>) {
|
|
45
|
+
this.state = state;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
toFunction(): AxFunction {
|
|
49
|
+
return {
|
|
50
|
+
name: 'WordPressPost',
|
|
51
|
+
description: 'Creates a post on WordPress',
|
|
52
|
+
parameters: {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: {
|
|
55
|
+
title: { type: 'string', description: 'Post title' },
|
|
56
|
+
content: { type: 'string', description: 'Post content' },
|
|
57
|
+
status: { type: 'string', description: 'Post status (draft, publish, private)' }
|
|
58
|
+
},
|
|
59
|
+
required: ['title', 'content', 'status']
|
|
60
|
+
},
|
|
61
|
+
func: async ({ title, content, status }: { title: string; content: string; status: string }) => {
|
|
62
|
+
const env = this.state.env || {};
|
|
63
|
+
const url = env.WORDPRESS_URL;
|
|
64
|
+
const username = env.WORDPRESS_USERNAME;
|
|
65
|
+
const password = env.WORDPRESS_PASSWORD;
|
|
66
|
+
// ... make API call using credentials from state
|
|
67
|
+
return { id: 123, link: `${url}/?p=123` };
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## FunctionRegistryType
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
type FunctionRegistryType = {
|
|
78
|
+
[key: string]: AxFunction | { new(state: Record<string, any>): { toFunction: () => AxFunction } };
|
|
79
|
+
};
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The registry key must match the name used in `AgentConfig.functions[]`.
|
|
83
|
+
|
|
84
|
+
## Built-in AxCrewFunctions
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { AxCrewFunctions } from '@amitdeshmukh/ax-crew';
|
|
88
|
+
// Contains: { CurrentDateTime, DaysBetweenDates }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**CurrentDateTime** -- returns current date/time in `iso`, `datetime`, or `date` format.
|
|
92
|
+
|
|
93
|
+
**DaysBetweenDates** -- calculates days between two ISO date strings. Parameters: `startDate`, `endDate`.
|
|
94
|
+
|
|
95
|
+
## Merging Registries
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { AxCrew, AxCrewFunctions } from '@amitdeshmukh/ax-crew';
|
|
99
|
+
import type { FunctionRegistryType } from '@amitdeshmukh/ax-crew';
|
|
100
|
+
|
|
101
|
+
const myFunctions: FunctionRegistryType = {
|
|
102
|
+
MyTool: MyTool,
|
|
103
|
+
WordPressPost: WordPressPost, // class-based
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Merge built-in + custom
|
|
107
|
+
const crew = new AxCrew(config, { ...AxCrewFunctions, ...myFunctions });
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then reference by name in agent config:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
{
|
|
114
|
+
name: "poster",
|
|
115
|
+
functions: ["CurrentDateTime", "WordPressPost"],
|
|
116
|
+
// ...
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Canonical Pattern
|
|
121
|
+
|
|
122
|
+
Full runnable example adapted from the WordPress example:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { AxCrew } from '@amitdeshmukh/ax-crew';
|
|
126
|
+
import type { AxCrewConfig, FunctionRegistryType } from '@amitdeshmukh/ax-crew';
|
|
127
|
+
import type { AxFunction } from '@ax-llm/ax';
|
|
128
|
+
import dotenv from 'dotenv';
|
|
129
|
+
dotenv.config();
|
|
130
|
+
|
|
131
|
+
// Plain AxFunction
|
|
132
|
+
const Summarize: AxFunction = {
|
|
133
|
+
name: 'Summarize',
|
|
134
|
+
description: 'Summarize text to a given length',
|
|
135
|
+
parameters: {
|
|
136
|
+
type: 'object',
|
|
137
|
+
properties: {
|
|
138
|
+
text: { type: 'string', description: 'Text to summarize' },
|
|
139
|
+
maxWords: { type: 'number', description: 'Maximum words' }
|
|
140
|
+
},
|
|
141
|
+
required: ['text']
|
|
142
|
+
},
|
|
143
|
+
func: ({ text, maxWords }: { text: string; maxWords?: number }) => {
|
|
144
|
+
const limit = maxWords ?? 50;
|
|
145
|
+
return text.split(' ').slice(0, limit).join(' ') + '...';
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Class-based function with state access
|
|
150
|
+
class FetchFromAPI {
|
|
151
|
+
private state: Record<string, any>;
|
|
152
|
+
constructor(state: Record<string, any>) { this.state = state; }
|
|
153
|
+
toFunction(): AxFunction {
|
|
154
|
+
return {
|
|
155
|
+
name: 'FetchFromAPI',
|
|
156
|
+
description: 'Fetch data from a configured API endpoint',
|
|
157
|
+
parameters: {
|
|
158
|
+
type: 'object',
|
|
159
|
+
properties: {
|
|
160
|
+
endpoint: { type: 'string', description: 'API endpoint path' }
|
|
161
|
+
},
|
|
162
|
+
required: ['endpoint']
|
|
163
|
+
},
|
|
164
|
+
func: async ({ endpoint }: { endpoint: string }) => {
|
|
165
|
+
const baseUrl = this.state.env?.API_BASE_URL || 'https://api.example.com';
|
|
166
|
+
const resp = await fetch(`${baseUrl}${endpoint}`);
|
|
167
|
+
return await resp.json();
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const config: AxCrewConfig = {
|
|
174
|
+
crew: [
|
|
175
|
+
{
|
|
176
|
+
name: "assistant",
|
|
177
|
+
description: "An assistant that can summarize text and fetch data",
|
|
178
|
+
signature: "request:string -> response:string",
|
|
179
|
+
provider: "openai",
|
|
180
|
+
providerKeyName: "OPENAI_API_KEY",
|
|
181
|
+
ai: { model: "gpt-4o-mini", temperature: 0.5 },
|
|
182
|
+
functions: ["Summarize", "FetchFromAPI"],
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
async function main() {
|
|
188
|
+
const customFunctions: FunctionRegistryType = {
|
|
189
|
+
Summarize,
|
|
190
|
+
FetchFromAPI,
|
|
191
|
+
};
|
|
192
|
+
const crew = new AxCrew(config, customFunctions);
|
|
193
|
+
|
|
194
|
+
// Set state for class-based functions
|
|
195
|
+
crew.state.set("env", { API_BASE_URL: "https://api.example.com" });
|
|
196
|
+
|
|
197
|
+
await crew.addAllAgents();
|
|
198
|
+
const assistant = crew.agents?.get("assistant");
|
|
199
|
+
const result = await assistant?.forward({ request: "Summarize the latest news" });
|
|
200
|
+
console.log(result?.response);
|
|
201
|
+
crew.destroy();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
main().catch(console.error);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Do Not Generate
|
|
208
|
+
|
|
209
|
+
- Do NOT define functions inline in AgentConfig; always use a `FunctionRegistryType` registry passed to the `AxCrew` constructor.
|
|
210
|
+
- Do NOT forget that class-based function constructors receive `state: Record<string, any>`, not `StateInstance`. Access values directly (e.g. `this.state.env`), since the state object is a plain record populated via `crew.state.set()`.
|
|
211
|
+
- Do NOT use a registry key that differs from the function name used in `AgentConfig.functions[]` -- they must match.
|
|
212
|
+
- Do NOT import `AxCrewFunctions` from `@ax-llm/ax`; import from `@amitdeshmukh/ax-crew`.
|
|
213
|
+
|
|
214
|
+
## References
|
|
215
|
+
|
|
216
|
+
- [write-post-and-publish-to-wordpress.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/write-post-and-publish-to-wordpress.ts)
|
|
217
|
+
- [src/functions/dateTime.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/src/functions/dateTime.ts)
|
|
218
|
+
- [src/functions/index.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/src/functions/index.ts)
|