@amitdeshmukh/ax-crew 8.6.0 → 8.7.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.
@@ -5,7 +5,9 @@
5
5
  "Bash(git push:*)",
6
6
  "Bash(git status:*)",
7
7
  "Bash(node:*)",
8
- "Bash(npm version:*)"
8
+ "Bash(npm version:*)",
9
+ "WebFetch(domain:github.com)",
10
+ "WebFetch(domain:tanstack.com)"
9
11
  ]
10
12
  }
11
13
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [8.7.1] - 2026-03-17
4
+
5
+ ### Fixed
6
+ - Skill postinstall now installs to the **project directory** (`.claude/skills/ax-crew/`, `.agents/skills/ax-crew/`) instead of the home directory. Skills are scoped to projects that use ax-crew.
7
+
8
+ ## [8.7.0] - 2026-03-17
9
+
10
+ ### Added
11
+ - **16 Claude Code & Codex skill files** in `src/skills/` — terse, code-first `.md` files covering the full AxCrew API: config, signatures, functions, state, sub-agents, streaming, MCP, metrics, execution modes, code execution, ACE, few-shot, providers, telemetry, and multi-agent patterns.
12
+ - **Postinstall auto-install**: `npm install` copies skill files to `~/.claude/skills/ax-crew/` (individual `.md` files) and `~/.agents/skills/ax-crew/` (combined `SKILL.md` for Codex). Skills are auto-discovered by Claude Code and Codex — no manual setup needed.
13
+ - **Preuninstall cleanup**: `npm uninstall` removes installed skill files.
14
+ - MIT LICENSE file.
15
+
3
16
  ## [8.6.0] - 2026-03-14
4
17
 
5
18
  ### Added
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Amit Deshmukh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -8,23 +8,23 @@ AxCrew lets you define a team of AI agents in config and run them together with
8
8
 
9
9
  ### Why AxCrew
10
10
  - **Config-first crews**: Declare agents once; instantiate on demand.
11
+ - **ACE Learning**: Agents learn from human feedback with persistent playbooks.
12
+ - **Sandboxed code execution**: AxJSRuntime with permission controls — data never leaves your environment.
11
13
  - **Shared state**: Simple key/value state all agents can read/write.
12
14
  - **Sub‑agents and tools**: Compose agents and functions cleanly.
13
- - **Streaming**: Real‑time token streaming for responsive UX.
14
15
  - **MCP**: Connect agents to MCP servers (STDIO, HTTP SSE, Streamable HTTP).
16
+ - **Streaming**: Real‑time token streaming for responsive UX.
15
17
  - **Metrics & costs**: Per‑agent and crew snapshots, with estimated USD.
18
+ - **Auto-installs Claude & Codex skills**: `npm install` installs 16 skill files that teach LLMs to build AxCrew agents.
16
19
 
17
20
  ### Install
18
- Install this package:
19
- ```bash
20
- npm install @amitdeshmukh/ax-crew
21
- ```
22
- AxLLM is a peer dependency, so you will need to install it separately.
23
21
 
24
22
  ```bash
25
- npm install @ax-llm/ax @ax-llm/ax-tools
23
+ npm install @amitdeshmukh/ax-crew @ax-llm/ax @ax-llm/ax-tools
26
24
  ```
27
25
 
26
+ This also auto-installs 16 skill files for Claude Code (`~/.claude/skills/ax-crew/`) and Codex (`~/.agents/skills/ax-crew/`).
27
+
28
28
  Requirements: Node.js >= 21.
29
29
 
30
30
  ### Environment
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@amitdeshmukh/ax-crew",
4
- "version": "8.6.0",
4
+ "version": "8.7.1",
5
5
  "description": "Build and launch a crew of AI agents with shared state. Built with axllm.dev",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -9,6 +9,8 @@
9
9
  "node": ">=21.0.0"
10
10
  },
11
11
  "scripts": {
12
+ "postinstall": "node scripts/install-skills.mjs",
13
+ "preuninstall": "node scripts/uninstall-skills.mjs",
12
14
  "build": "rm -rf dist && tsc --outDir dist",
13
15
  "release": "npm run build && npm publish --access public",
14
16
  "test": "vitest run",
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Postinstall script: installs ax-crew skill files for Claude Code and Codex.
5
+ * Runs automatically on `npm install @amitdeshmukh/ax-crew`.
6
+ *
7
+ * Skills are installed to the PROJECT directory (not home dir):
8
+ * Claude Code: .claude/skills/ax-crew/ (individual .md files)
9
+ * Codex: .agents/skills/ax-crew/ (combined SKILL.md)
10
+ *
11
+ * The project root is determined by walking up from node_modules
12
+ * to find the consuming project's root directory.
13
+ */
14
+
15
+ import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync } from 'fs';
16
+ import { join, dirname, resolve } from 'path';
17
+ import { fileURLToPath } from 'url';
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const skillsSource = join(__dirname, '..', 'src', 'skills');
21
+
22
+ // Find the project root by walking up from the package's location
23
+ // When installed via npm, we're at <project>/node_modules/@amitdeshmukh/ax-crew/scripts/
24
+ // So project root is 4 levels up. When running locally (dev), use INIT_CWD or cwd.
25
+ function findProjectRoot() {
26
+ // npm sets INIT_CWD to the directory where `npm install` was run
27
+ if (process.env.INIT_CWD) {
28
+ return process.env.INIT_CWD;
29
+ }
30
+ // Fallback: walk up from our location past node_modules
31
+ let dir = resolve(__dirname, '..');
32
+ while (dir !== dirname(dir)) {
33
+ if (existsSync(join(dir, 'node_modules'))) {
34
+ return dir;
35
+ }
36
+ dir = dirname(dir);
37
+ }
38
+ return process.cwd();
39
+ }
40
+
41
+ function installSkills() {
42
+ if (!existsSync(skillsSource)) return;
43
+
44
+ const skillFiles = readdirSync(skillsSource).filter(f => f.endsWith('.md')).sort();
45
+ if (skillFiles.length === 0) return;
46
+
47
+ const projectRoot = findProjectRoot();
48
+
49
+ // Claude Code: individual skill files in project dir
50
+ const claudeDir = join(projectRoot, '.claude', 'skills', 'ax-crew');
51
+ try {
52
+ mkdirSync(claudeDir, { recursive: true });
53
+ for (const file of skillFiles) {
54
+ copyFileSync(join(skillsSource, file), join(claudeDir, file));
55
+ }
56
+ console.log(` ax-crew: installed ${skillFiles.length} skills → ${claudeDir}`);
57
+ } catch {
58
+ // Silently skip
59
+ }
60
+
61
+ // Codex: single SKILL.md combining all skills in project dir
62
+ const codexDir = join(projectRoot, '.agents', 'skills', 'ax-crew');
63
+ try {
64
+ mkdirSync(codexDir, { recursive: true });
65
+
66
+ let combined = `---\nname: ax-crew\ndescription: Build and manage crews of AI agents with JSON config. Covers AxCrew class, agent config, signatures, functions, state, sub-agents, streaming, MCP, metrics, execution modes, code execution, ACE learning, few-shot, providers, telemetry, and multi-agent patterns.\n---\n\n`;
67
+
68
+ for (const file of skillFiles) {
69
+ const content = readFileSync(join(skillsSource, file), 'utf-8');
70
+ const body = content.replace(/^---\n[\s\S]*?\n---\n/, '');
71
+ combined += body.trim() + '\n\n---\n\n';
72
+ }
73
+
74
+ writeFileSync(join(codexDir, 'SKILL.md'), combined.trim());
75
+ console.log(` ax-crew: installed combined SKILL.md → ${codexDir}`);
76
+ } catch {
77
+ // Silently skip
78
+ }
79
+ }
80
+
81
+ installSkills();
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Preuninstall script: removes ax-crew skill files from the project directory.
5
+ */
6
+
7
+ import { existsSync, rmSync } from 'fs';
8
+ import { join } from 'path';
9
+
10
+ const projectRoot = process.env.INIT_CWD || process.cwd();
11
+
12
+ const targets = [
13
+ join(projectRoot, '.claude', 'skills', 'ax-crew'),
14
+ join(projectRoot, '.agents', 'skills', 'ax-crew'),
15
+ ];
16
+
17
+ for (const dir of targets) {
18
+ try {
19
+ if (existsSync(dir)) {
20
+ rmSync(dir, { recursive: true });
21
+ console.log(` ax-crew: removed skills from ${dir}`);
22
+ }
23
+ } catch {
24
+ // Silently skip
25
+ }
26
+ }
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: ax-crew-ace
3
+ version: __VERSION__
4
+ description: "ACE (Agentic Context Engineering) for AxCrew: feedback loops, online learning, playbook persistence, and optimization."
5
+ tags: [ace, agentic-context-engineering, feedback, learning, playbook, online-update, optimize]
6
+ ---
7
+
8
+ # ACE (Agentic Context Engineering)
9
+
10
+ ACE enables agents to learn from human feedback at runtime. Feedback is analyzed, categorized into playbook sections, and injected into the agent's system prompt on every subsequent `forward()` call.
11
+
12
+ ## ACEConfig Shape
13
+
14
+ ```ts
15
+ interface ACEConfig {
16
+ teacher?: {
17
+ provider?: Provider;
18
+ providerKeyName?: string;
19
+ apiURL?: string;
20
+ ai?: AxModelConfig & { model: string };
21
+ providerArgs?: Record<string, unknown>;
22
+ };
23
+ persistence?: {
24
+ playbookPath?: string;
25
+ initialPlaybook?: Record<string, any>;
26
+ autoPersist?: boolean;
27
+ onPersist?: (pb: any) => Promise<void> | void;
28
+ onLoad?: () => Promise<any> | any;
29
+ };
30
+ options?: {
31
+ maxEpochs?: number;
32
+ allowDynamicSections?: boolean;
33
+ tokenBudget?: number;
34
+ reflectorPrompt?: string;
35
+ curatorPrompt?: string;
36
+ };
37
+ metric?: {
38
+ metricFnName?: string;
39
+ primaryOutputField?: string;
40
+ };
41
+ compileOnStart?: boolean;
42
+ }
43
+ ```
44
+
45
+ ## Agent-Level ACE API
46
+
47
+ ```ts
48
+ // StatefulAxAgent methods:
49
+ await agent.initACE(aceConfig); // called automatically during addAgent()
50
+ await agent.applyOnlineUpdate({ example, prediction, feedback }); // learn from feedback
51
+ agent.getPlaybook(); // returns current ACEPlaybook
52
+ agent.applyPlaybook(playbook); // set playbook directly
53
+ await agent.optimizeOffline({ metric, examples }); // offline compilation
54
+ ```
55
+
56
+ ## Crew-Level Feedback Routing
57
+
58
+ ```ts
59
+ // AxCrew tracks which agents participated in a task and routes feedback to all of them:
60
+ crew.trackAgentExecution(taskId, agentName, input); // automatic during forward()
61
+ crew.recordAgentResult(taskId, agentName, result); // automatic during forward()
62
+ await crew.applyTaskFeedback({ taskId, feedback, strategy: "all" | "primary" | "weighted" });
63
+ crew.getTaskAgentInvolvement(taskId); // inspect execution history
64
+ crew.cleanupOldExecutions(maxAgeMs); // prevent memory leaks
65
+ ```
66
+
67
+ ## Playbook Persistence
68
+
69
+ Three persistence options (checked in order):
70
+ 1. `onLoad` callback -- custom async loader
71
+ 2. `initialPlaybook` -- inline playbook object
72
+ 3. `playbookPath` -- JSON file on disk (auto-created)
73
+
74
+ Auto-save: set `autoPersist: true` with `playbookPath` or `onPersist` callback.
75
+
76
+ ## Canonical Pattern
77
+
78
+ Adapted from `examples/ace-customer-support.ts` -- an agent that learns customer support exception policies from supervisor feedback.
79
+
80
+ ```ts
81
+ import { AxCrew } from "ax-crew";
82
+ import type { AxCrewConfig, Provider } from "ax-crew";
83
+
84
+ const config: AxCrewConfig = {
85
+ crew: [
86
+ {
87
+ name: "SupportAgent",
88
+ description: "Customer support agent. Follow company policies strictly.",
89
+ signature: "ticket:string, policies:string[] -> response:string, decision:string",
90
+ provider: "google-gemini" as Provider,
91
+ providerKeyName: "GEMINI_API_KEY",
92
+ ai: { model: "gemini-flash-latest", temperature: 0.7 },
93
+ options: { stream: false },
94
+ ace: {
95
+ teacher: {
96
+ provider: "google-gemini" as Provider,
97
+ providerKeyName: "GEMINI_API_KEY",
98
+ ai: { model: "gemini-flash-latest" },
99
+ },
100
+ options: { maxEpochs: 1, allowDynamicSections: true },
101
+ persistence: {
102
+ playbookPath: "playbooks/support.json",
103
+ autoPersist: true,
104
+ },
105
+ metric: { primaryOutputField: "response" },
106
+ compileOnStart: false,
107
+ },
108
+ },
109
+ ],
110
+ };
111
+
112
+ async function main() {
113
+ const crew = new AxCrew(config);
114
+ await crew.addAgentsToCrew(["SupportAgent"]);
115
+ const agent = crew.agents!.get("SupportAgent")!;
116
+
117
+ // Run the agent
118
+ const result = await agent.forward({
119
+ ticket: "Customer wants refund on sale item (defective on arrival)",
120
+ policies: ["No refunds on sale items", "Returns within 30 days only"],
121
+ });
122
+
123
+ console.log(result.response, result.decision);
124
+
125
+ // Apply feedback -- agent learns for future calls
126
+ const taskId = (result as any)._taskId;
127
+ if (taskId) {
128
+ await crew.applyTaskFeedback({
129
+ taskId,
130
+ feedback: "Defective products must always be refunded regardless of sale status",
131
+ strategy: "all",
132
+ });
133
+ }
134
+
135
+ // Or apply directly to agent (without task routing)
136
+ await (agent as any).applyOnlineUpdate({
137
+ example: { ticket: "..." },
138
+ prediction: result,
139
+ feedback: "Medical emergencies extend the 30-day window to 60 days",
140
+ });
141
+
142
+ // Inspect learned playbook
143
+ const playbook = (agent as any).getPlaybook();
144
+ console.log(JSON.stringify(playbook, null, 2));
145
+
146
+ crew.cleanupOldExecutions(60000);
147
+ crew.destroy();
148
+ }
149
+
150
+ main().catch(console.error);
151
+ ```
152
+
153
+ ## Do Not Generate
154
+
155
+ - Do NOT call `initACE()` manually -- it is called automatically when `addAgent()` / `addAgentsToCrew()` detects an `ace` config on the agent.
156
+ - Do NOT set `compileOnStart: true` without providing `examples` and a `metric` -- offline compilation requires both.
157
+ - Do NOT mutate the playbook object directly -- use `applyOnlineUpdate()` or `applyPlaybook()`.
158
+ - Do NOT forget `autoPersist: true` if you want playbook changes saved to disk automatically.
159
+ - Do NOT use `strategy: "weighted"` expecting differentiated weights -- it currently behaves the same as `"all"`.
160
+
161
+ ## References
162
+
163
+ - [ace-customer-support.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/ace-customer-support.ts)
164
+ - [src/agents/ace.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/src/agents/ace.ts)
165
+ - [AxACE upstream docs](https://axllm.dev/ace/)
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: ax-crew-agent-config
3
+ version: __VERSION__
4
+ description: "AgentConfig - agent configuration: provider, signature, model, temperature, definition, prompt, executionMode, axAgentOptions, providerArgs"
5
+ ---
6
+
7
+ # AgentConfig
8
+
9
+ Every agent in a crew is defined by an `AgentConfig` object inside `AxCrewConfig.crew[]`.
10
+
11
+ ## All Fields
12
+
13
+ ```ts
14
+ interface AgentConfig {
15
+ // Required
16
+ name: string; // Unique agent name
17
+ description: string; // Short description (used as default system prompt)
18
+ signature: string | AxSignature; // DSPy-style signature, e.g. "query:string -> answer:string"
19
+ provider: Provider; // "openai" | "anthropic" | "google-gemini" | "azure-openai" | ...
20
+ ai: AxModelConfig & { // Model configuration
21
+ model: string; // model name (required)
22
+ temperature?: number; // sampling temperature
23
+ maxTokens?: number; // max output tokens
24
+ stream?: boolean; // enable streaming at AI level
25
+ };
26
+
27
+ // Optional
28
+ providerKeyName?: string; // Env var name for API key (e.g. "OPENAI_API_KEY")
29
+ apiURL?: string; // Custom API endpoint (e.g. ollama on localhost)
30
+ providerArgs?: Record<string, unknown>; // Provider-specific args forwarded to Ax factory
31
+ definition?: string; // Detailed system prompt (must be >= 100 chars per Ax)
32
+ prompt?: string; // Alias for definition (used if definition is omitted)
33
+ debug?: boolean; // Enable debug logging
34
+ options?: Partial<AxProgramForwardOptions<any>> & Record<string, any>; // Forward options + provider-specific keys
35
+ functions?: string[]; // Function names from the registry
36
+ agents?: string[]; // Sub-agent names (must be added to crew first)
37
+ examples?: Array<Record<string, any>>; // DSPy few-shot examples
38
+ mcpServers?: Record<string, MCPTransportConfig>; // MCP server configs
39
+ executionMode?: "axagent" | "axgen"; // Execution engine (default: "axgen")
40
+ axAgentOptions?: AxCrewAxAgentOptions; // AxAgent-specific options (only for executionMode: "axagent")
41
+ ace?: ACEConfig; // Optional AxACE optimization config
42
+ }
43
+ ```
44
+
45
+ ## Canonical Pattern
46
+
47
+ ```ts
48
+ import { AxCrew } from '@amitdeshmukh/ax-crew';
49
+ import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
50
+
51
+ const config: AxCrewConfig = {
52
+ crew: [
53
+ {
54
+ name: "analyzer",
55
+ description: "Analyzes user queries and provides structured responses",
56
+ signature: "userQuery:string -> analysis:string, confidence:number",
57
+ provider: "anthropic",
58
+ providerKeyName: "ANTHROPIC_API_KEY",
59
+ ai: {
60
+ model: "claude-sonnet-4-20250514",
61
+ temperature: 0.5,
62
+ maxTokens: 2000,
63
+ },
64
+ options: { debug: true, stream: false },
65
+ functions: ["CurrentDateTime"],
66
+ }
67
+ ]
68
+ };
69
+
70
+ async function main() {
71
+ const crew = new AxCrew(config);
72
+ await crew.addAllAgents();
73
+ const analyzer = crew.agents?.get("analyzer");
74
+ const result = await analyzer?.forward({ userQuery: "What is quantum computing?" });
75
+ console.log(result?.analysis, result?.confidence);
76
+ crew.destroy();
77
+ }
78
+
79
+ main().catch(console.error);
80
+ ```
81
+
82
+ ## Provider Key Pattern
83
+
84
+ The `providerKeyName` field specifies which environment variable holds the API key. The key is read from `process.env` at agent creation time.
85
+
86
+ ```ts
87
+ {
88
+ provider: "openai",
89
+ providerKeyName: "OPENAI_API_KEY", // reads process.env.OPENAI_API_KEY
90
+ }
91
+ ```
92
+
93
+ ## Azure OpenAI Example
94
+
95
+ Use `providerArgs` for provider-specific configuration:
96
+
97
+ ```ts
98
+ import { AxCrew } from '@amitdeshmukh/ax-crew';
99
+ import type { AxCrewConfig } from '@amitdeshmukh/ax-crew';
100
+
101
+ const config: AxCrewConfig = {
102
+ crew: [
103
+ {
104
+ name: "TestAgent",
105
+ description: "Test Agent for Azure OpenAI",
106
+ provider: "azure-openai",
107
+ providerKeyName: "AZURE_OPENAI_API_KEY",
108
+ signature: "userQuery:string -> answer:string",
109
+ ai: {
110
+ model: "gpt-5-mini",
111
+ temperature: 0,
112
+ stream: false
113
+ },
114
+ providerArgs: {
115
+ resourceName: "your-resource-name",
116
+ deploymentName: "your-deployment-name",
117
+ version: "2025-01-01-preview"
118
+ },
119
+ options: { debug: true, stream: false }
120
+ }
121
+ ]
122
+ };
123
+
124
+ async function main() {
125
+ const crew = new AxCrew(config);
126
+ await crew.addAllAgents();
127
+ const agent = crew.agents?.get("TestAgent");
128
+ const response = await agent?.forward({ userQuery: "What is the capital of France?" });
129
+ console.log(response?.answer);
130
+ crew.destroy();
131
+ }
132
+
133
+ main().catch(console.error);
134
+ ```
135
+
136
+ ## Execution Mode
137
+
138
+ | Mode | Engine | When to use |
139
+ |---|---|---|
140
+ | `"axgen"` (default) | `AxGen` | Standard prompt-response with tool calling |
141
+ | `"axagent"` | `AxAgent` | Full agent capabilities: RLM, context fields, actor/responder split |
142
+
143
+ When `executionMode: "axagent"`, use `axAgentOptions` for agent-specific settings:
144
+
145
+ ```ts
146
+ {
147
+ executionMode: "axagent",
148
+ axAgentOptions: {
149
+ contextFields: ["conversationHistory"],
150
+ // agents: { ... }, // Agent graph config
151
+ // functions: { ... }, // Function graph config
152
+ // actorOptions: { description: "..." },
153
+ // responderOptions: { description: "..." },
154
+ }
155
+ }
156
+ ```
157
+
158
+ ## Signature Format
159
+
160
+ DSPy-style string signatures with optional field descriptions:
161
+
162
+ ```
163
+ "input1:type, input2:type -> output1:type, output2:type"
164
+ "topic:string \"The topic\" -> article:string \"The written article\""
165
+ "query:string -> results:string[]"
166
+ ```
167
+
168
+ Supported types: `string`, `number`, `boolean`, `string[]`, `number[]`, etc.
169
+
170
+ ## Do Not Generate
171
+
172
+ - Do NOT omit `name`, `description`, `signature`, `provider`, or `ai.model` -- all are required.
173
+ - Do NOT set `definition` to less than 100 characters if you provide it (Ax enforces this minimum).
174
+ - Do NOT confuse `options.stream` (forward option) with `ai.stream` (AI-level streaming config).
175
+ - Do NOT use `providerArgs` for API keys; use `providerKeyName` instead.
176
+ - Do NOT list sub-agents in `agents` that haven't been added to the crew before the parent agent.
177
+
178
+ ## References
179
+
180
+ - [basic-researcher-writer.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/basic-researcher-writer.ts)
181
+ - [providerArgs.ts](https://github.com/amitdeshmukh/ax-crew/blob/main/examples/providerArgs.ts)