@amitdeshmukh/ax-crew 8.6.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/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +7 -7
- 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
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-patterns
|
|
3
|
+
version: __VERSION__
|
|
4
|
+
description: "AxCrew multi-agent patterns: pipeline, delegation, fan-out, orchestrator, sequential workflows, and agent coordination."
|
|
5
|
+
tags: [patterns, workflow, pipeline, multi-agent, orchestrator, delegation, sequential, fan-out]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Multi-Agent Patterns
|
|
9
|
+
|
|
10
|
+
## Pipeline Pattern (A -> B -> C)
|
|
11
|
+
|
|
12
|
+
Sequential agent calls where each agent's output feeds the next. Each agent is independent -- the orchestration happens in your code.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { AxCrew } from "ax-crew";
|
|
16
|
+
import type { AxCrewConfig, Provider } from "ax-crew";
|
|
17
|
+
|
|
18
|
+
const config: AxCrewConfig = {
|
|
19
|
+
crew: [
|
|
20
|
+
{
|
|
21
|
+
name: "Planner",
|
|
22
|
+
description: "Generates search queries for a topic",
|
|
23
|
+
signature: 'topic:string, guidance:string -> queries:string[]',
|
|
24
|
+
provider: "anthropic" as Provider,
|
|
25
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
26
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 1 },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "Searcher",
|
|
30
|
+
description: "Searches the web for a query",
|
|
31
|
+
signature: 'query:string -> searchResult:string',
|
|
32
|
+
provider: "google-gemini" as Provider,
|
|
33
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
34
|
+
ai: { model: "gemini-1.5-pro", temperature: 0.5 },
|
|
35
|
+
options: {
|
|
36
|
+
googleSearchRetrieval: { mode: "MODE_UNSPECIFIED" },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "Writer",
|
|
41
|
+
description: "Writes a blog post from research",
|
|
42
|
+
signature: 'topic:string, guidance:string, searchResults:string[] -> title:string, content:string',
|
|
43
|
+
provider: "anthropic" as Provider,
|
|
44
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
45
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 1 },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "Publisher",
|
|
49
|
+
description: "Publishes a post to WordPress",
|
|
50
|
+
signature: 'title:string, content:string, status:string -> postResponse:string',
|
|
51
|
+
provider: "anthropic" as Provider,
|
|
52
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
53
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 0 },
|
|
54
|
+
functions: ["WordPressPost"],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
async function main() {
|
|
60
|
+
const crew = new AxCrew(config, customFunctions);
|
|
61
|
+
const agents = await crew.addAgentsToCrew([
|
|
62
|
+
"Planner", "Searcher", "Writer", "Publisher",
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
const planner = agents!.get("Planner")!;
|
|
66
|
+
const searcher = agents!.get("Searcher")!;
|
|
67
|
+
const writer = agents!.get("Writer")!;
|
|
68
|
+
const publisher = agents!.get("Publisher")!;
|
|
69
|
+
|
|
70
|
+
const topic = "How to tell what your dog is thinking";
|
|
71
|
+
const guidance = "Fun, engaging, under 500 words.";
|
|
72
|
+
|
|
73
|
+
// Step 1: Plan
|
|
74
|
+
const { queries } = await planner.forward({ topic, guidance });
|
|
75
|
+
|
|
76
|
+
// Step 2: Research (sequential to avoid rate limits)
|
|
77
|
+
const searchResults: string[] = [];
|
|
78
|
+
for (const query of queries) {
|
|
79
|
+
const { searchResult } = await searcher.forward({ query });
|
|
80
|
+
searchResults.push(searchResult);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Step 3: Write
|
|
84
|
+
const { title, content } = await writer.forward({ topic, guidance, searchResults });
|
|
85
|
+
|
|
86
|
+
// Step 4: Publish
|
|
87
|
+
const { postResponse } = await publisher.forward({ title, content, status: "draft" });
|
|
88
|
+
console.log(postResponse);
|
|
89
|
+
|
|
90
|
+
crew.destroy();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
main().catch(console.error);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Delegation Pattern (Sub-Agents)
|
|
97
|
+
|
|
98
|
+
Use `agents[]` in config to give one agent access to other agents as tools. The parent agent decides when to delegate. Sub-agents must be added to the crew **before** the parent.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const config: AxCrewConfig = {
|
|
102
|
+
crew: [
|
|
103
|
+
{
|
|
104
|
+
name: "MathAgent",
|
|
105
|
+
description: "Solves math problems using Python code execution",
|
|
106
|
+
signature: 'mathProblem:string -> solution:string',
|
|
107
|
+
provider: "google-gemini" as Provider,
|
|
108
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
109
|
+
ai: { model: "gemini-2.5-flash-lite", temperature: 0 },
|
|
110
|
+
options: { codeExecution: true },
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "ManagerAgent",
|
|
114
|
+
description: "Answers questions, delegating math to MathAgent",
|
|
115
|
+
signature: 'question:string -> answer:string',
|
|
116
|
+
provider: "google-gemini" as Provider,
|
|
117
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
118
|
+
ai: { model: "gemini-2.5-flash-lite", maxTokens: 1000, temperature: 0 },
|
|
119
|
+
agents: ["MathAgent"], // <-- delegation
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
async function main() {
|
|
125
|
+
const crew = new AxCrew(config);
|
|
126
|
+
|
|
127
|
+
// Order matters: sub-agents first, then parent
|
|
128
|
+
await crew.addAgentsToCrew(["MathAgent"]);
|
|
129
|
+
await crew.addAgentsToCrew(["ManagerAgent"]);
|
|
130
|
+
|
|
131
|
+
const manager = crew.agents!.get("ManagerAgent")!;
|
|
132
|
+
const result = await manager.forward({
|
|
133
|
+
question: "What is the 7th root of 1955?",
|
|
134
|
+
});
|
|
135
|
+
console.log(result.answer);
|
|
136
|
+
|
|
137
|
+
crew.destroy();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
main().catch(console.error);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Note: `addAgentsToCrew(["MathAgent", "ManagerAgent"])` also works -- it resolves dependencies automatically.
|
|
144
|
+
|
|
145
|
+
## Fan-Out Pattern (Parallel Agents)
|
|
146
|
+
|
|
147
|
+
Run multiple agents concurrently with `Promise.all`:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
async function main() {
|
|
151
|
+
const crew = new AxCrew(config);
|
|
152
|
+
await crew.addAllAgents();
|
|
153
|
+
|
|
154
|
+
const analyst = crew.agents!.get("Analyst")!;
|
|
155
|
+
const reviewer = crew.agents!.get("Reviewer")!;
|
|
156
|
+
const factChecker = crew.agents!.get("FactChecker")!;
|
|
157
|
+
|
|
158
|
+
const input = { document: "..." };
|
|
159
|
+
|
|
160
|
+
// Fan-out: run all three in parallel
|
|
161
|
+
const [analysis, review, facts] = await Promise.all([
|
|
162
|
+
analyst.forward(input),
|
|
163
|
+
reviewer.forward(input),
|
|
164
|
+
factChecker.forward(input),
|
|
165
|
+
]);
|
|
166
|
+
|
|
167
|
+
// Merge results downstream
|
|
168
|
+
const synthesizer = crew.agents!.get("Synthesizer")!;
|
|
169
|
+
const final = await synthesizer.forward({
|
|
170
|
+
analysis: analysis.result,
|
|
171
|
+
review: review.result,
|
|
172
|
+
facts: facts.result,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
crew.destroy();
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Orchestrator Pattern
|
|
180
|
+
|
|
181
|
+
A manager agent with multiple specialist sub-agents. The manager decides which specialist(s) to invoke based on the query.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const config: AxCrewConfig = {
|
|
185
|
+
crew: [
|
|
186
|
+
{
|
|
187
|
+
name: "CodeAgent",
|
|
188
|
+
description: "Writes and reviews code",
|
|
189
|
+
signature: "task:string -> code:string",
|
|
190
|
+
provider: "anthropic" as Provider,
|
|
191
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
192
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 0 },
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "ResearchAgent",
|
|
196
|
+
description: "Researches technical topics",
|
|
197
|
+
signature: "topic:string -> findings:string",
|
|
198
|
+
provider: "openai" as Provider,
|
|
199
|
+
providerKeyName: "OPENAI_API_KEY",
|
|
200
|
+
ai: { model: "gpt-4o", temperature: 0.5 },
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "Orchestrator",
|
|
204
|
+
description: "Routes tasks to the right specialist and synthesizes results",
|
|
205
|
+
signature: "request:string -> response:string",
|
|
206
|
+
provider: "anthropic" as Provider,
|
|
207
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
208
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 0.3 },
|
|
209
|
+
agents: ["CodeAgent", "ResearchAgent"], // can delegate to either
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
async function main() {
|
|
215
|
+
const crew = new AxCrew(config);
|
|
216
|
+
await crew.addAgentsToCrew(["CodeAgent", "ResearchAgent", "Orchestrator"]);
|
|
217
|
+
|
|
218
|
+
const orchestrator = crew.agents!.get("Orchestrator")!;
|
|
219
|
+
const result = await orchestrator.forward({
|
|
220
|
+
request: "Research WebSocket best practices and write a TypeScript echo server",
|
|
221
|
+
});
|
|
222
|
+
console.log(result.response);
|
|
223
|
+
|
|
224
|
+
crew.destroy();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
main().catch(console.error);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## definition / prompt for System Prompts
|
|
231
|
+
|
|
232
|
+
Use `definition` (or its alias `prompt`) to provide a detailed system prompt. Must be at least 100 characters. If both are set, `definition` takes precedence.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
{
|
|
236
|
+
name: "Writer",
|
|
237
|
+
description: "Short description (used as tool description for sub-agent delegation)",
|
|
238
|
+
definition: `You are a senior technical writer specializing in developer documentation.
|
|
239
|
+
Follow the Divio documentation framework: tutorials, how-to guides, reference, explanation.
|
|
240
|
+
Always include code examples. Use active voice. Keep paragraphs under 4 sentences.
|
|
241
|
+
Target audience: intermediate developers familiar with TypeScript.`,
|
|
242
|
+
signature: "topic:string -> documentation:string",
|
|
243
|
+
provider: "anthropic" as Provider,
|
|
244
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
245
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 0.7 },
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Shared State Across Agents
|
|
250
|
+
|
|
251
|
+
All agents in a crew share a mutable `state` object for out-of-band data passing:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
crew.state.set("env", { WORDPRESS_URL: "http://...", WORDPRESS_USERNAME: "..." });
|
|
255
|
+
crew.state.set("context", { userId: "abc-123" });
|
|
256
|
+
|
|
257
|
+
// Inside a custom function, state is accessible via the constructor:
|
|
258
|
+
class MyTool {
|
|
259
|
+
constructor(private state: Record<string, any>) {}
|
|
260
|
+
toFunction() {
|
|
261
|
+
return {
|
|
262
|
+
name: "myTool",
|
|
263
|
+
description: "...",
|
|
264
|
+
parameters: { ... },
|
|
265
|
+
func: async () => {
|
|
266
|
+
const env = this.state.env; // access shared state
|
|
267
|
+
// ...
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Do Not Generate
|
|
275
|
+
|
|
276
|
+
- Do NOT add a parent agent before its sub-agents -- `addAgentsToCrew` resolves dependencies but `addAgent` does not.
|
|
277
|
+
- Do NOT use `agents: ["SelfName"]` -- an agent cannot be its own sub-agent (circular dependency error).
|
|
278
|
+
- Do NOT assume agents share conversation context -- they share `state` but each `forward()` call is independent. Pass data explicitly via signatures.
|
|
279
|
+
- Do NOT use `definition` shorter than 100 characters -- Ax requires minimum length for program definitions.
|
|
280
|
+
- Do NOT confuse `description` (used as the tool description when this agent is a sub-agent) with `definition` (the system prompt).
|
|
281
|
+
|
|
282
|
+
## References
|
|
283
|
+
|
|
284
|
+
- [write-post-and-publish-to-wordpress.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/write-post-and-publish-to-wordpress.ts) (4-agent pipeline)
|
|
285
|
+
- [solve-math-problem.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/solve-math-problem.ts) (delegation)
|
|
286
|
+
- [search-tweets.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/search-tweets.ts) (streaming)
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-providers
|
|
3
|
+
version: __VERSION__
|
|
4
|
+
description: "AxCrew provider configuration: openai, anthropic, google-gemini, azure-openai, groq, ollama, mistral, cohere, grok/xAI, perplexity, and model setup."
|
|
5
|
+
tags: [provider, openai, anthropic, google-gemini, azure, groq, ollama, mistral, cohere, model, grok, perplexity]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Providers
|
|
9
|
+
|
|
10
|
+
AxCrew delegates provider instantiation to the Ax `ai()` factory. The `Provider` type is derived from Ax's `AxAIArgs['name']`, so any provider Ax supports is available.
|
|
11
|
+
|
|
12
|
+
## Provider Type
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type Provider = AxAIArgs<any>['name'];
|
|
16
|
+
// Known values: "openai", "anthropic", "google-gemini", "azure-openai",
|
|
17
|
+
// "groq", "ollama", "mistral", "cohere", "grok", "deepseek", "huggingface", etc.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## AgentConfig Provider Fields
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
interface AgentConfig {
|
|
24
|
+
provider: Provider; // e.g. "openai"
|
|
25
|
+
providerKeyName?: string; // env var name, e.g. "OPENAI_API_KEY"
|
|
26
|
+
ai: AxModelConfig & { model: string }; // model name + temperature, maxTokens, etc.
|
|
27
|
+
apiURL?: string; // custom endpoint (ollama, proxies)
|
|
28
|
+
providerArgs?: Record<string, unknown>; // provider-specific args (azure, etc.)
|
|
29
|
+
options?: Partial<AxProgramForwardOptions<any>> & Record<string, any>; // searchParameters, codeExecution, etc.
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Provider-Specific Configuration
|
|
34
|
+
|
|
35
|
+
### Azure OpenAI
|
|
36
|
+
|
|
37
|
+
Use `providerArgs` for Azure-specific fields:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
{
|
|
41
|
+
name: "AzureAgent",
|
|
42
|
+
provider: "azure-openai",
|
|
43
|
+
providerKeyName: "AZURE_OPENAI_API_KEY",
|
|
44
|
+
ai: { model: "gpt-5-mini", temperature: 0 },
|
|
45
|
+
providerArgs: {
|
|
46
|
+
resourceName: "your-resource-name",
|
|
47
|
+
deploymentName: "your-deployment-name",
|
|
48
|
+
version: "2025-01-01-preview",
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Ollama (Local)
|
|
54
|
+
|
|
55
|
+
Set `apiURL` to point at the local Ollama endpoint:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
{
|
|
59
|
+
name: "LocalAgent",
|
|
60
|
+
provider: "ollama",
|
|
61
|
+
providerKeyName: "OLLAMA_API_KEY", // can be any non-empty value
|
|
62
|
+
apiURL: "http://localhost:11434",
|
|
63
|
+
ai: { model: "llama3", temperature: 0.7 },
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Grok / xAI
|
|
68
|
+
|
|
69
|
+
Use provider `"grok"` with a Grok API key:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
{
|
|
73
|
+
name: "XSearchAgent",
|
|
74
|
+
provider: "grok",
|
|
75
|
+
providerKeyName: "GROK_API_KEY",
|
|
76
|
+
ai: { model: "grok-3-latest", temperature: 0.1 },
|
|
77
|
+
options: {
|
|
78
|
+
stream: true,
|
|
79
|
+
searchParameters: {
|
|
80
|
+
mode: "on",
|
|
81
|
+
returnCitations: true,
|
|
82
|
+
maxSearchResults: 10,
|
|
83
|
+
sources: [
|
|
84
|
+
{ type: "x" },
|
|
85
|
+
{ type: "web" },
|
|
86
|
+
{ type: "news" },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Perplexity (via MCP)
|
|
94
|
+
|
|
95
|
+
Use any provider as the agent's LLM and attach Perplexity as an MCP server:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
{
|
|
99
|
+
name: "DeepResearchAgent",
|
|
100
|
+
provider: "google-gemini",
|
|
101
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
102
|
+
ai: { model: "gemini-2.5-flash-lite", temperature: 0.1 },
|
|
103
|
+
mcpServers: {
|
|
104
|
+
"perplexity-mcp": {
|
|
105
|
+
command: "uvx",
|
|
106
|
+
args: ["perplexity-mcp"],
|
|
107
|
+
env: {
|
|
108
|
+
PERPLEXITY_API_KEY: process.env.PERPLEXITY_API_KEY,
|
|
109
|
+
PERPLEXITY_MODEL: "sonar-deep-research",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Mixed Providers in One Crew
|
|
117
|
+
|
|
118
|
+
Each agent can use a different provider. The `providerKeyName` maps to an environment variable read at runtime.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const config: AxCrewConfig = {
|
|
122
|
+
crew: [
|
|
123
|
+
{
|
|
124
|
+
name: "Planner",
|
|
125
|
+
provider: "anthropic",
|
|
126
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
127
|
+
ai: { model: "claude-3-5-sonnet-20240620", temperature: 1 },
|
|
128
|
+
signature: "topic:string -> queries:string[]",
|
|
129
|
+
description: "Generates search queries",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "Searcher",
|
|
133
|
+
provider: "google-gemini",
|
|
134
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
135
|
+
ai: { model: "gemini-1.5-pro", temperature: 0.5 },
|
|
136
|
+
signature: "query:string -> results:string",
|
|
137
|
+
description: "Searches the web",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "Writer",
|
|
141
|
+
provider: "openai",
|
|
142
|
+
providerKeyName: "OPENAI_API_KEY",
|
|
143
|
+
ai: { model: "gpt-4o", temperature: 0.8 },
|
|
144
|
+
signature: "topic:string, results:string[] -> post:string",
|
|
145
|
+
description: "Writes content from research",
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Canonical Pattern
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { AxCrew } from "ax-crew";
|
|
155
|
+
import type { AxCrewConfig } from "ax-crew";
|
|
156
|
+
|
|
157
|
+
const config: AxCrewConfig = {
|
|
158
|
+
crew: [
|
|
159
|
+
{
|
|
160
|
+
name: "TestAgent",
|
|
161
|
+
description: "Test Agent for Azure OpenAI",
|
|
162
|
+
provider: "azure-openai",
|
|
163
|
+
providerKeyName: "AZURE_OPENAI_API_KEY",
|
|
164
|
+
signature: "userQuery:string -> answer:string",
|
|
165
|
+
ai: { model: "gpt-5-mini", temperature: 0 },
|
|
166
|
+
providerArgs: {
|
|
167
|
+
resourceName: "your-resource-name",
|
|
168
|
+
deploymentName: "your-deployment-name",
|
|
169
|
+
version: "2025-01-01-preview",
|
|
170
|
+
},
|
|
171
|
+
options: { debug: true, stream: false },
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
async function main() {
|
|
177
|
+
const crew = new AxCrew(config);
|
|
178
|
+
await crew.addAllAgents();
|
|
179
|
+
|
|
180
|
+
const agent = crew.agents?.get("TestAgent");
|
|
181
|
+
const response = await agent?.forward({ userQuery: "What is the capital of France?" });
|
|
182
|
+
console.log(response?.answer);
|
|
183
|
+
|
|
184
|
+
crew.destroy();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
main().catch(console.error);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Do Not Generate
|
|
191
|
+
|
|
192
|
+
- Do NOT hardcode API keys in config -- always use `providerKeyName` which reads from `process.env`.
|
|
193
|
+
- Do NOT use `providerArgs` for non-Azure providers unless the Ax factory documents it -- standard providers only need `provider`, `providerKeyName`, `ai`, and optionally `apiURL`.
|
|
194
|
+
- Do NOT confuse `options.searchParameters` (Grok-specific forward option) with `mcpServers` (external tool servers).
|
|
195
|
+
- Do NOT set `provider: "perplexity"` -- Perplexity is accessed via an MCP server, not as a native Ax provider.
|
|
196
|
+
- Do NOT omit `providerKeyName` -- the crew will throw at initialization if the env var is missing.
|
|
197
|
+
|
|
198
|
+
## References
|
|
199
|
+
|
|
200
|
+
- [providerArgs.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/providerArgs.ts) (Azure OpenAI)
|
|
201
|
+
- [search-tweets.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/search-tweets.ts) (Grok/xAI)
|
|
202
|
+
- [perplexityDeepSearch.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/perplexityDeepSearch.ts) (Perplexity MCP)
|
|
203
|
+
- [write-post-and-publish-to-wordpress.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/write-post-and-publish-to-wordpress.ts) (mixed providers)
|
|
204
|
+
- [src/agents/compose.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/src/agents/compose.ts)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew-signatures
|
|
3
|
+
description: AxCrew DSPy-style signature format for defining agent inputs/outputs. Covers signature syntax, types (string, number, boolean, class, string[], json, image, audio, date), optional fields (?), field descriptions, and AxSignature builder alternative.
|
|
4
|
+
version: "__VERSION__"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AxCrew Signatures
|
|
8
|
+
|
|
9
|
+
DSPy-style string format: `"input1:type, input2:type -> output1:type, output2:type"`
|
|
10
|
+
|
|
11
|
+
## Supported Types
|
|
12
|
+
|
|
13
|
+
| Type | Description |
|
|
14
|
+
|------|-------------|
|
|
15
|
+
| `string` | Text (default if omitted) |
|
|
16
|
+
| `number` | Numeric |
|
|
17
|
+
| `boolean` | True/false |
|
|
18
|
+
| `string[]` | Array of strings |
|
|
19
|
+
| `json` | Arbitrary JSON object |
|
|
20
|
+
| `class` | Classification label |
|
|
21
|
+
| `image` | Image input |
|
|
22
|
+
| `audio` | Audio input |
|
|
23
|
+
| `date` | Date value |
|
|
24
|
+
|
|
25
|
+
## Signature Syntax
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Minimal — types default to string
|
|
29
|
+
"question -> answer"
|
|
30
|
+
|
|
31
|
+
// Explicit types
|
|
32
|
+
"question:string -> answer:string"
|
|
33
|
+
|
|
34
|
+
// Multiple inputs and outputs
|
|
35
|
+
"question:string, context:string -> answer:string, confidence:number"
|
|
36
|
+
|
|
37
|
+
// Optional fields use ? suffix
|
|
38
|
+
"query:string, context?:string -> answer:string"
|
|
39
|
+
|
|
40
|
+
// Field descriptions in quotes
|
|
41
|
+
'question:string "The user question", context:string "Reference text" -> answer:string "Final answer", confidence:number "0-1 score"'
|
|
42
|
+
|
|
43
|
+
// Array output
|
|
44
|
+
'context:string, query:string -> answer:string, keyFindings:string[] "Analyzes context and returns findings"'
|
|
45
|
+
|
|
46
|
+
// Classification
|
|
47
|
+
"text:string -> sentiment:class"
|
|
48
|
+
|
|
49
|
+
// Multi-modal
|
|
50
|
+
"image:image, question:string -> caption:string"
|
|
51
|
+
|
|
52
|
+
// JSON output
|
|
53
|
+
"query:string -> result:json"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Full Examples in AgentConfig
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { AxCrew } from 'ax-crew';
|
|
60
|
+
import type { AxCrewConfig } from 'ax-crew';
|
|
61
|
+
|
|
62
|
+
const config: AxCrewConfig = {
|
|
63
|
+
crew: [
|
|
64
|
+
// Simple Q&A
|
|
65
|
+
{
|
|
66
|
+
name: "QA",
|
|
67
|
+
description: "Answers questions",
|
|
68
|
+
signature: "question:string -> answer:string",
|
|
69
|
+
provider: "openai",
|
|
70
|
+
ai: { model: "gpt-4o", temperature: 0 },
|
|
71
|
+
},
|
|
72
|
+
// Multi-field with descriptions
|
|
73
|
+
{
|
|
74
|
+
name: "Analyst",
|
|
75
|
+
description: "Analyzes data and returns structured findings",
|
|
76
|
+
signature:
|
|
77
|
+
'context:string, query:string -> answer:string, keyFindings:string[] "Analyzes context and returns findings"',
|
|
78
|
+
provider: "google-gemini",
|
|
79
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
80
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
81
|
+
},
|
|
82
|
+
// Optional input field
|
|
83
|
+
{
|
|
84
|
+
name: "Summarizer",
|
|
85
|
+
description: "Summarizes text with optional style",
|
|
86
|
+
signature: "text:string, style?:string -> summary:string",
|
|
87
|
+
provider: "openai",
|
|
88
|
+
ai: { model: "gpt-4o-mini" },
|
|
89
|
+
},
|
|
90
|
+
// Classification
|
|
91
|
+
{
|
|
92
|
+
name: "Classifier",
|
|
93
|
+
description: "Classifies sentiment",
|
|
94
|
+
signature: 'question:string -> sentiment:string "positive, negative, or neutral"',
|
|
95
|
+
provider: "google-gemini",
|
|
96
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
97
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
98
|
+
},
|
|
99
|
+
// Multi-output with confidence
|
|
100
|
+
{
|
|
101
|
+
name: "Extractor",
|
|
102
|
+
description: "Extracts entities from text",
|
|
103
|
+
signature: "text:string -> entities:string[], confidence:number",
|
|
104
|
+
provider: "openai",
|
|
105
|
+
ai: { model: "gpt-4o" },
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
async function main() {
|
|
111
|
+
const crew = new AxCrew(config);
|
|
112
|
+
await crew.addAllAgents();
|
|
113
|
+
|
|
114
|
+
const qa = crew.agents?.get("QA");
|
|
115
|
+
const result = await qa?.forward({ question: "What is TypeScript?" });
|
|
116
|
+
console.log(result?.answer);
|
|
117
|
+
|
|
118
|
+
const analyst = crew.agents?.get("Analyst");
|
|
119
|
+
const analysis = await analyst?.forward({
|
|
120
|
+
context: "Q1 revenue: $10M, Q2: $15M, Q3: $12M",
|
|
121
|
+
query: "What is the revenue trend?",
|
|
122
|
+
});
|
|
123
|
+
console.log(analysis?.answer, analysis?.keyFindings);
|
|
124
|
+
|
|
125
|
+
crew.destroy();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main().catch(console.error);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## AxSignature Builder Alternative
|
|
132
|
+
|
|
133
|
+
The `signature` field also accepts an `AxSignature` object from `@ax-llm/ax`:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { AxSignature } from '@ax-llm/ax';
|
|
137
|
+
import type { AxCrewConfig } from 'ax-crew';
|
|
138
|
+
|
|
139
|
+
const sig = new AxSignature(
|
|
140
|
+
"question:string, context:string -> answer:string, confidence:number"
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const config: AxCrewConfig = {
|
|
144
|
+
crew: [
|
|
145
|
+
{
|
|
146
|
+
name: "Agent",
|
|
147
|
+
description: "Uses AxSignature object",
|
|
148
|
+
signature: sig, // AxSignature instance accepted
|
|
149
|
+
provider: "openai",
|
|
150
|
+
ai: { model: "gpt-4o" },
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Do Not Generate
|
|
157
|
+
|
|
158
|
+
- Do NOT omit the `->` separator between inputs and outputs
|
|
159
|
+
- Do NOT use unsupported types (e.g., `int`, `float`, `array`, `object` -- use `number`, `string[]`, `json`)
|
|
160
|
+
- Do NOT put field descriptions outside quotes: use `'field:type "desc"'` not `field:type desc`
|
|
161
|
+
- Do NOT use `|` or union types in signatures -- use `class` type for enums
|
|
162
|
+
- Do NOT confuse `string[]` (array of strings) with `json` (arbitrary object)
|
|
163
|
+
- Do NOT wrap the signature string in `AxSignature()` when passing to config -- raw strings work directly
|
|
164
|
+
|
|
165
|
+
## References
|
|
166
|
+
|
|
167
|
+
- [rlm-long-task.ts](../examples/rlm-long-task.ts) -- array output in signature
|
|
168
|
+
- [rlm-shared-fields.ts](../examples/rlm-shared-fields.ts) -- field descriptions in quotes
|
|
169
|
+
- [ace-customer-support.ts](../examples/ace-customer-support.ts) -- multi-output signature
|