
AxCrew lets you define a team of AI agents in config and run them together with shared state, tools, streaming, MCP, and built‑in metrics/cost tracking. Bring your own functions or use the provided registry.
npm install installs 16 skill files that teach LLMs to build AxCrew agents.npm install @amitdeshmukh/ax-crew @ax-llm/ax @ax-llm/ax-tools
This also auto-installs 16 skill files for Claude Code (~/.claude/skills/ax-crew/) and Codex (~/.agents/skills/ax-crew/).
Requirements: Node.js >= 21.
Set provider keys in your environment. Example .env:
GEMINI_API_KEY=...
ANTHROPIC_API_KEY=...
OPENAI_API_KEY=...
AZURE_OPENAI_API_KEY=...
In each agent config, set providerKeyName to the env var name. AxCrew resolves the key at runtime by reading process.env[providerKeyName] in Node or globalThis[providerKeyName] in the browser. Ensure your env is loaded (for example, import dotenv/config in Node) before creating the crew.
providerArgs)Some providers require extra top-level configuration beyond ai.model (for example, Azure deployment details or Vertex AI project/region). Pass these via providerArgs. AxCrew forwards providerArgs to Ax unchanged; validation and semantics are handled by Ax. Refer to Ax provider docs for supported fields.
import { AxCrew, AxCrewFunctions, FunctionRegistryType, StateInstance } from '@amitdeshmukh/ax-crew';
import type { AxFunction } from '@ax-llm/ax';
const config = {
crew: [{
name: "Planner",
description: "Creates a plan to complete a task",
executionMode: "axgen", // "axagent" | "axgen"
signature: "task:string \"a task to be completed\" -> plan:string \"a plan to execute the task\"",
provider: "google-gemini",
providerKeyName: "GEMINI_API_KEY",
ai: {
model: "gemini-1.5-pro",
temperature: 0
}
}]
};
// Create custom functions with type safety
class MyCustomFunction {
constructor(private state: Record<string, any>) {}
toFunction(): AxFunction {
return {
name: 'MyCustomFunction',
description: 'Does something useful',
parameters: {
type: 'object',
properties: {
inputParam: { type: 'string', description: "input to the function" }
}
},
func: async ({ inputParam }) => {
// Implementation
return inputParam;
}
};
}
}
// Type-safe function registry
const myFunctions: FunctionRegistryType = {
MyCustomFunction
};
// Create crew with type checking
const crew = new AxCrew(config, myFunctions);
// Set and get state
crew.crewState.set('key', 'value');
const value: string = crew.crewState.get('key');
// Add agents to the crew
await crew.addAgentsToCrew(['Planner']);
const planner = crew.agents?.get('Planner');
if (planner) {
const response = await planner.forward({ task: "Plan something" });
// Sub-agent usage - when used by another agent (AI is ignored and agent's own config is used)
const subAgentResponse = await planner.forward(ai, { task: "Plan something" });
// Metrics (per-agent and per-crew)
const agentMetrics = (planner as any).getMetrics?.();
const crewMetrics = crew.getCrewMetrics();
console.log('Agent metrics:', agentMetrics);
console.log('Crew metrics:', crewMetrics);
}
Key TypeScript features: - Full type definitions for all classes, methods, and properties - Type-safe configuration objects - Proper typing for function registries and custom functions - Type checking for state management - Comprehensive type safety for agent operations and responses - Usage cost tracking with proper types
signature, provider, ai model config, optional examples, and optional mcpServers.agents to compose behaviors.functions.crew.crewState.set/get/getAll() shared across all agents.definition (preferred) or prompt to set the system program. If both are present, definition wins.executionMode to axgen (default) or axagent per agent.streamingForward() for token streams.getMetrics() + crew‑level getCrewMetrics() snapshots.Pass a JSON object to the AxCrew constructor:
// Import the AxCrew class
import { AxCrew } from '@amitdeshmukh/ax-crew';
// Create the configuration object
const config = {
crew: [
{
name: "Planner",
description: "Creates a plan to complete a task",
signature: "task:string \"a task to be completed\" -> plan:string \"a plan to execute the task in 5 steps or less\"",
provider: "google-gemini",
providerKeyName: "GEMINI_API_KEY",
ai: {
model: "gemini-1.5-flash",
temperature: 0
},
options: {
debug: false
}
}
// ... more agents
]
};
// Create a new instance of AxCrew using the config object
const crew = new AxCrew(config);
AxCrew no longer supports reading from a configuration file to remain browser-compatible.
definition. If both are provided, definition takes precedence.Add either field to any agent config. The chosen value becomes the Ax agent's underlying program description (system prompt).
{
"name": "Planner",
"description": "Creates a plan to complete a task",
"prompt": "You are a meticulous planning assistant. Produce concise, executable step-by-step plans with clear justifications, constraints, and assumptions. Prefer brevity, avoid fluff, and ask for missing critical details before proceeding when necessary.",
"signature": "task:string -> plan:string",
"provider": "google-gemini",
"providerKeyName": "GEMINI_API_KEY",
"ai": { "model": "gemini-1.5-flash", "temperature": 0 }
}
axagent | axgen)Each agent can run in one of two execution modes supported by AxLLM:
axgen (default): Uses AxGen capabilities.axagent: Uses AxAgent capabilities.Set mode in config:
{
"name": "Planner",
"description": "Creates plans",
"executionMode": "axgen",
"signature": "task:string -> plan:string",
"provider": "google-gemini",
"providerKeyName": "GEMINI_API_KEY",
"ai": { "model": "gemini-1.5-flash", "temperature": 0 }
}
Execution is routed internally by executionMode while you continue to call the same public APIs (forward / streamingForward).
There is no external API split and no caller-side branching for axagent vs axgen.
AxAgent in newer Ax versions moved to an RLM split architecture (Actor/Responder + runtime loop).
AxCrew supports this directly so you can use modern AxAgent capabilities without changing the AxCrew call surface.
To configure those capabilities in AxCrew, use axAgentOptions on an agent (effective when executionMode is axagent):
const config = {
crew: [{
name: "Researcher",
description: "Deep research agent",
executionMode: "axagent",
signature: "query:string, context:string? -> answer:string",
provider: "google-gemini",
providerKeyName: "GEMINI_API_KEY",
ai: { model: "gemini-1.5-pro", temperature: 0 },
axAgentOptions: {
runtime,
contextFields: ["context"],
mode: "simple",
maxTurns: 12
}
}]
};
RLM mode requirements:
- axAgentOptions.runtime: Provide an AxJSRuntime instance for runtime execution.
- axAgentOptions.contextFields: Required in RLM mode (can be an empty array when no context fields are needed).
Example runtime wiring:
import { AxJSRuntime, AxJSRuntimePermission } from '@ax-llm/ax';
const runtime = new AxJSRuntime({
permissions: [AxJSRuntimePermission.TIMING],
});
const config = {
crew: [{
name: "Analyzer",
executionMode: "axagent",
// ...
axAgentOptions: {
runtime,
contextFields: ["context"]
}
}]
};
Why this exists:
- Upstream AxAgent changed to support richer RLM behaviors (runtime-backed decomposition, actor/responder separation, context management).
- AxCrew needs to preserve compatibility while exposing these capabilities.
- executionMode keeps this explicit per-agent and lets AxCrew route internally with zero external API change.
forward() and streamingForward() remain unchanged; AxCrew routes internally based on executionMode.
The following examples in this repo demonstrate equivalent RLM behavior in AxCrew and print accumulated costs at the end:
examples/rlm-long-task.ts: Long-task analysis with context management and RLM runtime.examples/rlm-shared-fields.ts: Shared-field propagation with parent/child AxAgent setup.Both examples:
- run through the same public forward() API
- use AxAgent RLM options through axAgentOptions
- print per-agent and crew metrics (estimatedCostUSD, token usage)
- are compatible with telemetry/tracing instrumentation
You can provide examples to guide the behavior of your agents using the examples field in the agent configuration. Examples help the agent understand the expected input/output format and improve its responses.
{
"name": "MathTeacher",
"description": "Solves math problems with step by step explanations",
"signature": "problem:string \"a math problem to solve\" -> solution:string \"step by step solution with final answer\"",
"provider": "google-gemini",
"providerKeyName": "GEMINI_API_KEY",
"ai": {
"model": "gemini-1.5-pro",
"temperature": 0
},
"examples": [
{
"problem": "what is the square root of 144?",
"solution": "Let's solve this step by step:\n1. The square root of a number is a value that, when multiplied by itself, gives the original number\n2. For 144, we need to find a number that when multiplied by itself equals 144\n3. 12 × 12 = 144\nTherefore, the square root of 144 is 12"
},
{
"problem": "what is the cube root of 27?",
"solution": "Let's solve this step by step:\n1. The cube root of a number is a value that, when multiplied by itself twice, gives the original number\n2. For 27, we need to find a number that when cubed equals 27\n3. 3 × 3 × 3 = 27\nTherefore, the cube root of 27 is 3"
}
]
}
The examples should: - Match the input/output signature of your agent - Demonstrate the desired format and style of responses - Include edge cases or specific patterns you want the agent to learn - Be clear and concise while showing the expected behavior
Examples are particularly useful for: - Teaching agents specific response formats - Demonstrating step-by-step problem-solving approaches - Showing how to handle edge cases - Maintaining consistent output styles across responses
Functions (aka Tools) are the building blocks of agents. They are used to perform specific tasks, such as calling external APIs, databases, or other services.
The FunctionRegistry is a central place where all the functions that agents can use are registered. This allows for easy access and management of functions across different agents in the crew.
To use the FunctionRegistry, you need to either:
- import and use the built-in functions from the @amitdeshmukh/ax-crew package, or
- bring your own functions before initializing AxCrew.
Here's an example of how to set up the FunctionRegistry with built-in functions:
import { AxCrewFunctions } from '@amitdeshmukh/ax-crew';
const crew = new AxCrew(config, AxCrewFunctions);
if you want to bring your own functions, you can do so by creating a new instance of FunctionRegistry and passing it to the AxCrew constructor.
import { FunctionRegistryType } from '@amitdeshmukh/ax-crew';
const myFunctions: FunctionRegistryType = {
GoogleSearch: googleSearchInstance.toFunction()
};
const crew = new AxCrew(config, myFunctions);
There are three ways to add agents to your crew, each offering different levels of control:
This is the simplest method that automatically handles all dependencies:
// Initialize all agents defined in the config
await crew.addAllAgents();
// Get agent instances
const planner = crew.agents?.get("Planner");
const manager = crew.agents?.get("Manager");
This method: - Reads all agents from your conf
$ claude mcp add ax-crew \
-- python -m otcore.mcp_server <graph>