@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.
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: ax-crew-mcp
3
+ version: "__VERSION__"
4
+ description: "ax-crew MCP integration: MCP, Model Context Protocol, STDIO, HTTP SSE, Streamable HTTP, mcpServers, tools, tool filtering, multiple servers"
5
+ argument-hint: [topic]
6
+ allowed-tools: Read, Grep, Glob
7
+ ---
8
+
9
+ # ax-crew MCP (Model Context Protocol)
10
+
11
+ MCP servers expose external tools to agents. Configured per-agent via `mcpServers` in the agent config. Transport type is auto-detected by config shape.
12
+
13
+ ## Three Transport Types
14
+
15
+ ### STDIO (local process)
16
+
17
+ ```typescript
18
+ mcpServers: {
19
+ "context7": {
20
+ command: "npx", // required
21
+ args: ["-y", "@upstash/context7-mcp"], // optional
22
+ env: { API_KEY: "..." }, // optional
23
+ tools: ["resolve-library-id", "query-docs"], // optional allowlist
24
+ }
25
+ }
26
+ ```
27
+
28
+ Type: `MCPStdioTransportConfig = { command: string; args?: string[]; env?: NodeJS.ProcessEnv; tools?: string[] }`
29
+
30
+ ### HTTP SSE (remote, server-sent events)
31
+
32
+ ```typescript
33
+ mcpServers: {
34
+ "api-server": {
35
+ sseUrl: "https://api.example.com/mcp/sse", // required
36
+ tools: ["search", "fetch"], // optional allowlist
37
+ }
38
+ }
39
+ ```
40
+
41
+ Type: `MCPHTTPSSETransportConfig = { sseUrl: string; tools?: string[] }`
42
+
43
+ ### Streamable HTTP (bidirectional)
44
+
45
+ ```typescript
46
+ mcpServers: {
47
+ "graphjin": {
48
+ mcpEndpoint: "http://localhost:8080/api/v1/mcp", // required
49
+ options: { timeout: 30000 }, // optional AxMCPStreamableHTTPTransportOptions
50
+ tools: ["list_workflows", "execute_workflow"], // optional allowlist
51
+ }
52
+ }
53
+ ```
54
+
55
+ Type: `MCPStreamableHTTPTransportConfig = { mcpEndpoint: string; options?: AxMCPStreamableHTTPTransportOptions; tools?: string[] }`
56
+
57
+ ## tools[] Allowlist
58
+
59
+ When `tools` is specified, only those MCP tool names are exposed to the agent. This reduces token usage and prevents the agent from calling unwanted tools.
60
+
61
+ ```typescript
62
+ mcpServers: {
63
+ "big-server": {
64
+ command: "npx",
65
+ args: ["-y", "some-mcp-server"],
66
+ tools: ["only_this_tool", "and_this_one"], // filter from all available
67
+ }
68
+ }
69
+ ```
70
+
71
+ If `tools` is omitted or empty, all tools from the MCP server are exposed.
72
+
73
+ ## Multiple MCP Servers Per Agent
74
+
75
+ An agent can connect to multiple MCP servers simultaneously. All tools are merged:
76
+
77
+ ```typescript
78
+ {
79
+ name: "MultiToolAgent",
80
+ description: "Agent with multiple MCP servers",
81
+ signature: 'query:string -> answer:string',
82
+ provider: "google-gemini",
83
+ providerKeyName: "GEMINI_API_KEY",
84
+ ai: { model: "gemini-2.5-pro", temperature: 0 },
85
+ mcpServers: {
86
+ "filesystem": {
87
+ command: "npx",
88
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
89
+ },
90
+ "database": {
91
+ mcpEndpoint: "http://localhost:8080/api/v1/mcp",
92
+ tools: ["query", "describe_table"],
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Canonical Pattern
99
+
100
+ ### STDIO transport (from mcp-agent.ts)
101
+
102
+ ```typescript
103
+ import { AxCrew } from '@amitdeshmukh/ax-crew';
104
+ import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
105
+
106
+ const config: AxCrewConfig = {
107
+ crew: [
108
+ {
109
+ name: "Context7DocsAgent",
110
+ description: "Agent with access to Context7 Docs APIs",
111
+ signature: 'apiDocQuery:string "a question" -> apiDocAnswer:string "the answer"',
112
+ provider: "google-gemini",
113
+ providerKeyName: "GEMINI_API_KEY",
114
+ ai: { model: "gemini-2.5-pro", temperature: 0 },
115
+ options: { debug: true },
116
+ mcpServers: {
117
+ "context7": {
118
+ command: "npx",
119
+ args: ["-y", "@upstash/context7-mcp", "--api-key", process.env.CONTEXT7_API_KEY!],
120
+ },
121
+ },
122
+ },
123
+ {
124
+ name: "ManagerAgent",
125
+ description: "Orchestrates sub-agents",
126
+ signature: 'question:string -> answer:string',
127
+ provider: "google-gemini",
128
+ providerKeyName: "GEMINI_API_KEY",
129
+ ai: { model: "gemini-2.5-pro", maxTokens: 1000, temperature: 0 },
130
+ agents: ["Context7DocsAgent"],
131
+ },
132
+ ],
133
+ };
134
+
135
+ async function main() {
136
+ const crew = new AxCrew(config);
137
+ try {
138
+ await crew.addAllAgents();
139
+
140
+ const manager = crew.agents?.get("ManagerAgent");
141
+ if (!manager) throw new Error("Agent not found");
142
+
143
+ const result = await manager.forward({
144
+ question: "How do I configure MCP servers in ax-crew?",
145
+ });
146
+ console.log("Answer:", result.answer);
147
+ } finally {
148
+ crew.destroy();
149
+ }
150
+ }
151
+
152
+ main().catch(console.error);
153
+ ```
154
+
155
+ ### Streamable HTTP transport (from graphjin-database-agent.ts)
156
+
157
+ ```typescript
158
+ import { AxCrew } from '@amitdeshmukh/ax-crew';
159
+ import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
160
+
161
+ const config: AxCrewConfig = {
162
+ crew: [
163
+ {
164
+ name: "DatabaseAgent",
165
+ description: "Agent with direct database access via GraphJin",
166
+ signature: 'dbQuery:string "a database question" -> dbResult:string "the result"',
167
+ provider: "google-gemini",
168
+ providerKeyName: "GEMINI_API_KEY",
169
+ ai: { model: "gemini-2.5-pro", temperature: 0 },
170
+ mcpServers: {
171
+ "graphjin": {
172
+ command: "graphjin",
173
+ args: ["mcp", "--server", "http://localhost:8080"],
174
+ },
175
+ },
176
+ },
177
+ {
178
+ name: "ManagerAgent",
179
+ description: "Orchestrates database queries",
180
+ signature: 'question:string -> answer:string',
181
+ provider: "google-gemini",
182
+ providerKeyName: "GEMINI_API_KEY",
183
+ ai: { model: "gemini-2.5-pro", maxTokens: 2000, temperature: 0 },
184
+ agents: ["DatabaseAgent"],
185
+ },
186
+ ],
187
+ };
188
+
189
+ async function main() {
190
+ const crew = new AxCrew(config);
191
+ try {
192
+ await crew.addAllAgents();
193
+ const manager = crew.agents?.get("ManagerAgent");
194
+ if (!manager) throw new Error("Agent not found");
195
+
196
+ const result = await manager.forward({
197
+ question: "What tables are available in the database?",
198
+ });
199
+ console.log("Answer:", result.answer);
200
+ } finally {
201
+ crew.destroy();
202
+ }
203
+ }
204
+
205
+ main().catch(console.error);
206
+ ```
207
+
208
+ ## Do Not Generate
209
+
210
+ - Do NOT mix transport config keys -- use exactly one of `command`, `sseUrl`, or `mcpEndpoint` per server entry.
211
+ - Do NOT forget `crew.destroy()` -- MCP STDIO processes must be cleaned up.
212
+ - Do NOT put `mcpServers` at the crew level -- it is per-agent only.
213
+ - Do NOT assume MCP tools have `parameters` -- some zero-arg tools omit it; ax-crew normalizes this automatically.
214
+ - Do NOT use `AxMCPStdioTransport` directly -- ax-crew handles transport creation internally from config.
215
+
216
+ ## References
217
+
218
+ - [mcp-agent.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/mcp-agent.ts)
219
+ - [graphjin-database-agent.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/graphjin-database-agent.ts)
220
+ - [Source: agentConfig.ts (initializeMCPServers)](https://github.com/amitdeshmukh/ax-crew/blob/main/src/agents/agentConfig.ts)
221
+ - [Types: MCPStdioTransportConfig, MCPHTTPSSETransportConfig, MCPStreamableHTTPTransportConfig](https://github.com/amitdeshmukh/ax-crew/blob/main/src/types.ts)
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: ax-crew-metrics
3
+ version: "__VERSION__"
4
+ description: "ax-crew metrics and cost tracking: metrics, cost, tracking, getMetrics, getCrewMetrics, MetricsSnapshot, usage, tokens, estimatedCostUSD, resetCosts, resetCrewMetrics"
5
+ argument-hint: [topic]
6
+ allowed-tools: Read, Grep, Glob
7
+ ---
8
+
9
+ # ax-crew Metrics & Cost Tracking
10
+
11
+ ## Per-Agent: agent.getMetrics()
12
+
13
+ Returns a `MetricsSnapshot` scoped to this agent within its crew.
14
+
15
+ ```typescript
16
+ const agent = crew.agents?.get("MyAgent");
17
+ const metrics = agent.getMetrics();
18
+ ```
19
+
20
+ ## Crew-Level: crew.getCrewMetrics()
21
+
22
+ Returns a `MetricsSnapshot` aggregated across all agents in the crew.
23
+
24
+ ```typescript
25
+ const crewMetrics = crew.getCrewMetrics();
26
+ ```
27
+
28
+ ## MetricsSnapshot Shape
29
+
30
+ ```typescript
31
+ interface MetricsSnapshot {
32
+ provider?: string;
33
+ model?: string;
34
+ requests: {
35
+ totalRequests: number;
36
+ totalErrors: number;
37
+ errorRate: number; // errors / requests
38
+ totalStreamingRequests: number;
39
+ durationMsSum: number;
40
+ durationCount: number;
41
+ };
42
+ tokens: {
43
+ promptTokens: number;
44
+ completionTokens: number;
45
+ totalTokens?: number;
46
+ };
47
+ estimatedCostUSD: number; // rounded to 5 decimal places
48
+ functions: {
49
+ totalFunctionCalls: number;
50
+ totalFunctionLatencyMs: number;
51
+ details?: Array<{ // per-function breakdown
52
+ name: string;
53
+ calls: number;
54
+ totalLatencyMs: number;
55
+ }>;
56
+ };
57
+ }
58
+ ```
59
+
60
+ ## Reset Methods
61
+
62
+ ```typescript
63
+ // Reset all cost/usage tracking for the entire crew (resets agent usage + metrics)
64
+ crew.resetCosts();
65
+
66
+ // Reset only the metrics registry for the crew
67
+ crew.resetCrewMetrics();
68
+ ```
69
+
70
+ `resetCosts()` calls `resetUsage()` and `resetMetrics()` on each agent, then clears crew-level metrics.
71
+ `resetCrewMetrics()` only clears the MetricsRegistry entries for this crew.
72
+
73
+ ## Canonical Pattern
74
+
75
+ ```typescript
76
+ import { AxCrew, AxCrewFunctions } from '@amitdeshmukh/ax-crew';
77
+ import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
78
+
79
+ const config: AxCrewConfig = {
80
+ crew: [
81
+ {
82
+ name: "researcher",
83
+ description: "A research agent that finds information",
84
+ signature: "query:string -> research:string",
85
+ provider: "google-gemini",
86
+ providerKeyName: "GEMINI_API_KEY",
87
+ ai: { model: "gemini-2.5-flash-lite", maxTokens: 4000, stream: true },
88
+ functions: ["CurrentDateTime"],
89
+ },
90
+ {
91
+ name: "writer",
92
+ description: "A writing agent that creates content",
93
+ signature: "topic:string -> article:string",
94
+ provider: "google-gemini",
95
+ providerKeyName: "GEMINI_API_KEY",
96
+ ai: { model: "gemini-2.5-flash-lite", maxTokens: 4000, stream: true },
97
+ agents: ["researcher"],
98
+ },
99
+ ],
100
+ };
101
+
102
+ async function main() {
103
+ const crew = new AxCrew(config, AxCrewFunctions);
104
+ await crew.addAgentsToCrew(["researcher"]);
105
+ await crew.addAgentsToCrew(["writer"]);
106
+
107
+ const writer = crew.agents?.get("writer");
108
+ const researcher = crew.agents?.get("researcher");
109
+ if (!writer || !researcher) throw new Error("Failed to initialize agents");
110
+
111
+ try {
112
+ const { article } = await writer.forward({
113
+ topic: "Quantum Computing Benefits",
114
+ });
115
+ console.log("Article:", article);
116
+
117
+ // Per-agent metrics
118
+ console.log("Writer Metrics:", JSON.stringify(writer.getMetrics?.(), null, 2));
119
+ console.log("Researcher Metrics:", JSON.stringify(researcher.getMetrics?.(), null, 2));
120
+
121
+ // Crew-wide aggregate
122
+ console.log("Crew Metrics:", JSON.stringify(crew.getCrewMetrics(), null, 2));
123
+
124
+ // Reset for next measurement period
125
+ crew.resetCosts();
126
+ } finally {
127
+ crew.destroy();
128
+ }
129
+ }
130
+
131
+ main().catch(console.error);
132
+ ```
133
+
134
+ ## Accessing Specific Fields
135
+
136
+ ```typescript
137
+ const m = agent.getMetrics();
138
+
139
+ // Cost
140
+ console.log(`Estimated USD: ${m?.estimatedCostUSD ?? 0}`);
141
+
142
+ // Tokens
143
+ console.log(`Prompt: ${m?.tokens?.promptTokens}, Completion: ${m?.tokens?.completionTokens}, Total: ${m?.tokens?.totalTokens}`);
144
+
145
+ // Request stats
146
+ console.log(`Requests: ${m?.requests?.totalRequests}, Errors: ${m?.requests?.totalErrors}`);
147
+
148
+ // Function calls
149
+ console.log(`Function calls: ${m?.functions?.totalFunctionCalls}`);
150
+ if (m?.functions?.details) {
151
+ for (const fn of m.functions.details) {
152
+ console.log(` ${fn.name}: ${fn.calls} calls, ${fn.totalLatencyMs}ms`);
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Do Not Generate
158
+
159
+ - Do NOT call `getMetrics()` on the crew object -- use `crew.getCrewMetrics()` for crew-level and `agent.getMetrics()` for per-agent.
160
+ - Do NOT confuse `resetCosts()` with `resetCrewMetrics()` -- `resetCosts()` is broader (resets agent usage too).
161
+ - Do NOT expect `getMetrics()` to return cost data from the legacy `getUsage()` / `getCosts()` API -- those are separate.
162
+ - Do NOT assume `functions.details` is always present -- it is `undefined` when no function calls have been made.
163
+ - Do NOT forget that `estimatedCostUSD` is an estimate based on tracked token counts and model pricing.
164
+
165
+ ## References
166
+
167
+ - [basic-researcher-writer.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/basic-researcher-writer.ts)
168
+ - [rlm-long-task.ts example](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/rlm-long-task.ts)
169
+ - [Source: MetricsSnapshot type](https://github.com/amitdeshmukh/ax-crew/blob/main/src/metrics/types.ts)
170
+ - [Source: MetricsRegistry](https://github.com/amitdeshmukh/ax-crew/blob/main/src/metrics/registry.ts)
@@ -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)