@amitdeshmukh/ax-crew 8.7.3 → 9.0.1
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/CHANGELOG.md +40 -0
- package/README.md +9 -9
- package/dist/agents/agentConfig.d.ts +3 -0
- package/dist/agents/agentConfig.js +12 -4
- package/dist/agents/crew.d.ts +59 -0
- package/dist/agents/crew.js +356 -0
- package/dist/agents/deferredTools.d.ts +49 -0
- package/dist/agents/deferredTools.js +237 -0
- package/dist/agents/index.d.ts +4 -266
- package/dist/agents/index.js +3 -1014
- package/dist/agents/lazyAgent.d.ts +33 -0
- package/dist/agents/lazyAgent.js +78 -0
- package/dist/agents/statefulAgent.d.ts +97 -0
- package/dist/agents/statefulAgent.js +478 -0
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +18 -1
- package/examples/graphjin-database-agent.ts +85 -64
- package/examples/write-post-and-publish-to-wordpress.ts +1 -1
- package/package.json +1 -1
- package/src/agents/agentConfig.ts +15 -8
- package/src/agents/crew.ts +444 -0
- package/src/agents/deferredTools.ts +275 -0
- package/src/agents/index.ts +4 -1281
- package/src/agents/lazyAgent.ts +95 -0
- package/src/agents/statefulAgent.ts +668 -0
- package/src/index.ts +7 -4
- package/src/skills/axcrew-functions.md +2 -2
- package/src/skills/axcrew-mcp.md +41 -1
- package/src/skills/axcrew-patterns.md +48 -4
- package/src/skills/axcrew-state.md +16 -16
- package/src/skills/axcrew.md +14 -1
- package/src/types.ts +19 -0
- package/.claude/settings.local.json +0 -13
- package/.claude/skills/ax-crew/SKILL.md +0 -466
|
@@ -192,7 +192,7 @@ async function main() {
|
|
|
192
192
|
const crew = new AxCrew(config, customFunctions);
|
|
193
193
|
|
|
194
194
|
// Set state for class-based functions
|
|
195
|
-
crew.
|
|
195
|
+
crew.crewState.set("env", { API_BASE_URL: "https://api.example.com" });
|
|
196
196
|
|
|
197
197
|
await crew.addAllAgents();
|
|
198
198
|
const assistant = crew.agents?.get("assistant");
|
|
@@ -210,7 +210,7 @@ main().catch(console.error);
|
|
|
210
210
|
## Do Not Generate
|
|
211
211
|
|
|
212
212
|
- Do NOT define functions inline in AgentConfig; always use a `FunctionRegistryType` registry passed to the `AxCrew` constructor.
|
|
213
|
-
- 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.
|
|
213
|
+
- 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.crewState.set()`.
|
|
214
214
|
- Do NOT use a registry key that differs from the function name used in `AgentConfig.functions[]` -- they must match.
|
|
215
215
|
- Do NOT import `AxCrewFunctions` from `@ax-llm/ax`; import from `@amitdeshmukh/ax-crew`.
|
|
216
216
|
|
package/src/skills/axcrew-mcp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: axcrew-mcp
|
|
3
|
-
version: "
|
|
3
|
+
version: "9.0.0"
|
|
4
4
|
description: "ax-crew MCP integration: MCP, Model Context Protocol, STDIO, HTTP SSE, Streamable HTTP, mcpServers, tools, tool filtering, multiple servers"
|
|
5
5
|
argument-hint: [topic]
|
|
6
6
|
allowed-tools: Read, Grep, Glob
|
|
@@ -205,6 +205,46 @@ async function main() {
|
|
|
205
205
|
main().catch(console.error);
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
## Deferred Tool Loading
|
|
209
|
+
|
|
210
|
+
When an agent has many MCP tools (20+), use the `deferredTools` config to reduce token usage. Only core tools + a `search_tools` meta-function are sent to the LLM. The LLM discovers additional tools on demand. Discovered tools persist across `forward()` calls. Tool results that mention deferred tool names (e.g., error responses suggesting `fix_query_error`) auto-activate those tools.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
{
|
|
214
|
+
name: "BigMCPAgent",
|
|
215
|
+
description: "Agent with many MCP tools",
|
|
216
|
+
signature: 'query:string -> answer:string',
|
|
217
|
+
provider: "anthropic",
|
|
218
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
219
|
+
ai: { model: "claude-sonnet-4-6", temperature: 0 },
|
|
220
|
+
mcpServers: {
|
|
221
|
+
"large-server": {
|
|
222
|
+
command: "npx",
|
|
223
|
+
args: ["-y", "some-large-mcp-server"],
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
deferredTools: {
|
|
227
|
+
enabled: true, // default: auto (true when tool count > threshold)
|
|
228
|
+
threshold: 20, // tool count to activate deferred mode
|
|
229
|
+
maxSearchResults: 10, // max tools returned per search
|
|
230
|
+
coreTools: ["execute_graphql", "list_tables"], // always keep active
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### What is "core" vs "deferred"
|
|
236
|
+
|
|
237
|
+
- **Core** (always visible): custom functions, sub-agent functions, `resource_*` functions, explicitly listed `coreTools`
|
|
238
|
+
- **Deferred** (discoverable via search): MCP tool functions (except `resource_*`)
|
|
239
|
+
|
|
240
|
+
### Resource Caching
|
|
241
|
+
|
|
242
|
+
MCP `resource_*` functions (reference docs like query syntax guides) are automatically cached in-memory. Repeated calls return the cached result without re-fetching from the MCP server.
|
|
243
|
+
|
|
244
|
+
## Prompt Caching
|
|
245
|
+
|
|
246
|
+
Prompt caching is enabled by default for all agents. System prompts and tool definitions are cached across multi-step interactions via Anthropic's implicit caching or Gemini's context caching. This reduces token costs by up to 6x for agents with many tools — the system prompt (~13K tokens of tool schemas) is processed once and reused on subsequent steps.
|
|
247
|
+
|
|
208
248
|
## Supporting files
|
|
209
249
|
- See [examples/mcp-agent.ts](examples/mcp-agent.ts) for a complete runnable example.
|
|
210
250
|
- See [examples/graphjin-database-agent.ts](examples/graphjin-database-agent.ts) for Streamable HTTP transport.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: axcrew-patterns
|
|
3
|
-
version:
|
|
3
|
+
version: 9.0.0
|
|
4
4
|
description: "AxCrew multi-agent patterns: pipeline, delegation, fan-out, orchestrator, sequential workflows, and agent coordination."
|
|
5
5
|
tags: [patterns, workflow, pipeline, multi-agent, orchestrator, delegation, sequential, fan-out]
|
|
6
6
|
---
|
|
@@ -251,8 +251,8 @@ Target audience: intermediate developers familiar with TypeScript.`,
|
|
|
251
251
|
All agents in a crew share a mutable `state` object for out-of-band data passing:
|
|
252
252
|
|
|
253
253
|
```ts
|
|
254
|
-
crew.
|
|
255
|
-
crew.
|
|
254
|
+
crew.crewState.set("env", { WORDPRESS_URL: "http://...", WORDPRESS_USERNAME: "..." });
|
|
255
|
+
crew.crewState.set("context", { userId: "abc-123" });
|
|
256
256
|
|
|
257
257
|
// Inside a custom function, state is accessible via the constructor:
|
|
258
258
|
class MyTool {
|
|
@@ -271,17 +271,61 @@ class MyTool {
|
|
|
271
271
|
}
|
|
272
272
|
```
|
|
273
273
|
|
|
274
|
+
## Cost Optimization Pattern (Single-Delegation Manager)
|
|
275
|
+
|
|
276
|
+
When a manager orchestrates sub-agents, use a **single-delegation** pattern: send the full question to the sub-agent in one call. Do NOT break questions into sub-queries — the sub-agent handles multi-step work internally.
|
|
277
|
+
|
|
278
|
+
This pattern reduced costs from $128 to $1 on the same query in testing.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
{
|
|
282
|
+
name: "ManagerAgent",
|
|
283
|
+
description: "Orchestrates database queries and analysis tasks",
|
|
284
|
+
definition: `You are an orchestrator that routes questions to specialized agents.
|
|
285
|
+
Delegate each question to the most relevant agent in a SINGLE call — do not break questions into sub-queries.
|
|
286
|
+
The sub-agent will handle all the steps internally. Your job is to route and synthesize, not to decompose.
|
|
287
|
+
If multiple agents are needed, call them and combine their answers.`,
|
|
288
|
+
signature: 'question:string -> answer:string',
|
|
289
|
+
provider: "anthropic" as Provider,
|
|
290
|
+
providerKeyName: "ANTHROPIC_API_KEY",
|
|
291
|
+
ai: { model: "claude-sonnet-4-6", maxTokens: 2000, temperature: 0 },
|
|
292
|
+
agents: ["DatabaseAgent", "AnalyticsAgent"],
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Workflow Reuse Pattern (MCP Agents)
|
|
297
|
+
|
|
298
|
+
For agents connected to MCP servers, use a strategy-driven definition that checks for saved workflows before building new ones. This ensures repeat questions reuse cached workflows ($0.17) instead of rebuilding from scratch ($0.55).
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
{
|
|
302
|
+
name: "DatabaseAgent",
|
|
303
|
+
definition: `You answer questions by querying databases via an MCP server.
|
|
304
|
+
|
|
305
|
+
STRATEGY:
|
|
306
|
+
1. Check first — call list_workflows and list_saved_queries. If a match exists, execute it directly.
|
|
307
|
+
2. Learn — read resource docs, list tables, describe schema.
|
|
308
|
+
3. Build — author a JS workflow with server-side computation, validate with a test query.
|
|
309
|
+
4. Save and run — save the workflow for reuse, then execute it.
|
|
310
|
+
5. If a query fails, call fix_query_error to diagnose. Do not retry the same query.
|
|
311
|
+
6. Synthesize the answer from results.`,
|
|
312
|
+
// ...
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
274
316
|
## Supporting files
|
|
275
317
|
- See [examples/write-post-and-publish-to-wordpress.ts](examples/write-post-and-publish-to-wordpress.ts) for a complete pipeline example.
|
|
276
318
|
- See [examples/solve-math-problem.ts](examples/solve-math-problem.ts) for a delegation example.
|
|
319
|
+
- See [examples/graphjin-database-agent.ts](examples/graphjin-database-agent.ts) for single-delegation + workflow reuse pattern.
|
|
277
320
|
|
|
278
321
|
## Do Not Generate
|
|
279
322
|
|
|
280
323
|
- Do NOT add a parent agent before its sub-agents -- `addAgentsToCrew` resolves dependencies but `addAgent` does not.
|
|
281
324
|
- Do NOT use `agents: ["SelfName"]` -- an agent cannot be its own sub-agent (circular dependency error).
|
|
282
|
-
- Do NOT assume agents share conversation context -- they share `
|
|
325
|
+
- Do NOT assume agents share conversation context -- they share `crewState` but each `forward()` call is independent. Pass data explicitly via signatures.
|
|
283
326
|
- Do NOT use `definition` shorter than 100 characters -- Ax requires minimum length for program definitions.
|
|
284
327
|
- Do NOT confuse `description` (used as the tool description when this agent is a sub-agent) with `definition` (the system prompt).
|
|
328
|
+
- Do NOT have the manager decompose questions into sub-queries -- send the full question to the sub-agent in one call.
|
|
285
329
|
|
|
286
330
|
## References
|
|
287
331
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: axcrew-state
|
|
3
|
-
version:
|
|
3
|
+
version: 9.0.0
|
|
4
4
|
description: "State management: shared state, StateInstance, set, get, getAll, reset, accessing state from class-based functions"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# State
|
|
8
8
|
|
|
9
|
-
Every `AxCrew` instance has a shared `StateInstance` at `crew.
|
|
9
|
+
Every `AxCrew` instance has a shared `StateInstance` at `crew.crewState`. All agents and class-based functions in the crew can access the same state.
|
|
10
10
|
|
|
11
11
|
## StateInstance API
|
|
12
12
|
|
|
@@ -21,9 +21,9 @@ interface StateInstance {
|
|
|
21
21
|
|
|
22
22
|
## Core Behavior
|
|
23
23
|
|
|
24
|
-
- `crew.
|
|
24
|
+
- `crew.crewState` is created automatically when `new AxCrew(config)` is called.
|
|
25
25
|
- State is keyed by `crewId` (auto-generated UUID). Each crew instance has its own isolated state.
|
|
26
|
-
- State persists for the lifetime of the crew. Calling `crew.destroy()` calls `
|
|
26
|
+
- State persists for the lifetime of the crew. Calling `crew.destroy()` calls `crewState.reset()`.
|
|
27
27
|
- Values can be any type: strings, objects, arrays, etc.
|
|
28
28
|
|
|
29
29
|
## Canonical Pattern
|
|
@@ -53,7 +53,7 @@ class SendEmail {
|
|
|
53
53
|
required: ['to', 'subject', 'body']
|
|
54
54
|
},
|
|
55
55
|
func: async ({ to, subject, body }: { to: string; subject: string; body: string }) => {
|
|
56
|
-
// Access env credentials set via crew.
|
|
56
|
+
// Access env credentials set via crew.crewState.set("env", {...})
|
|
57
57
|
const env = this.state.env || {};
|
|
58
58
|
const smtpHost = env.SMTP_HOST;
|
|
59
59
|
const smtpUser = env.SMTP_USER;
|
|
@@ -84,15 +84,15 @@ async function main() {
|
|
|
84
84
|
const crew = new AxCrew(config, functions);
|
|
85
85
|
|
|
86
86
|
// Set environment variables in shared state BEFORE adding agents
|
|
87
|
-
crew.
|
|
87
|
+
crew.crewState.set("env", {
|
|
88
88
|
SMTP_HOST: "smtp.example.com",
|
|
89
89
|
SMTP_USER: "user@example.com",
|
|
90
90
|
SMTP_PASS: "secret",
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// You can also set arbitrary data
|
|
94
|
-
crew.
|
|
95
|
-
crew.
|
|
94
|
+
crew.crewState.set("company", "Acme Corp");
|
|
95
|
+
crew.crewState.set("maxRetries", 3);
|
|
96
96
|
|
|
97
97
|
await crew.addAllAgents();
|
|
98
98
|
const notifier = crew.agents?.get("notifier");
|
|
@@ -101,11 +101,11 @@ async function main() {
|
|
|
101
101
|
console.log(result?.result);
|
|
102
102
|
|
|
103
103
|
// Read state back
|
|
104
|
-
console.log("All state:", crew.
|
|
105
|
-
console.log("Company:", crew.
|
|
104
|
+
console.log("All state:", crew.crewState.getAll());
|
|
105
|
+
console.log("Company:", crew.crewState.get("company"));
|
|
106
106
|
|
|
107
107
|
// Reset state (clear all)
|
|
108
|
-
crew.
|
|
108
|
+
crew.crewState.reset();
|
|
109
109
|
|
|
110
110
|
crew.destroy();
|
|
111
111
|
}
|
|
@@ -118,7 +118,7 @@ main().catch(console.error);
|
|
|
118
118
|
The common pattern for passing credentials to class-based functions:
|
|
119
119
|
|
|
120
120
|
```ts
|
|
121
|
-
crew.
|
|
121
|
+
crew.crewState.set("env", {
|
|
122
122
|
WORDPRESS_URL: "http://my-wordpress-site.com",
|
|
123
123
|
WORDPRESS_USERNAME: "my-username",
|
|
124
124
|
WORDPRESS_PASSWORD: "my-password",
|
|
@@ -147,11 +147,11 @@ class MyFunction {
|
|
|
147
147
|
|
|
148
148
|
## Accessing State from Agents
|
|
149
149
|
|
|
150
|
-
Each `StatefulAxAgent` has a `
|
|
150
|
+
Each `StatefulAxAgent` has a `crewState` property that references the crew's shared state:
|
|
151
151
|
|
|
152
152
|
```ts
|
|
153
153
|
const agent = crew.agents?.get("myAgent");
|
|
154
|
-
// agent.
|
|
154
|
+
// agent.crewState is the same StateInstance as crew.crewState
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
## Supporting files
|
|
@@ -160,8 +160,8 @@ const agent = crew.agents?.get("myAgent");
|
|
|
160
160
|
## Do Not Generate
|
|
161
161
|
|
|
162
162
|
- Do NOT assume state values exist without checking; always use optional chaining (e.g. `this.state.env?.KEY`).
|
|
163
|
-
- Do NOT call `crew.
|
|
164
|
-
- Do NOT confuse `crew.
|
|
163
|
+
- Do NOT call `crew.crewState.set("env", ...)` after `addAllAgents()` if class-based functions read state during construction -- set state first.
|
|
164
|
+
- Do NOT confuse `crew.crewState` (StateInstance with `set`/`get`/`getAll`/`reset`) with plain objects. The state object passed to class-based function constructors is a plain record, not the `StateInstance` interface.
|
|
165
165
|
- Do NOT store sensitive credentials in state if the state object might be logged or serialized. The `getAll()` method returns all stored values.
|
|
166
166
|
|
|
167
167
|
## References
|
package/src/skills/axcrew.md
CHANGED
|
@@ -98,11 +98,24 @@ new AxCrew(crewConfig: AxCrewConfig, functionsRegistry?: FunctionRegistryType, o
|
|
|
98
98
|
| `crew.agents?.get("A")` | Retrieve a `StatefulAxAgent` |
|
|
99
99
|
| `await agent.forward({ key: "value" })` | Run the agent |
|
|
100
100
|
| `agent.streamingForward({ key: "value" })` | Stream output chunks |
|
|
101
|
-
| `crew.
|
|
101
|
+
| `crew.crewState` | Shared `StateInstance` across all agents |
|
|
102
102
|
| `crew.resetCosts()` | Reset usage/metrics for all agents |
|
|
103
103
|
| `crew.getCrewMetrics()` | Aggregate metrics snapshot |
|
|
104
104
|
| `crew.destroy()` | Clean up agents, state, execution history |
|
|
105
105
|
|
|
106
|
+
## Deferred Tool Loading
|
|
107
|
+
|
|
108
|
+
Agents with many MCP tools can use `deferredTools` in their agent config to avoid overwhelming the LLM context. When the total tool count exceeds a threshold (default 20), only core tools plus a `search_tools` meta-tool are visible to the agent. The LLM discovers additional tools by calling `search_tools`, which uses local multi-signal search (no API calls). Discovered tools persist across `forward()` calls, and related tools are proactively activated alongside the requested tool.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
{
|
|
112
|
+
name: "BigToolAgent",
|
|
113
|
+
// ...
|
|
114
|
+
mcpServers: { /* ... */ },
|
|
115
|
+
deferredTools: { maxTools: 20 }, // optional, 20 is the default threshold
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
106
119
|
## Related Skills
|
|
107
120
|
|
|
108
121
|
- `ax-crew-agent-config` -- AgentConfig fields, provider setup, executionMode
|
package/src/types.ts
CHANGED
|
@@ -202,6 +202,22 @@ interface ACEConfig {
|
|
|
202
202
|
compileOnStart?: boolean;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Configuration for deferred tool loading.
|
|
207
|
+
* When an agent has many tools, only core tools are visible by default.
|
|
208
|
+
* A search_tools meta-function lets the LLM discover and activate deferred tools on demand.
|
|
209
|
+
*/
|
|
210
|
+
interface DeferredToolsConfig {
|
|
211
|
+
/** Enable deferred tool loading. Default: auto (true when tool count > threshold) */
|
|
212
|
+
enabled?: boolean;
|
|
213
|
+
/** Tool count threshold to activate deferred mode. Default: 20 */
|
|
214
|
+
threshold?: number;
|
|
215
|
+
/** Max tools returned per search. Default: 10 */
|
|
216
|
+
maxSearchResults?: number;
|
|
217
|
+
/** Tool names to always keep active (bypasses deferral) */
|
|
218
|
+
coreTools?: string[];
|
|
219
|
+
}
|
|
220
|
+
|
|
205
221
|
/**
|
|
206
222
|
* The configuration for an agent.
|
|
207
223
|
*
|
|
@@ -261,6 +277,8 @@ interface AgentConfig {
|
|
|
261
277
|
mcpServers?: Record<string, MCPTransportConfig>;
|
|
262
278
|
/** Optional AxACE configuration to enable optimization for this agent */
|
|
263
279
|
ace?: ACEConfig;
|
|
280
|
+
/** Deferred tool loading — reduces token usage when an agent has many tools */
|
|
281
|
+
deferredTools?: DeferredToolsConfig;
|
|
264
282
|
}
|
|
265
283
|
|
|
266
284
|
/**
|
|
@@ -335,6 +353,7 @@ export {
|
|
|
335
353
|
type ModelInfo,
|
|
336
354
|
type UsageCost,
|
|
337
355
|
type AggregatedCosts,
|
|
356
|
+
type DeferredToolsConfig,
|
|
338
357
|
// ACE exports
|
|
339
358
|
type ACEConfig,
|
|
340
359
|
type ACEMetricConfig,
|