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.