@amitdeshmukh/ax-crew 8.4.0 → 8.6.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/skills/ax-crew/SKILL.md +466 -0
- package/CHANGELOG.md +10 -0
- package/dist/agents/index.d.ts +43 -2
- package/dist/agents/index.js +96 -2
- package/package.json +1 -1
- package/src/agents/index.ts +113 -2
- package/examples/run-manager.ts +0 -98
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-crew
|
|
3
|
+
description: Guide for building multi-agent AI systems with ax-crew. Use when creating agent crews, configuring agents, using MCP servers, shared state, sub-agents, streaming, ACE learning, function registries, metrics/cost tracking, telemetry, or agent workflows with @amitdeshmukh/ax-crew.
|
|
4
|
+
argument-hint: [topic]
|
|
5
|
+
allowed-tools: Read, Grep, Glob
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# ax-crew Library Guide
|
|
9
|
+
|
|
10
|
+
ax-crew (`@amitdeshmukh/ax-crew`) is a TypeScript framework for building teams of AI agents with shared state, tools, streaming, MCP integration, and built-in metrics/cost tracking. It is powered by [AxLLM](https://axllm.dev) (`@ax-llm/ax`).
|
|
11
|
+
|
|
12
|
+
**Package:** `@amitdeshmukh/ax-crew` (v8.5.0+)
|
|
13
|
+
**Peer deps:** `@ax-llm/ax`, `@ax-llm/ax-tools`, `@opentelemetry/api` (optional)
|
|
14
|
+
**Node.js:** >= 21
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @amitdeshmukh/ax-crew @ax-llm/ax @ax-llm/ax-tools
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Core Concepts
|
|
23
|
+
|
|
24
|
+
- **Config-first:** Define agents in a JSON/TypeScript config object, instantiate on demand.
|
|
25
|
+
- **Shared state:** Simple key/value store all agents can read/write via `crew.state`.
|
|
26
|
+
- **Sub-agents:** Agents can delegate to other agents listed in their `agents` field.
|
|
27
|
+
- **Functions (tools):** Register callable tools via a function registry, reference by name.
|
|
28
|
+
- **Execution modes:** `axgen` (default, structured generation) or `axagent` (agentic loop with RLM).
|
|
29
|
+
- **MCP:** Connect agents to external MCP servers (STDIO, HTTP SSE, Streamable HTTP).
|
|
30
|
+
- **ACE:** Agentic Context Engineering - agents learn from human feedback at runtime.
|
|
31
|
+
- **Metrics:** Per-agent and crew-level token usage, cost estimation, and request stats.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { AxCrew, AxCrewFunctions } from '@amitdeshmukh/ax-crew';
|
|
37
|
+
import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
|
|
38
|
+
|
|
39
|
+
const config: AxCrewConfig = {
|
|
40
|
+
crew: [
|
|
41
|
+
{
|
|
42
|
+
name: "Researcher",
|
|
43
|
+
description: "Finds information on a topic",
|
|
44
|
+
signature: 'query:string "research query" -> research:string "research findings"',
|
|
45
|
+
provider: "google-gemini",
|
|
46
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
47
|
+
ai: { model: "gemini-2.5-flash", temperature: 0 },
|
|
48
|
+
functions: ["CurrentDateTime"]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "Writer",
|
|
52
|
+
description: "Writes articles based on research",
|
|
53
|
+
signature: 'topic:string -> article:string',
|
|
54
|
+
provider: "google-gemini",
|
|
55
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
56
|
+
ai: { model: "gemini-2.5-flash", temperature: 0.7 },
|
|
57
|
+
agents: ["Researcher"] // Writer can delegate to Researcher
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const crew = new AxCrew(config, AxCrewFunctions);
|
|
63
|
+
await crew.addAllAgents();
|
|
64
|
+
|
|
65
|
+
const writer = crew.agents?.get("Writer");
|
|
66
|
+
const { article } = await writer.forward({ topic: "Quantum Computing" });
|
|
67
|
+
console.log(article);
|
|
68
|
+
|
|
69
|
+
// Metrics
|
|
70
|
+
console.log(crew.getCrewMetrics());
|
|
71
|
+
|
|
72
|
+
// Cleanup
|
|
73
|
+
crew.destroy();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Agent Configuration Reference
|
|
77
|
+
|
|
78
|
+
Each agent in the `crew` array accepts these fields:
|
|
79
|
+
|
|
80
|
+
| Field | Type | Required | Description |
|
|
81
|
+
|-------|------|----------|-------------|
|
|
82
|
+
| `name` | string | Yes | Unique agent name |
|
|
83
|
+
| `description` | string | Yes | What the agent does |
|
|
84
|
+
| `signature` | string | Yes | DSPy-format I/O schema: `input:type "desc" -> output:type "desc"` |
|
|
85
|
+
| `provider` | string | Yes | LLM provider: `google-gemini`, `anthropic`, `openai`, `azure-openai`, etc. |
|
|
86
|
+
| `providerKeyName` | string | No | Env var name for API key (e.g. `"GEMINI_API_KEY"`) |
|
|
87
|
+
| `ai` | object | Yes | `{ model: string, temperature?: number, maxTokens?: number, stream?: boolean }` |
|
|
88
|
+
| `executionMode` | string | No | `"axgen"` (default) or `"axagent"` |
|
|
89
|
+
| `definition` / `prompt` | string | No | System prompt (>= 100 chars). `definition` takes precedence. |
|
|
90
|
+
| `functions` | string[] | No | Tool names from the function registry |
|
|
91
|
+
| `agents` | string[] | No | Sub-agent names this agent can delegate to |
|
|
92
|
+
| `examples` | object[] | No | Few-shot examples matching the signature |
|
|
93
|
+
| `mcpServers` | object | No | MCP server configurations |
|
|
94
|
+
| `ace` | object | No | ACE learning configuration |
|
|
95
|
+
| `debug` | boolean | No | Enable debug logging |
|
|
96
|
+
| `apiURL` | string | No | Custom API endpoint (e.g. for Ollama) |
|
|
97
|
+
| `providerArgs` | object | No | Provider-specific args (e.g. Azure deployment details) |
|
|
98
|
+
| `options` | object | No | Forward options: `debug`, `stream`, `codeExecution`, `thinkingTokenBudget`, etc. |
|
|
99
|
+
| `axAgentOptions` | object | No | RLM options (only for `axagent` mode): `runtime`, `contextFields`, `mode`, `maxTurns` |
|
|
100
|
+
|
|
101
|
+
### Signature Format (DSPy)
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
"inputField:type \"description\" -> outputField:type \"description\""
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Supported types: `string`, `number`, `boolean`, `json`, `string[]`, etc.
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
```
|
|
111
|
+
"query:string -> answer:string"
|
|
112
|
+
"task:string \"a task\" -> plan:string \"step-by-step plan\""
|
|
113
|
+
"question:string, context:string? -> answer:string, confidence:number"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Adding Agents to the Crew
|
|
117
|
+
|
|
118
|
+
Three methods, from simplest to most controlled:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// 1. All agents (auto-handles dependencies)
|
|
122
|
+
await crew.addAllAgents();
|
|
123
|
+
|
|
124
|
+
// 2. Subset with auto dependency resolution
|
|
125
|
+
await crew.addAgentsToCrew(["Writer", "Researcher"]);
|
|
126
|
+
|
|
127
|
+
// 3. Manual (you handle dependency order)
|
|
128
|
+
await crew.addAgent("Researcher");
|
|
129
|
+
await crew.addAgent("Writer");
|
|
130
|
+
|
|
131
|
+
// 4. Lazy initialization (defers expensive init until delegation)
|
|
132
|
+
await crew.addLazyAgent("ExpensiveSubAgent");
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`addLazyAgent()` builds the agent schema immediately (so parent agents can see it as a tool) but defers expensive initialization (MCP server startup, AI client creation) until the agent is actually called.
|
|
136
|
+
|
|
137
|
+
## Function Registry (Tools)
|
|
138
|
+
|
|
139
|
+
Two ways to define tools:
|
|
140
|
+
|
|
141
|
+
### Direct AxFunction objects
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import type { AxFunction } from '@ax-llm/ax';
|
|
145
|
+
|
|
146
|
+
const myFunctions = {
|
|
147
|
+
SearchWeb: {
|
|
148
|
+
name: 'SearchWeb',
|
|
149
|
+
description: 'Searches the web',
|
|
150
|
+
parameters: {
|
|
151
|
+
type: 'object',
|
|
152
|
+
properties: { query: { type: 'string', description: 'search query' } }
|
|
153
|
+
},
|
|
154
|
+
func: async ({ query }) => { /* ... */ return results; }
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Class-based (receives shared state)
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
class DatabaseQuery {
|
|
163
|
+
constructor(private state: Record<string, any>) {}
|
|
164
|
+
toFunction(): AxFunction {
|
|
165
|
+
return {
|
|
166
|
+
name: 'DatabaseQuery',
|
|
167
|
+
description: 'Queries the database',
|
|
168
|
+
parameters: {
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: { sql: { type: 'string', description: 'SQL query' } }
|
|
171
|
+
},
|
|
172
|
+
func: async ({ sql }) => {
|
|
173
|
+
const userId = this.state.userId; // Access shared state
|
|
174
|
+
return await db.query(sql, userId);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const crew = new AxCrew(config, { DatabaseQuery, ...AxCrewFunctions });
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Built-in functions: `CurrentDateTime`, `DaysBetweenDates` (via `AxCrewFunctions`).
|
|
184
|
+
|
|
185
|
+
## Shared State
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
crew.state.set('userId', '123');
|
|
189
|
+
crew.state.get('userId'); // '123'
|
|
190
|
+
crew.state.getAll(); // { userId: '123' }
|
|
191
|
+
crew.state.reset(); // Clear all
|
|
192
|
+
|
|
193
|
+
// Agents share the same state
|
|
194
|
+
const agent = crew.agents?.get("MyAgent");
|
|
195
|
+
agent.state.set('key', 'value'); // Visible to all agents
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Streaming
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Method 1: streamingForward (async iterator)
|
|
202
|
+
const stream = await agent.streamingForward({ topic: "AI" });
|
|
203
|
+
for await (const chunk of stream) {
|
|
204
|
+
if (chunk.delta && 'answer' in chunk.delta) {
|
|
205
|
+
process.stdout.write(chunk.delta.answer);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Method 2: forward with onStream callback
|
|
210
|
+
await agent.forward(
|
|
211
|
+
{ topic: "AI" },
|
|
212
|
+
{ onStream: (chunk) => process.stdout.write(chunk) }
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## MCP Server Integration
|
|
217
|
+
|
|
218
|
+
Three transport types, auto-detected by config shape:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
mcpServers: {
|
|
222
|
+
// STDIO - local process
|
|
223
|
+
"filesystem": {
|
|
224
|
+
command: "npx",
|
|
225
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
|
|
226
|
+
env: { NODE_ENV: "production" }
|
|
227
|
+
},
|
|
228
|
+
// HTTP SSE - remote server
|
|
229
|
+
"api-server": {
|
|
230
|
+
sseUrl: "https://api.example.com/mcp/sse"
|
|
231
|
+
},
|
|
232
|
+
// Streamable HTTP - bidirectional
|
|
233
|
+
"stream-service": {
|
|
234
|
+
mcpEndpoint: "http://localhost:3002/stream",
|
|
235
|
+
options: { timeout: 30000 }
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### MCP Tool Filtering
|
|
241
|
+
|
|
242
|
+
Reduce token usage by exposing only needed tools:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
mcpServers: {
|
|
246
|
+
graphjin: {
|
|
247
|
+
mcpEndpoint: "http://localhost:8080/api/v1/mcp",
|
|
248
|
+
tools: ["list_workflows", "execute_workflow", "describe_table"] // Only these tools
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## ACE (Agentic Context Engineering)
|
|
254
|
+
|
|
255
|
+
Enable agents to learn from human feedback at runtime:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
{
|
|
259
|
+
name: "SupportAgent",
|
|
260
|
+
// ... other config ...
|
|
261
|
+
ace: {
|
|
262
|
+
teacher: {
|
|
263
|
+
provider: "google-gemini",
|
|
264
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
265
|
+
ai: { model: "gemini-flash-latest" }
|
|
266
|
+
},
|
|
267
|
+
options: { maxEpochs: 1, allowDynamicSections: true },
|
|
268
|
+
persistence: {
|
|
269
|
+
playbookPath: "playbooks/support.json",
|
|
270
|
+
autoPersist: true
|
|
271
|
+
},
|
|
272
|
+
metric: { primaryOutputField: "response" },
|
|
273
|
+
compileOnStart: false
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Applying Feedback
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const result = await agent.forward({ ticket: "..." });
|
|
282
|
+
|
|
283
|
+
// Teach the agent
|
|
284
|
+
await crew.applyTaskFeedback({
|
|
285
|
+
taskId: result._taskId,
|
|
286
|
+
feedback: "For loyal customers, extend return window to 60 days",
|
|
287
|
+
strategy: "all" // "all" | "primary" | "weighted"
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// View learned rules
|
|
291
|
+
const playbook = agent.getPlaybook?.();
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Metrics & Cost Tracking
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// Per-agent metrics
|
|
298
|
+
const metrics = agent.getMetrics?.();
|
|
299
|
+
// { provider, model, requests: {...}, tokens: {...}, estimatedCostUSD, functions: {...} }
|
|
300
|
+
|
|
301
|
+
// Crew-level aggregated metrics
|
|
302
|
+
const crewMetrics = crew.getCrewMetrics();
|
|
303
|
+
|
|
304
|
+
// Reset
|
|
305
|
+
crew.resetCosts();
|
|
306
|
+
crew.resetMetrics();
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## OpenTelemetry Integration
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { trace, metrics } from '@opentelemetry/api';
|
|
313
|
+
|
|
314
|
+
const crew = new AxCrew(config, functions, undefined, {
|
|
315
|
+
telemetry: {
|
|
316
|
+
tracer: trace.getTracer('my-app'),
|
|
317
|
+
meter: metrics.getMeter('my-app')
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Execution Modes
|
|
323
|
+
|
|
324
|
+
### axgen (default)
|
|
325
|
+
Structured generation via AxGen. Sub-agents become callable tool functions. Best for deterministic, single-pass tasks.
|
|
326
|
+
|
|
327
|
+
### axagent
|
|
328
|
+
Agentic loop with RLM (Runtime Language Model) support. Best for multi-step reasoning.
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { AxJSRuntime, AxJSRuntimePermission } from '@ax-llm/ax';
|
|
332
|
+
|
|
333
|
+
{
|
|
334
|
+
name: "DeepResearcher",
|
|
335
|
+
executionMode: "axagent",
|
|
336
|
+
signature: "query:string, context:string? -> answer:string",
|
|
337
|
+
// ... provider config ...
|
|
338
|
+
axAgentOptions: {
|
|
339
|
+
runtime: new AxJSRuntime({ permissions: [AxJSRuntimePermission.TIMING] }),
|
|
340
|
+
contextFields: ["context"],
|
|
341
|
+
mode: "simple",
|
|
342
|
+
maxTurns: 12
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Both modes use the same `forward()` / `streamingForward()` API.
|
|
348
|
+
|
|
349
|
+
## Environment Setup
|
|
350
|
+
|
|
351
|
+
Set provider API keys as env vars. Each agent specifies which key via `providerKeyName`:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
GEMINI_API_KEY=...
|
|
355
|
+
ANTHROPIC_API_KEY=...
|
|
356
|
+
OPENAI_API_KEY=...
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
AxCrew resolves keys via `process.env[providerKeyName]` (Node) or `globalThis[providerKeyName]` (browser).
|
|
360
|
+
|
|
361
|
+
## Cleanup
|
|
362
|
+
|
|
363
|
+
Always call `crew.destroy()` when done to clean up MCP servers and resources:
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
try {
|
|
367
|
+
// ... use agents ...
|
|
368
|
+
} finally {
|
|
369
|
+
crew.destroy();
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Key Exports
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
import {
|
|
377
|
+
AxCrew, // Main class
|
|
378
|
+
AxCrewFunctions, // Built-in function registry
|
|
379
|
+
MetricsRegistry, // Metrics helpers
|
|
380
|
+
} from '@amitdeshmukh/ax-crew';
|
|
381
|
+
|
|
382
|
+
import type {
|
|
383
|
+
AxCrewConfig, // Top-level config
|
|
384
|
+
AgentConfig, // Per-agent config
|
|
385
|
+
AxCrewOptions, // Constructor options (telemetry, debug)
|
|
386
|
+
StateInstance, // State API
|
|
387
|
+
FunctionRegistryType,// Function registry shape
|
|
388
|
+
ACEConfig, // ACE configuration
|
|
389
|
+
} from '@amitdeshmukh/ax-crew';
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Common Patterns
|
|
393
|
+
|
|
394
|
+
### Manager + Specialist Pattern
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
const config: AxCrewConfig = {
|
|
398
|
+
crew: [
|
|
399
|
+
{
|
|
400
|
+
name: "SpecialistAgent",
|
|
401
|
+
description: "Handles domain-specific queries",
|
|
402
|
+
signature: 'query:string -> answer:string',
|
|
403
|
+
provider: "google-gemini",
|
|
404
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
405
|
+
ai: { model: "gemini-2.5-pro", temperature: 0 },
|
|
406
|
+
mcpServers: { /* domain tools */ }
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
name: "ManagerAgent",
|
|
410
|
+
description: "Orchestrates specialists to answer questions",
|
|
411
|
+
prompt: "You orchestrate sub-agents to answer user questions. Delegate domain queries to specialists.",
|
|
412
|
+
signature: 'question:string -> answer:string',
|
|
413
|
+
provider: "google-gemini",
|
|
414
|
+
providerKeyName: "GEMINI_API_KEY",
|
|
415
|
+
ai: { model: "gemini-2.5-pro", temperature: 0 },
|
|
416
|
+
agents: ["SpecialistAgent"]
|
|
417
|
+
}
|
|
418
|
+
]
|
|
419
|
+
};
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Lazy Sub-Agent for Expensive Resources
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
const crew = new AxCrew(config);
|
|
426
|
+
await crew.addLazyAgent("HeavyMCPAgent"); // Schema only, no MCP startup yet
|
|
427
|
+
await crew.addAgentsToCrew(["ManagerAgent"]); // Manager sees HeavyMCPAgent as a tool
|
|
428
|
+
// HeavyMCPAgent initializes only when Manager actually delegates to it
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Pipeline Pattern (Sequential Processing)
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
const crew = new AxCrew(config);
|
|
435
|
+
await crew.addAllAgents();
|
|
436
|
+
|
|
437
|
+
const researcher = crew.agents?.get("Researcher");
|
|
438
|
+
const writer = crew.agents?.get("Writer");
|
|
439
|
+
|
|
440
|
+
const { research } = await researcher.forward({ query: "topic" });
|
|
441
|
+
crew.state.set("research", research);
|
|
442
|
+
const { article } = await writer.forward({ topic: "topic" });
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Examples
|
|
446
|
+
|
|
447
|
+
See the `examples/` directory for complete working examples:
|
|
448
|
+
|
|
449
|
+
- `basic-researcher-writer.ts` - Simple two-agent crew
|
|
450
|
+
- `mcp-agent.ts` - MCP server integration with sub-agents
|
|
451
|
+
- `streaming.ts` - Real-time token streaming
|
|
452
|
+
- `run-crew-workflow.ts` - Database workflows with MCP tool filtering
|
|
453
|
+
- `ace-customer-support.ts` - ACE learning from feedback
|
|
454
|
+
- `ace-flight-finder.ts` - Flight assistant with preference learning
|
|
455
|
+
- `rlm-long-task.ts` - RLM mode with context management
|
|
456
|
+
- `rlm-shared-fields.ts` - RLM with field propagation
|
|
457
|
+
- `telemetry-demo.ts` - OpenTelemetry with Jaeger
|
|
458
|
+
- `solve-math-problem.ts` - Code execution with sub-agents
|
|
459
|
+
|
|
460
|
+
## Troubleshooting
|
|
461
|
+
|
|
462
|
+
- **Missing API key:** Ensure `providerKeyName` matches an env var that is set before crew creation.
|
|
463
|
+
- **Circular dependencies:** AxCrew detects and reports circular `agents` references.
|
|
464
|
+
- **MCP server won't start:** Enable `debug: true` on the agent to see MCP init logs.
|
|
465
|
+
- **Sub-agent not visible:** Ensure the sub-agent is added to the crew before the parent agent, or use `addAllAgents()` / `addAgentsToCrew()` for automatic ordering.
|
|
466
|
+
- **definition too short:** Must be >= 100 characters. Use `prompt` as an alias.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [8.6.0] - 2026-03-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Claude Code skill (`.claude/skills/ax-crew/SKILL.md`) providing comprehensive library guidance for LLMs. Covers agent configuration, sub-agents, shared state, MCP integration, ACE learning, streaming, metrics, execution modes, function registries, and common patterns.
|
|
7
|
+
|
|
8
|
+
## [8.5.0] - 2026-03-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Lazy agent initialization** via `crew.addLazyAgent(agentName)`. Builds the tool schema immediately from the crew config (name, description, signature) but defers expensive initialization (MCP server startup, AI client creation) until the Manager actually delegates to the agent. Ideal for sub-agents with stdio MCP servers that spawn a process on init — avoids the cold-start penalty on every request when the agent isn't needed.
|
|
12
|
+
|
|
3
13
|
## [8.4.0] - 2026-03-05
|
|
4
14
|
|
|
5
15
|
### Added
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AxAgent, AxAI } from "@ax-llm/ax";
|
|
1
|
+
import { AxAgent, AxAI, AxSignature as AxSignatureClass } from "@ax-llm/ax";
|
|
2
2
|
import type { AxSignature, AxAgentic, AxFunction, AxProgramForwardOptions, AxProgramStreamingForwardOptions, AxGenStreamingOut } from "@ax-llm/ax";
|
|
3
3
|
import type { StateInstance, FunctionRegistryType, UsageCost, AxCrewConfig, AxCrewOptions, MCPTransportConfig, ACEConfig, AgentExecutionMode, AxCrewAxAgentOptions } from "../types.js";
|
|
4
4
|
declare class StatefulAxAgent extends AxAgent<any, any> {
|
|
@@ -113,6 +113,35 @@ declare class StatefulAxAgent extends AxAgent<any, any> {
|
|
|
113
113
|
*/
|
|
114
114
|
private composeInstructionWithPlaybook;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Lightweight proxy that stands in for a real agent in the crew's agent map.
|
|
118
|
+
* It exposes the same `getFunction()` interface (built from the crew config)
|
|
119
|
+
* but defers the expensive `createAgent()` call — and therefore MCP server
|
|
120
|
+
* startup — until the Manager actually delegates to it.
|
|
121
|
+
*
|
|
122
|
+
* Usage: `crew.addLazyAgent("CreateChart")` instead of `crew.addAgent("CreateChart")`
|
|
123
|
+
*/
|
|
124
|
+
declare class LazyStatefulAxAgent {
|
|
125
|
+
private realAgent;
|
|
126
|
+
private crewRef;
|
|
127
|
+
private agentName;
|
|
128
|
+
private description;
|
|
129
|
+
private signatureStr;
|
|
130
|
+
private func;
|
|
131
|
+
private _id;
|
|
132
|
+
constructor(crewRef: any, agentName: string, crewConfig: AxCrewConfig);
|
|
133
|
+
private resolve;
|
|
134
|
+
getFunction(): AxFunction;
|
|
135
|
+
getSignature(): AxSignatureClass<Record<string, any>, Record<string, any>>;
|
|
136
|
+
getId(): string;
|
|
137
|
+
setId(id: string): void;
|
|
138
|
+
getTraces(): any[];
|
|
139
|
+
setDemos(): void;
|
|
140
|
+
getUsage(): any[];
|
|
141
|
+
resetUsage(): void;
|
|
142
|
+
forward(...args: any[]): Promise<any>;
|
|
143
|
+
streamingForward(...args: any[]): any;
|
|
144
|
+
}
|
|
116
145
|
/**
|
|
117
146
|
* AxCrew orchestrates a set of Ax agents that share state,
|
|
118
147
|
* tools (functions), optional MCP servers, streaming, and a built-in metrics
|
|
@@ -160,6 +189,18 @@ declare class AxCrew {
|
|
|
160
189
|
* @param {string} agentName - The name of the agent to add.
|
|
161
190
|
*/
|
|
162
191
|
addAgent(agentName: string): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Adds a lazy agent to the crew by name.
|
|
194
|
+
* The agent's tool schema is built immediately from the crew config,
|
|
195
|
+
* but the expensive initialization (MCP servers, AI client, etc.) is
|
|
196
|
+
* deferred until the Manager actually delegates to this agent.
|
|
197
|
+
*
|
|
198
|
+
* Use this for sub-agents that may not be needed on every request
|
|
199
|
+
* (e.g., agents with stdio MCP servers that spawn a process).
|
|
200
|
+
*
|
|
201
|
+
* @param {string} agentName - The name of the agent to add lazily.
|
|
202
|
+
*/
|
|
203
|
+
addLazyAgent(agentName: string): void;
|
|
163
204
|
/**
|
|
164
205
|
* Sets up agents in the crew by name.
|
|
165
206
|
* For an array of Agent names provided, it adds
|
|
@@ -221,5 +262,5 @@ declare class AxCrew {
|
|
|
221
262
|
*/
|
|
222
263
|
resetCrewMetrics(): void;
|
|
223
264
|
}
|
|
224
|
-
export { AxCrew };
|
|
265
|
+
export { AxCrew, LazyStatefulAxAgent };
|
|
225
266
|
export type { StatefulAxAgent };
|
package/dist/agents/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import { AxAgent, AxGen } from "@ax-llm/ax";
|
|
2
|
+
import { AxAgent, AxGen, AxSignature as AxSignatureClass } from "@ax-llm/ax";
|
|
3
3
|
import { createState } from "../state/index.js";
|
|
4
4
|
import { parseCrewConfig, parseAgentConfig } from "./agentConfig.js";
|
|
5
5
|
import { MetricsRegistry } from "../metrics/index.js";
|
|
@@ -515,6 +515,81 @@ class StatefulAxAgent extends AxAgent {
|
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
|
+
/**
|
|
519
|
+
* Lightweight proxy that stands in for a real agent in the crew's agent map.
|
|
520
|
+
* It exposes the same `getFunction()` interface (built from the crew config)
|
|
521
|
+
* but defers the expensive `createAgent()` call — and therefore MCP server
|
|
522
|
+
* startup — until the Manager actually delegates to it.
|
|
523
|
+
*
|
|
524
|
+
* Usage: `crew.addLazyAgent("CreateChart")` instead of `crew.addAgent("CreateChart")`
|
|
525
|
+
*/
|
|
526
|
+
class LazyStatefulAxAgent {
|
|
527
|
+
realAgent = null;
|
|
528
|
+
crewRef; // AxCrew — forward-declared to avoid circular ref
|
|
529
|
+
agentName;
|
|
530
|
+
description;
|
|
531
|
+
signatureStr;
|
|
532
|
+
func;
|
|
533
|
+
_id = "lazy";
|
|
534
|
+
constructor(crewRef, agentName, crewConfig) {
|
|
535
|
+
this.crewRef = crewRef;
|
|
536
|
+
this.agentName = agentName;
|
|
537
|
+
const agentDef = parseCrewConfig(crewConfig).crew.find((a) => a.name === agentName);
|
|
538
|
+
if (!agentDef) {
|
|
539
|
+
throw new Error(`Agent "${agentName}" not found in crew config`);
|
|
540
|
+
}
|
|
541
|
+
this.description = agentDef.description;
|
|
542
|
+
this.signatureStr = agentDef.signature;
|
|
543
|
+
// Build the tool schema from the signature's input fields
|
|
544
|
+
const sig = new AxSignatureClass(this.signatureStr);
|
|
545
|
+
const parameters = sig.toInputJSONSchema();
|
|
546
|
+
this.func = {
|
|
547
|
+
name: agentName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase(),
|
|
548
|
+
description: this.description,
|
|
549
|
+
parameters,
|
|
550
|
+
func: async (args) => {
|
|
551
|
+
const agent = await this.resolve();
|
|
552
|
+
return agent.forward(args);
|
|
553
|
+
},
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
async resolve() {
|
|
557
|
+
if (!this.realAgent) {
|
|
558
|
+
const agent = await this.crewRef.createAgent(this.agentName);
|
|
559
|
+
agent.setId(this._id);
|
|
560
|
+
this.realAgent = agent;
|
|
561
|
+
}
|
|
562
|
+
return this.realAgent;
|
|
563
|
+
}
|
|
564
|
+
// AxAgentic interface
|
|
565
|
+
getFunction() {
|
|
566
|
+
return this.func;
|
|
567
|
+
}
|
|
568
|
+
getSignature() {
|
|
569
|
+
return new AxSignatureClass(this.signatureStr);
|
|
570
|
+
}
|
|
571
|
+
// AxProgrammable / AxTunable stubs
|
|
572
|
+
getId() { return this._id; }
|
|
573
|
+
setId(id) { this._id = id; }
|
|
574
|
+
getTraces() { return this.realAgent?.getTraces() ?? []; }
|
|
575
|
+
setDemos() { }
|
|
576
|
+
getUsage() { return this.realAgent?.getUsage() ?? []; }
|
|
577
|
+
resetUsage() { this.realAgent?.resetUsage(); }
|
|
578
|
+
// Forward / streaming — resolve on demand
|
|
579
|
+
async forward(...args) {
|
|
580
|
+
const agent = await this.resolve();
|
|
581
|
+
return agent.forward(...args);
|
|
582
|
+
}
|
|
583
|
+
streamingForward(...args) {
|
|
584
|
+
// Must be sync to match the interface, so we wrap in an async generator
|
|
585
|
+
const self = this;
|
|
586
|
+
async function* lazyStream() {
|
|
587
|
+
const agent = await self.resolve();
|
|
588
|
+
yield* agent.streamingForward(...args);
|
|
589
|
+
}
|
|
590
|
+
return lazyStream();
|
|
591
|
+
}
|
|
592
|
+
}
|
|
518
593
|
/**
|
|
519
594
|
* AxCrew orchestrates a set of Ax agents that share state,
|
|
520
595
|
* tools (functions), optional MCP servers, streaming, and a built-in metrics
|
|
@@ -689,6 +764,25 @@ class AxCrew {
|
|
|
689
764
|
throw new Error(`Failed to add agent ${agentName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
690
765
|
}
|
|
691
766
|
}
|
|
767
|
+
/**
|
|
768
|
+
* Adds a lazy agent to the crew by name.
|
|
769
|
+
* The agent's tool schema is built immediately from the crew config,
|
|
770
|
+
* but the expensive initialization (MCP servers, AI client, etc.) is
|
|
771
|
+
* deferred until the Manager actually delegates to this agent.
|
|
772
|
+
*
|
|
773
|
+
* Use this for sub-agents that may not be needed on every request
|
|
774
|
+
* (e.g., agents with stdio MCP servers that spawn a process).
|
|
775
|
+
*
|
|
776
|
+
* @param {string} agentName - The name of the agent to add lazily.
|
|
777
|
+
*/
|
|
778
|
+
addLazyAgent(agentName) {
|
|
779
|
+
if (!this.agents) {
|
|
780
|
+
this.agents = new Map();
|
|
781
|
+
}
|
|
782
|
+
if (!this.agents.has(agentName)) {
|
|
783
|
+
this.agents.set(agentName, new LazyStatefulAxAgent(this, agentName, this.crewConfig));
|
|
784
|
+
}
|
|
785
|
+
}
|
|
692
786
|
/**
|
|
693
787
|
* Sets up agents in the crew by name.
|
|
694
788
|
* For an array of Agent names provided, it adds
|
|
@@ -917,4 +1011,4 @@ class AxCrew {
|
|
|
917
1011
|
MetricsRegistry.reset({ crewId: this.crewId });
|
|
918
1012
|
}
|
|
919
1013
|
}
|
|
920
|
-
export { AxCrew };
|
|
1014
|
+
export { AxCrew, LazyStatefulAxAgent };
|
package/package.json
CHANGED
package/src/agents/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import { AxAgent, AxAI, AxGen } from "@ax-llm/ax";
|
|
2
|
+
import { AxAgent, AxAI, AxGen, AxSignature as AxSignatureClass } from "@ax-llm/ax";
|
|
3
3
|
|
|
4
4
|
import type {
|
|
5
5
|
AxSignature,
|
|
@@ -697,6 +697,94 @@ class StatefulAxAgent extends AxAgent<any, any> {
|
|
|
697
697
|
}
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
+
/**
|
|
701
|
+
* Lightweight proxy that stands in for a real agent in the crew's agent map.
|
|
702
|
+
* It exposes the same `getFunction()` interface (built from the crew config)
|
|
703
|
+
* but defers the expensive `createAgent()` call — and therefore MCP server
|
|
704
|
+
* startup — until the Manager actually delegates to it.
|
|
705
|
+
*
|
|
706
|
+
* Usage: `crew.addLazyAgent("CreateChart")` instead of `crew.addAgent("CreateChart")`
|
|
707
|
+
*/
|
|
708
|
+
class LazyStatefulAxAgent {
|
|
709
|
+
private realAgent: StatefulAxAgent | null = null;
|
|
710
|
+
private crewRef: any; // AxCrew — forward-declared to avoid circular ref
|
|
711
|
+
private agentName: string;
|
|
712
|
+
private description: string;
|
|
713
|
+
private signatureStr: string;
|
|
714
|
+
private func: AxFunction;
|
|
715
|
+
private _id: string = "lazy";
|
|
716
|
+
|
|
717
|
+
constructor(crewRef: any, agentName: string, crewConfig: AxCrewConfig) {
|
|
718
|
+
this.crewRef = crewRef;
|
|
719
|
+
this.agentName = agentName;
|
|
720
|
+
|
|
721
|
+
const agentDef = parseCrewConfig(crewConfig).crew.find(
|
|
722
|
+
(a) => a.name === agentName
|
|
723
|
+
);
|
|
724
|
+
if (!agentDef) {
|
|
725
|
+
throw new Error(`Agent "${agentName}" not found in crew config`);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
this.description = agentDef.description;
|
|
729
|
+
this.signatureStr = agentDef.signature as string;
|
|
730
|
+
|
|
731
|
+
// Build the tool schema from the signature's input fields
|
|
732
|
+
const sig = new AxSignatureClass(this.signatureStr);
|
|
733
|
+
const parameters = sig.toInputJSONSchema();
|
|
734
|
+
|
|
735
|
+
this.func = {
|
|
736
|
+
name: agentName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase(),
|
|
737
|
+
description: this.description,
|
|
738
|
+
parameters,
|
|
739
|
+
func: async (args?: any) => {
|
|
740
|
+
const agent = await this.resolve();
|
|
741
|
+
return agent.forward(args);
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
private async resolve(): Promise<StatefulAxAgent> {
|
|
747
|
+
if (!this.realAgent) {
|
|
748
|
+
const agent = await this.crewRef.createAgent(this.agentName) as StatefulAxAgent;
|
|
749
|
+
agent.setId(this._id);
|
|
750
|
+
this.realAgent = agent;
|
|
751
|
+
}
|
|
752
|
+
return this.realAgent!;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// AxAgentic interface
|
|
756
|
+
getFunction(): AxFunction {
|
|
757
|
+
return this.func;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
getSignature() {
|
|
761
|
+
return new AxSignatureClass(this.signatureStr);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// AxProgrammable / AxTunable stubs
|
|
765
|
+
getId(): string { return this._id; }
|
|
766
|
+
setId(id: string): void { this._id = id; }
|
|
767
|
+
getTraces(): any[] { return this.realAgent?.getTraces() ?? []; }
|
|
768
|
+
setDemos(): void { /* no-op until resolved */ }
|
|
769
|
+
getUsage(): any[] { return this.realAgent?.getUsage() ?? []; }
|
|
770
|
+
resetUsage(): void { this.realAgent?.resetUsage(); }
|
|
771
|
+
|
|
772
|
+
// Forward / streaming — resolve on demand
|
|
773
|
+
async forward(...args: any[]): Promise<any> {
|
|
774
|
+
const agent = await this.resolve();
|
|
775
|
+
return (agent as any).forward(...args);
|
|
776
|
+
}
|
|
777
|
+
streamingForward(...args: any[]): any {
|
|
778
|
+
// Must be sync to match the interface, so we wrap in an async generator
|
|
779
|
+
const self = this;
|
|
780
|
+
async function* lazyStream() {
|
|
781
|
+
const agent = await self.resolve();
|
|
782
|
+
yield* (agent as any).streamingForward(...args);
|
|
783
|
+
}
|
|
784
|
+
return lazyStream();
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
700
788
|
/**
|
|
701
789
|
* AxCrew orchestrates a set of Ax agents that share state,
|
|
702
790
|
* tools (functions), optional MCP servers, streaming, and a built-in metrics
|
|
@@ -912,6 +1000,29 @@ class AxCrew {
|
|
|
912
1000
|
}
|
|
913
1001
|
}
|
|
914
1002
|
|
|
1003
|
+
/**
|
|
1004
|
+
* Adds a lazy agent to the crew by name.
|
|
1005
|
+
* The agent's tool schema is built immediately from the crew config,
|
|
1006
|
+
* but the expensive initialization (MCP servers, AI client, etc.) is
|
|
1007
|
+
* deferred until the Manager actually delegates to this agent.
|
|
1008
|
+
*
|
|
1009
|
+
* Use this for sub-agents that may not be needed on every request
|
|
1010
|
+
* (e.g., agents with stdio MCP servers that spawn a process).
|
|
1011
|
+
*
|
|
1012
|
+
* @param {string} agentName - The name of the agent to add lazily.
|
|
1013
|
+
*/
|
|
1014
|
+
addLazyAgent(agentName: string): void {
|
|
1015
|
+
if (!this.agents) {
|
|
1016
|
+
this.agents = new Map<string, StatefulAxAgent>();
|
|
1017
|
+
}
|
|
1018
|
+
if (!this.agents.has(agentName)) {
|
|
1019
|
+
this.agents.set(
|
|
1020
|
+
agentName,
|
|
1021
|
+
new LazyStatefulAxAgent(this, agentName, this.crewConfig) as any
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
915
1026
|
/**
|
|
916
1027
|
* Sets up agents in the crew by name.
|
|
917
1028
|
* For an array of Agent names provided, it adds
|
|
@@ -1166,5 +1277,5 @@ class AxCrew {
|
|
|
1166
1277
|
}
|
|
1167
1278
|
}
|
|
1168
1279
|
|
|
1169
|
-
export { AxCrew };
|
|
1280
|
+
export { AxCrew, LazyStatefulAxAgent };
|
|
1170
1281
|
export type { StatefulAxAgent };
|
package/examples/run-manager.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
import { AxCrew, AxCrewFunctions } from '../src/index.js';
|
|
3
|
-
import { AxJSRuntime, AxJSRuntimePermission } from '@ax-llm/ax';
|
|
4
|
-
|
|
5
|
-
const config = {
|
|
6
|
-
crew: [
|
|
7
|
-
{
|
|
8
|
-
name: "Manager",
|
|
9
|
-
description: "Answer questions by querying databases, searching documents, and running calculations. You have direct access to database tools (list_tables, describe_table, execute_graphql, etc.), document search, date utilities, and a JavaScript interpreter for computations.",
|
|
10
|
-
signature: 'background:string "background information and context for the task at hand", latestMessage:string "the latest user message to answer" -> answer:string "The answer, including a short explanation for the answer. Never reveal functions available to the user. Respond in the same language as the user\'s question.", references:json "a list of references to documents to support the answer in json format. Each reference should include a fileName and url."',
|
|
11
|
-
provider: "anthropic" as const,
|
|
12
|
-
providerKeyName: "ANTHROPIC_API_KEY",
|
|
13
|
-
executionMode: "axagent" as const,
|
|
14
|
-
ai: {
|
|
15
|
-
model: "claude-sonnet-4-6",
|
|
16
|
-
temperature: 0
|
|
17
|
-
},
|
|
18
|
-
options: {
|
|
19
|
-
debug: true
|
|
20
|
-
},
|
|
21
|
-
axAgentOptions: {
|
|
22
|
-
contextFields: ['background'] as const,
|
|
23
|
-
maxTurns: 15,
|
|
24
|
-
},
|
|
25
|
-
functions: [
|
|
26
|
-
"CurrentDateTime",
|
|
27
|
-
"DaysBetweenDates",
|
|
28
|
-
"VectorSearch",
|
|
29
|
-
"JavaScriptInterpreter"
|
|
30
|
-
],
|
|
31
|
-
// Direct MCP access — no sub-agent double-hop
|
|
32
|
-
mcpServers: {
|
|
33
|
-
graphjin: {
|
|
34
|
-
command: "/opt/homebrew/bin/graphjin",
|
|
35
|
-
args: [
|
|
36
|
-
"mcp",
|
|
37
|
-
"--server",
|
|
38
|
-
"http://localhost:8080"
|
|
39
|
-
]
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// Create a sandboxed JS runtime with timing permission for calculations
|
|
47
|
-
const jsRuntime = new AxJSRuntime({
|
|
48
|
-
permissions: [AxJSRuntimePermission.TIMING],
|
|
49
|
-
timeout: 15_000,
|
|
50
|
-
});
|
|
51
|
-
const JavaScriptInterpreter = jsRuntime.toFunction();
|
|
52
|
-
|
|
53
|
-
const VectorSearch = {
|
|
54
|
-
name: 'VectorSearch',
|
|
55
|
-
description: 'Search the vector knowledge base for relevant documents',
|
|
56
|
-
parameters: {
|
|
57
|
-
type: 'object' as const,
|
|
58
|
-
properties: {
|
|
59
|
-
query: { type: 'string', description: 'The search query' }
|
|
60
|
-
},
|
|
61
|
-
required: ['query']
|
|
62
|
-
},
|
|
63
|
-
func: async ({ query }: { query: string }) => {
|
|
64
|
-
console.log(`[VectorSearch] Searching for: ${query}`);
|
|
65
|
-
return `No documents found for: ${query}`;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
async function main() {
|
|
70
|
-
const crew = new AxCrew(config, { ...AxCrewFunctions, VectorSearch, JavaScriptInterpreter });
|
|
71
|
-
|
|
72
|
-
await crew.addAllAgents();
|
|
73
|
-
|
|
74
|
-
const manager = crew.agents?.get('Manager');
|
|
75
|
-
if (!manager) {
|
|
76
|
-
throw new Error('Manager agent not found');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const query = "analyze all our orders to date, give me a table showing P&L";
|
|
80
|
-
console.log(`\nQuery: ${query}\n`);
|
|
81
|
-
|
|
82
|
-
const result = await manager.forward({
|
|
83
|
-
background: "User is querying the system about order information.",
|
|
84
|
-
latestMessage: query
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
console.log(`\nAnswer: ${result.answer}`);
|
|
88
|
-
console.log(`\nReferences:`, JSON.stringify(result.references, null, 2));
|
|
89
|
-
|
|
90
|
-
const crewMetrics = crew.getCrewMetrics();
|
|
91
|
-
console.log(`\nCrew Metrics:`, JSON.stringify(crewMetrics, null, 2));
|
|
92
|
-
|
|
93
|
-
crew.destroy();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
main()
|
|
97
|
-
.catch(console.error)
|
|
98
|
-
.finally(() => process.exit(0));
|