MCPcopy Index your code
hub / github.com/amitdeshmukh/ax-crew

github.com/amitdeshmukh/ax-crew @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
215 symbols 525 edges 39 files 31 documented · 14%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

AxCrew

npm version npm downloads

AxCrew — build a crew of AI agents with shared state (powered by AxLLM)

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.

Why AxCrew

  • Config-first crews: Declare agents once; instantiate on demand.
  • ACE Learning: Agents learn from human feedback with persistent playbooks.
  • Sandboxed code execution: AxJSRuntime with permission controls — data never leaves your environment.
  • Shared state: Simple key/value state all agents can read/write.
  • Sub‑agents and tools: Compose agents and functions cleanly.
  • MCP: Connect agents to MCP servers (STDIO, HTTP SSE, Streamable HTTP).
  • Streaming: Real‑time token streaming for responsive UX.
  • Metrics & costs: Per‑agent and crew snapshots, with estimated USD.
  • Auto-installs Claude & Codex skills: npm install installs 16 skill files that teach LLMs to build AxCrew agents.

Install

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.

Environment

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.

Provider-specific arguments (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.

Quickstart

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

Concepts at a glance

  • Agent: An LLM program with a signature, provider, ai model config, optional examples, and optional mcpServers.
  • Sub‑agents: List other agent names in agents to compose behaviors.
  • Functions (tools): Register callable functions via a registry and reference by name in agent functions.
  • State: crew.crewState.set/get/getAll() shared across all agents.
  • Persona: Use definition (preferred) or prompt to set the system program. If both are present, definition wins.
  • Execution mode: Set executionMode to axgen (default) or axagent per agent.
  • Streaming: Use streamingForward() for token streams.
  • Metrics: Per‑agent getMetrics() + crew‑level getCrewMetrics() snapshots.

Usage

Initializing a Crew

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.

Agent Persona: definition and prompt

  • definition: Detailed persona/program description used as the system prompt. Recommended for precise control. Must be at least 100 characters.
  • prompt: An alias for 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 }
}

Execution Modes (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 RLM Support

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.

RLM Examples (with cost and tracing verification)

The following examples in this repo demonstrate equivalent RLM behavior in AxCrew and print accumulated costs at the end:

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

Agent Examples

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

Function Registry

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);

Adding Agents to the Crew

There are three ways to add agents to your crew, each offering different levels of control:

Method 1: Add All Agents Automatically

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

Extension points exported contracts — how you extend this code

StateInstance (Interface)
* A state instance that is shared between agents. * This can be used to store data that becomes available to all agents
src/types.ts
TokenUsage (Interface)
(no doc)
src/metrics/types.ts
ACEBullet (Interface)
(no doc)
src/agents/ace.ts
ModelUsageBase (Interface)
* The usage metrics of the model. * Supports both direct token properties and nested tokens structure
src/types.ts
CostSnapshot (Interface)
(no doc)
src/metrics/types.ts
ACEPlaybook (Interface)
(no doc)
src/agents/ace.ts
ModelInfo (Interface)
* The published cost for using the model. * promptTokenCostPer1M: number; * completionTokenCostPer1M: number;
src/types.ts
RequestStats (Interface)
(no doc)
src/metrics/types.ts

Core symbols most depended-on inside this repo

get
called by 55
src/types.ts
set
called by 19
src/types.ts
forward
called by 19
src/agents/lazyAgent.ts
getMetrics
called by 14
src/agents/statefulAgent.ts
addAllAgents
called by 13
src/agents/crew.ts
getCrewMetrics
called by 12
src/agents/crew.ts
destroy
called by 10
src/agents/crew.ts
addAgent
called by 9
src/agents/crew.ts

Shape

Method 91
Function 77
Interface 31
Class 16

Languages

TypeScript100%

Modules by API surface

src/agents/statefulAgent.ts30 symbols
tests/execution-mode-metrics.test.ts26 symbols
src/types.ts23 symbols
src/agents/ace.ts21 symbols
src/agents/crew.ts17 symbols
src/agents/lazyAgent.ts15 symbols
src/agents/deferredTools.ts12 symbols
src/metrics/registry.ts11 symbols
src/metrics/types.ts8 symbols
src/agents/agentConfig.ts8 symbols
examples/ace-customer-support.ts7 symbols
src/state/index.ts6 symbols

Datastores touched

dbDatabase · 1 repos

For agents

$ claude mcp add ax-crew \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact