Claude for Developers

Multi-Agent Systems with Claude: Build Autonomous Teams Tutorial

Discover how to build collaborative multi-agent systems with Claude AI, turning individual models into autonomous teams. This TypeScript tutorial delivers a complete, working example for AI orchestrat

J

Jennifer Yu

Workflow Automation Specialist

December 9, 2025 min read
Share:

Introduction to Multi-Agent Systems with Claude

Multi-agent systems (MAS) represent the next evolution in AI, where multiple specialized AI instances collaborate to solve complex tasks. Unlike single-agent setups, MAS mimic human teams: a supervisor delegates work, agents execute roles like researcher or editor, and results iterate until completion.

Claude excels here due to its superior reasoning, tool use, and context handling in the Anthropic API. Models like Claude 3.5 Sonnet shine in role-playing and structured outputs, making them ideal for agent swarms.

This tutorial builds a Content Creation Pipeline: a supervisor oversees a Researcher, Writer, and Editor—all powered by Claude via the TypeScript SDK. We'll use sequential API calls with a stateful orchestration loop for collaboration.

Why Multi-Agent with Claude?

  • Modularity: Break tasks into roles for better accuracy (e.g., Researcher focuses on facts).
  • Scalability: Parallelize agents with async calls (future-proof for production).
  • Reliability: Claude's constitutional AI reduces hallucinations in team settings.
  • Cost-Effective: Use Haiku for simple agents, Opus for complex supervision.

Real-world use: Automate reports, code reviews, or marketing campaigns.

Prerequisites

  • Node.js 18+
  • Anthropic API key (free tier available at console.anthropic.com)
  • Basic TypeScript knowledge

Step 1: Project Setup

Create a new directory and initialize:

mkdir claude-multi-agent
cd claude-multi-agent
npm init -y
npm install @anthropic-ai/sdk typescript ts-node @types/node
npx tsc --init

Update tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
  }
}

Create src/index.ts and .env for your API key:

npm install dotenv
npm install -D @types/dotenv

.env:

ANTHROPIC_API_KEY=your_key_here

Step 2: Core Components

We'll define:

  • Agent Interface: Standardized inputs/outputs.
  • Prompt Templates: Role-specific system prompts.
  • Supervisor Logic: Decides next action.

Agent Types

import Anthropic from '@anthropic-ai/sdk';
import dotenv from 'dotenv';

dotenv.config();

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

type AgentMessage = {
  role: string;
  content: string;
  task: string;
};

type AgentResponse = {
  output: string;
  nextAction: 'research' | 'write' | 'edit' | 'done';
  feedback?: string;
};

interface ClaudeAgent {
  name: string;
  model: string;
  systemPrompt: string;
  invoke(messages: AgentMessage[]): Promise<AgentResponse>;
}

Step 3: Define Agents

Researcher Agent

const researcher: ClaudeAgent = {
  name: 'Researcher',
  model: 'claude-3-5-sonnet-20240620',
  systemPrompt: `You are a meticulous Researcher. Given a topic, gather key facts, sources, and insights. Output structured bullet points. Suggest if writing or editing is next.`
};

function createAgentInvoke(agent: ClaudeAgent) {
  return async (messages: AgentMessage[]): Promise<AgentResponse> => {
    const response = await client.messages.create({
      model: agent.model,
      max_tokens: 2000,
      system: agent.systemPrompt,
      messages: messages.map(m => ({ role: 'user' as const, content: m.content })),
    });

    const output = response.content[0].text;
    // Parse structured response (use XML or JSON tools in prod)
    const parsed = parseAgentResponse(output); // Implement parser
    return parsed;
  };
}

researcher.invoke = createAgentInvoke(researcher);

Implement a simple parser (in production, use Claude's tool calling for JSON):

function parseAgentResponse(text: string): AgentResponse {
  // Regex or simple split for tutorial
  const nextMatch = text.match(/Next action: (\w+)/i);
  return {
    output: text,
    nextAction: (nextMatch?.[1].toLowerCase() as any) || 'done',
  };
}

Writer and Editor Agents

const writer: ClaudeAgent = {
  name: 'Writer',
  model: 'claude-3-5-sonnet-20240620',
  systemPrompt: `You are a skilled Writer. Use research to draft engaging content. Output full draft. Decide if editing needed.`
};

writer.invoke = createAgentInvoke(writer);

const editor: ClaudeAgent = {
  name: 'Editor',
  model: 'claude-3-haiku-20240307', // Faster/cheaper
  systemPrompt: `You are an Editor. Review draft for clarity, grammar, facts. Suggest revisions or approve.`
};

editor.invoke = createAgentInvoke(editor);

const agents = { researcher, writer, editor };

Step 4: Supervisor Agent

The brain: Oversees workflow, maintains state.

const supervisorSystem = `You are Supervisor. Manage agents for content pipeline.
State: {research, draft, edits}

Commands:
- research: Send topic to Researcher
- write: Send research to Writer
- edit: Send draft to Editor
- done: Output final

Respond with JSON: {"next_agent": "research|write|edit|done", "rationale": "...", "input": "..."}`;

type SupervisorDecision = {
  next_agent: keyof typeof agents | 'done';
  rationale: string;
  input?: string;
};

async function getSupervisorDecision(state: any): Promise<SupervisorDecision> {
  const msg = `Current state: ${JSON.stringify(state)}\
Decide next step.`;
  const res = await client.messages.create({
    model: 'claude-3-opus-20240229',
    system: supervisorSystem,
    max_tokens: 500,
    messages: [{ role: 'user' as const, content: msg }],
  });
  return JSON.parse(res.content[0].text); // Use tools for robust parsing
}

Step 5: Orchestration Loop

async function runPipeline(topic: string) {
  let state = {
    topic,
    research: '',
    draft: '',
    edits: '',
    history: [],
  };

  while (true) {
    const decision = await getSupervisorDecision(state);
    state.history.push(decision);

    if (decision.next_agent === 'done') {
      console.log('Final Output:', state.draft);
      break;
    }

    const currentAgent = agents[decision.next_agent as keyof typeof agents];
    const taskMsg: AgentMessage = {
      role: currentAgent.name,
      content: decision.input || topic,
      task: state.topic,
    };

    const response = await currentAgent.invoke([taskMsg]);
    state.research = decision.next_agent === 'research' ? response.output : state.research;
    state.draft = decision.next_agent === 'write' ? response.output : state.draft;
    state.edits += response.feedback || '';

    console.log(`${currentAgent.name}: ${response.output.slice(0, 100)}...`);
  }
}

// Run
runPipeline('Best practices for Claude prompt engineering');

Step 6: Enhancements for Production

  • Tool Calling: Use Claude's tools for structured outputs.
    // Example tool
    tools: [{
      name: 'publish',
      description: 'Finalize content',
      input_schema: { type: 'object', properties: { content: {type: 'string'} } }
    }]
    
  • Parallelism: Promise.all for independent agents.
  • Persistence: Redis/Stateful DB for long runs.
  • Error Handling: Retry logic with exponential backoff.
  • MCP Integration: Extend with Model Context Protocol servers for external tools.
  • Costs: Monitor tokens; use Haiku for editors.

Full Code

Combine into src/index.ts. Run with npx ts-node src/index.ts.

Expected Output:

  • Supervisor delegates: research → write → edit → done.
  • Produces polished article on topic.

Best Practices & Limitations

Prompt Engineering Tips:

  • Role specificity reduces drift.
  • Chain-of-thought in system prompts.
  • XML/JSON delimiters for parsing.

Claude-Specific:

  • Leverage 200k context for long histories.
  • Sonnet for balance of speed/quality.
  • Avoid infinite loops with max iterations (e.g., 10).

Limitations:

  • Sequential by default; async for true parallelism.
  • Token costs scale with agents.
  • No native state; manage externally.

Conclusion

You've built a scalable multi-agent swarm with Claude! Experiment by adding agents (e.g., Fact-Checker). For enterprise, integrate with n8n or Claude Code.

Fork on GitHub, share your variants. Next: AI Agents with Tools.

Word count: ~1450

The #1 Newsletter in AI

Stay ahead of the AI curve

The most important updates, news, and content — delivered in one weekly newsletter.

No spam. Unsubscribe anytime. Privacy policy

claude agents
multi-agent
claude api
ai orchestration
prompt engineering
ai-agents
J

About Jennifer Yu

Workflow Automation Specialist

Jennifer covers workflow strategy, no-code platforms, and clear implementation guidance for teams adopting automation.

Comments (0)