Skip to main content
Chapter 6 Multi-Agent Architectures

The Orchestrator Pattern

22 min read Lesson 21 / 28

The Orchestrator Pattern

In multi-agent systems, an orchestrator is a Claude agent whose job is to break down complex goals into sub-tasks and delegate them to specialized subagents. Subagents are focused, context-limited agents that do one thing well.

Why Multi-Agent?

  • Parallelism — Subagents can run concurrently
  • Specialization — Each agent has a focused system prompt and tool set
  • Context management — Subagents have smaller, targeted contexts
  • Reliability — Failures are isolated to individual subagents

Orchestrator Implementation

import anthropic
import json
import asyncio
from concurrent.futures import ThreadPoolExecutor

client = anthropic.Anthropic()

# ── Subagent: Web Researcher ──

def research_agent(topic: str) -> str:
    """Specialized agent for web research."""
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system="You are a concise research assistant. Summarize key facts about the given topic in 3-5 bullet points.",
        messages=[{"role": "user", "content": f"Research: {topic}"}],
    )
    return response.content[0].text


# ── Subagent: Data Analyst ──

def analysis_agent(data: str, question: str) -> str:
    """Specialized agent for data analysis."""
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system="You are a data analyst. Extract insights and patterns from the provided data.",
        messages=[{
            "role": "user",
            "content": f"Data:\n{data}\n\nQuestion: {question}"
        }],
    )
    return response.content[0].text


# ── Orchestrator ──

ORCHESTRATOR_TOOLS = [
    {
        "name": "delegate_research",
        "description": "Assign a research task to the web research subagent.",
        "input_schema": {
            "type": "object",
            "properties": {"topic": {"type": "string", "description": "What to research"}},
            "required": ["topic"],
        },
    },
    {
        "name": "delegate_analysis",
        "description": "Assign a data analysis task to the analyst subagent.",
        "input_schema": {
            "type": "object",
            "properties": {
                "data": {"type": "string", "description": "The data to analyze"},
                "question": {"type": "string", "description": "What to find in the data"},
            },
            "required": ["data", "question"],
        },
    },
]

def orchestrate(goal: str) -> str:
    """Orchestrator that plans and delegates to subagents."""
    messages = [{"role": "user", "content": goal}]

    for _ in range(15):
        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=2048,
            system="You are an orchestrator. Break down the goal into research and analysis tasks. Delegate to subagents using tools. Synthesize their outputs into a final answer.",
            tools=ORCHESTRATOR_TOOLS,
            messages=messages,
        )

        if response.stop_reason == "end_turn":
            return response.content[0].text

        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                if block.name == "delegate_research":
                    result = research_agent(block.input["topic"])
                elif block.name == "delegate_analysis":
                    result = analysis_agent(block.input["data"], block.input["question"])
                else:
                    result = json.dumps({"error": "Unknown subagent"})

                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result,
                })

        messages.append({"role": "assistant", "content": response.content})
        messages.append({"role": "user", "content": tool_results})

    return "Orchestration did not complete."


result = orchestrate("Analyze the competitive landscape for AI coding assistants in 2025.")
print(result)

The orchestrator does not need to know how subagents work internally — it only cares about their inputs and outputs.