Files
python-sdk/docs/agent/multi_agent.md
T
zeekay 2f38fb90ae docs: replace all placeholder content with real documentation
MCP docs:
- quickstart.md - Installation, basic usage, transport modes
- configuration.md - CLI options, env vars, config files
- vscode.md - VS Code, Cursor, Windsurf integration

Agent SDK docs:
- agents.md - Creating and configuring agents
- running_agents.md - Runner, RunConfig, async/sync
- tools.md - Function tools, context, custom tools
- guardrails.md - Input/output validation
- handoffs.md - Agent delegation patterns
- streaming.md - Stream events and responses
- tracing.md - Observability and debugging
- context.md - Mutable run context
- config.md - RunConfig and ModelSettings
- results.md - RunResult, items, usage
- models.md - Providers and model selection
- multi_agent.md - Complex multi-agent patterns
2026-01-05 18:37:11 -08:00

5.6 KiB

Multi-Agent Systems

Build complex workflows with multiple cooperating agents.

Agent Teams

Create specialized agents that work together:

from agents import Agent

# Specialist agents
researcher = Agent(
    name="researcher",
    instructions="Research topics thoroughly and provide facts.",
    handoff_description="Researches information and facts.",
)

writer = Agent(
    name="writer", 
    instructions="Write clear, engaging content based on research.",
    handoff_description="Writes content and articles.",
)

editor = Agent(
    name="editor",
    instructions="Review and improve written content.",
    handoff_description="Edits and improves content quality.",
)

# Coordinator
coordinator = Agent(
    name="coordinator",
    instructions="""Coordinate the team to produce quality content.
    1. Use researcher for facts
    2. Use writer to draft content
    3. Use editor to polish""",
    handoffs=[researcher, writer, editor],
)

Sequential Workflow

Agents pass work in sequence:

from agents import Agent, handoff, Handoff

@handoff
def to_next_stage(ctx) -> Handoff:
    """Move to the next processing stage."""
    stages = ctx.context.get("stages", [])
    current = ctx.context.get("current_stage", 0)
    
    if current < len(stages):
        ctx.context["current_stage"] = current + 1
        return Handoff(target=stages[current])
    return None

stage1 = Agent(name="stage1", handoffs=[to_next_stage])
stage2 = Agent(name="stage2", handoffs=[to_next_stage])
stage3 = Agent(name="stage3", instructions="Final stage.")

Parallel Execution

Run multiple agents simultaneously:

import asyncio
from agents import Agent, Runner

agents = [
    Agent(name="analyst1", instructions="Analyze from perspective A"),
    Agent(name="analyst2", instructions="Analyze from perspective B"),
    Agent(name="analyst3", instructions="Analyze from perspective C"),
]

async def parallel_analysis(prompt: str):
    tasks = [Runner.run(agent, prompt) for agent in agents]
    results = await asyncio.gather(*tasks)
    return [r.final_output for r in results]

# Combine results
outputs = await parallel_analysis("Analyze this data")

Supervisor Pattern

One agent oversees others:

from agents import Agent, function_tool, Runner

workers = {
    "data": Agent(name="data_worker", instructions="Process data."),
    "analysis": Agent(name="analysis_worker", instructions="Analyze results."),
}

@function_tool
async def delegate(task_type: str, task: str) -> str:
    """Delegate a task to a worker agent."""
    if task_type not in workers:
        return f"Unknown worker type: {task_type}"
    
    result = await Runner.run(workers[task_type], task)
    return result.final_output

supervisor = Agent(
    name="supervisor",
    instructions="Coordinate workers to complete complex tasks.",
    tools=[delegate],
)

Debate Pattern

Agents discuss and reach consensus:

from agents import Agent, Runner

pro_agent = Agent(
    name="pro",
    instructions="Argue in favor of the proposition.",
)

con_agent = Agent(
    name="con", 
    instructions="Argue against the proposition.",
)

judge_agent = Agent(
    name="judge",
    instructions="Evaluate arguments and reach a conclusion.",
)

async def debate(topic: str, rounds: int = 3):
    history = [f"Topic: {topic}"]
    
    for _ in range(rounds):
        # Pro argument
        pro_result = await Runner.run(pro_agent, "\n".join(history))
        history.append(f"Pro: {pro_result.final_output}")
        
        # Con argument
        con_result = await Runner.run(con_agent, "\n".join(history))
        history.append(f"Con: {con_result.final_output}")
    
    # Final judgment
    verdict = await Runner.run(judge_agent, "\n".join(history))
    return verdict.final_output

Router Pattern

Route requests to appropriate specialists:

from agents import Agent

specialists = {
    "billing": Agent(name="billing", instructions="Handle billing."),
    "technical": Agent(name="technical", instructions="Handle tech issues."),
    "sales": Agent(name="sales", instructions="Handle sales inquiries."),
}

router = Agent(
    name="router",
    instructions="""Route customer requests to the right specialist:
    - Billing questions → billing
    - Technical issues → technical  
    - Purchase inquiries → sales""",
    handoffs=list(specialists.values()),
)

Shared Context

Agents share state through context:

from dataclasses import dataclass, field
from agents import Agent, Runner, function_tool

@dataclass
class SharedState:
    findings: list[str] = field(default_factory=list)
    decisions: list[str] = field(default_factory=list)

@function_tool
def add_finding(ctx, finding: str) -> str:
    """Add a finding to shared state."""
    ctx.context.findings.append(finding)
    return f"Added finding: {finding}"

@function_tool
def add_decision(ctx, decision: str) -> str:
    """Record a decision."""
    ctx.context.decisions.append(decision)
    return f"Recorded: {decision}"

state = SharedState()
result = await Runner.run(coordinator, "Analyze and decide", context=state)
print(f"Findings: {state.findings}")
print(f"Decisions: {state.decisions}")

Error Recovery

Handle agent failures:

from agents import Runner, AgentsException

async def run_with_fallback(primary: Agent, fallback: Agent, prompt: str):
    try:
        return await Runner.run(primary, prompt)
    except AgentsException:
        return await Runner.run(fallback, prompt)

See Also