Skip to content
Learn Agentic AI
Learn Agentic AI12 min read8 views

Multi-Agent Orchestration Patterns: Manager vs Delegation in OpenAI Agents SDK

Learn the two core multi-agent orchestration patterns in the OpenAI Agents SDK — Agents as Tools (Manager) and Handoffs (Delegation) — with code examples and a decision framework for choosing the right approach.

Why Multi-Agent Orchestration Matters

Building a single AI agent is relatively straightforward. Building a system where multiple specialized agents collaborate on complex tasks is where real engineering challenges emerge. The OpenAI Agents SDK provides two fundamentally different orchestration patterns, and choosing the wrong one can make your system fragile, slow, or impossible to debug.

This post breaks down both patterns — Agents as Tools (Manager pattern) and Handoffs (Delegation pattern) — with working code, architectural trade-offs, and a decision framework you can apply to your own projects.

Pattern 1: Agents as Tools (Manager Pattern)

In this pattern, a central manager agent orchestrates the workflow by calling other agents as if they were tools. The manager retains full control of the conversation. Sub-agents execute discrete tasks and return results to the manager, which synthesizes everything into a final response.

flowchart TD
    START["Multi-Agent Orchestration Patterns: Manager vs De…"] --> A
    A["Why Multi-Agent Orchestration Matters"]
    A --> B
    B["Pattern 1: Agents as Tools Manager Patt…"]
    B --> C
    C["Pattern 2: Handoffs Delegation Pattern"]
    C --> D
    D["Comparing the Two Patterns"]
    D --> E
    E["Hybrid Approaches"]
    E --> F
    F["Decision Framework"]
    F --> G
    G["Common Pitfalls"]
    G --> H
    H["Summary"]
    H --> DONE["Key Takeaways"]
    style START fill:#4f46e5,stroke:#4338ca,color:#fff
    style DONE fill:#059669,stroke:#047857,color:#fff

How It Works

The manager agent sees each sub-agent as a callable tool. When the manager decides it needs specialized work done, it invokes the sub-agent tool, waits for the result, and continues its own reasoning with that result incorporated.

from agents import Agent, Runner
import asyncio

# Define specialized sub-agents
research_agent = Agent(
    name="ResearchAgent",
    instructions="""You are a research specialist. Given a topic,
    provide detailed factual information with sources.
    Be thorough but concise. Return structured findings.""",
    model="gpt-4o",
)

analysis_agent = Agent(
    name="AnalysisAgent",
    instructions="""You are a data analysis specialist.
    Given research findings, identify key trends, patterns,
    and actionable insights. Provide quantified assessments
    where possible.""",
    model="gpt-4o",
)

# Define the manager agent that uses sub-agents as tools
manager_agent = Agent(
    name="ManagerAgent",
    instructions="""You are a project manager coordinating research
    and analysis tasks. Use your research tool to gather information,
    then use your analysis tool to derive insights. Synthesize
    everything into a clear executive summary.""",
    model="gpt-4o",
    tools=[
        research_agent.as_tool(
            tool_name="research",
            tool_description="Gather detailed research on a given topic"
        ),
        analysis_agent.as_tool(
            tool_name="analyze",
            tool_description="Analyze research findings for trends and insights"
        ),
    ],
)

async def main():
    result = await Runner.run(
        manager_agent,
        input="Investigate the current state of AI agent frameworks in 2026"
    )
    print(result.final_output)

asyncio.run(main())

Key Characteristics of the Manager Pattern

Centralized control: The manager agent decides when to call sub-agents, what inputs to provide, and how to combine results. The sub-agents never see each other or the end user directly.

Preserved context: Because the manager maintains the conversation thread, it has full visibility into what has been done and what remains. This makes it easy to implement retry logic or adjust strategy mid-execution.

Structured data flow: Sub-agents return their results to the manager. You can enforce structured outputs on sub-agents to guarantee clean data passing:

from pydantic import BaseModel

class ResearchFindings(BaseModel):
    topic: str
    key_facts: list[str]
    sources: list[str]
    confidence_score: float

research_agent = Agent(
    name="ResearchAgent",
    instructions="Research the given topic thoroughly. Return structured findings.",
    model="gpt-4o",
    output_type=ResearchFindings,
)

# When used as a tool, the manager receives a ResearchFindings object
manager_agent = Agent(
    name="ManagerAgent",
    instructions="Use research tool then synthesize findings.",
    model="gpt-4o",
    tools=[
        research_agent.as_tool(
            tool_name="research",
            tool_description="Research a topic and return structured findings"
        ),
    ],
)

Pattern 2: Handoffs (Delegation Pattern)

In the delegation pattern, agents transfer full conversational control to one another. When Agent A hands off to Agent B, Agent B becomes the active agent and directly interacts with the user (or continues the task). Agent A is no longer in the loop.

How It Works

You define handoff targets on each agent. The SDK manages the transfer of context and conversation state between agents.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

from agents import Agent, Runner, handoff
import asyncio

# Define specialist agents
billing_agent = Agent(
    name="BillingAgent",
    instructions="""You handle all billing-related questions.
    You can look up invoices, explain charges, and process
    payment method updates. Be precise with dollar amounts.""",
    model="gpt-4o",
)

technical_agent = Agent(
    name="TechnicalAgent",
    instructions="""You handle all technical support questions.
    You can troubleshoot issues, guide users through configurations,
    and escalate bugs to engineering.""",
    model="gpt-4o",
)

# Define the triage agent with handoffs
triage_agent = Agent(
    name="TriageAgent",
    instructions="""You are the first point of contact for customer
    support. Determine the nature of the customer's issue and route
    them to the appropriate specialist:
    - Billing questions → BillingAgent
    - Technical issues → TechnicalAgent
    Keep your initial interaction brief. Do not attempt to solve
    the problem yourself.""",
    model="gpt-4o",
    handoffs=[
        handoff(billing_agent, description="Transfer to billing specialist for payment and invoice questions"),
        handoff(technical_agent, description="Transfer to technical support for product issues and bugs"),
    ],
)

async def main():
    result = await Runner.run(
        triage_agent,
        input="I was charged twice for my subscription last month"
    )
    print(f"Final agent: {result.last_agent.name}")
    print(f"Response: {result.final_output}")

asyncio.run(main())

Key Characteristics of the Delegation Pattern

Decentralized control: Each agent operates independently once it receives control. There is no manager watching over the process.

Full context transfer: When a handoff occurs, the receiving agent gets the conversation history (configurable). It can continue the interaction as if it had been there from the start.

Specialization: Each agent can have its own tools, instructions, and model. The billing agent might use GPT-4o-mini for cost efficiency while the technical agent uses GPT-4o for complex reasoning.

Comparing the Two Patterns

Dimension Manager (Agents as Tools) Delegation (Handoffs)
Control flow Centralized — manager orchestrates Decentralized — agents self-route
Context visibility Manager sees everything Each agent sees its own context
User interaction Only manager talks to user Active agent talks to user
Parallelism Manager can call multiple tools Sequential handoffs only
Error recovery Manager can retry or re-route Receiving agent must handle errors
Latency Higher — extra LLM call for manager Lower — direct agent response
Complexity Simpler to reason about Requires careful handoff design

Hybrid Approaches

Real-world systems often combine both patterns. A triage agent uses handoffs to route to specialist departments, and each specialist uses sub-agents as tools for specific tasks:

flowchart TD
    ROOT["Multi-Agent Orchestration Patterns: Manager …"] 
    ROOT --> P0["Pattern 1: Agents as Tools Manager Patt…"]
    P0 --> P0C0["How It Works"]
    P0 --> P0C1["Key Characteristics of the Manager Patt…"]
    ROOT --> P1["Pattern 2: Handoffs Delegation Pattern"]
    P1 --> P1C0["How It Works"]
    P1 --> P1C1["Key Characteristics of the Delegation P…"]
    style ROOT fill:#4f46e5,stroke:#4338ca,color:#fff
    style P0 fill:#e0e7ff,stroke:#6366f1,color:#1e293b
    style P1 fill:#e0e7ff,stroke:#6366f1,color:#1e293b
from agents import Agent, Runner, handoff

# Sub-agent tools for the billing specialist
invoice_lookup_agent = Agent(
    name="InvoiceLookup",
    instructions="Look up invoice details given a customer ID and date range.",
    model="gpt-4o-mini",
)

refund_calculator_agent = Agent(
    name="RefundCalculator",
    instructions="Calculate refund amounts based on subscription terms and usage.",
    model="gpt-4o-mini",
)

# Billing specialist uses sub-agents as tools
billing_agent = Agent(
    name="BillingAgent",
    instructions="""You handle billing questions. Use your tools to
    look up invoices and calculate refunds when needed.""",
    model="gpt-4o",
    tools=[
        invoice_lookup_agent.as_tool(
            tool_name="lookup_invoice",
            tool_description="Look up invoice details for a customer"
        ),
        refund_calculator_agent.as_tool(
            tool_name="calculate_refund",
            tool_description="Calculate refund amount for a subscription"
        ),
    ],
)

# Technical specialist (similar setup)
diagnostic_agent = Agent(
    name="DiagnosticAgent",
    instructions="Run diagnostic checks and return results.",
    model="gpt-4o-mini",
)

technical_agent = Agent(
    name="TechnicalAgent",
    instructions="Handle technical issues. Use diagnostics tool when needed.",
    model="gpt-4o",
    tools=[
        diagnostic_agent.as_tool(
            tool_name="run_diagnostics",
            tool_description="Run diagnostic checks on user's system"
        ),
    ],
)

# Triage uses handoffs to route
triage_agent = Agent(
    name="TriageAgent",
    instructions="Route customers to the right department.",
    model="gpt-4o",
    handoffs=[
        handoff(billing_agent, description="Billing and payment issues"),
        handoff(technical_agent, description="Technical and product issues"),
    ],
)

Decision Framework

Use this framework to choose your orchestration pattern:

flowchart TD
    CENTER(("Core Concepts"))
    CENTER --> N0["You need a single agent to synthesize r…"]
    CENTER --> N1["The workflow requires parallel executio…"]
    CENTER --> N2["You want centralized error handling and…"]
    CENTER --> N3["The final output must combine informati…"]
    CENTER --> N4["You need strict control over what infor…"]
    CENTER --> N5["The user needs to interact with a speci…"]
    style CENTER fill:#4f46e5,stroke:#4338ca,color:#fff

Choose Manager (Agents as Tools) when:

  • You need a single agent to synthesize results from multiple specialists
  • The workflow requires parallel execution of sub-tasks
  • You want centralized error handling and retry logic
  • The final output must combine information from multiple domains
  • You need strict control over what information flows between agents

Choose Delegation (Handoffs) when:

  • The user needs to interact with a specialist directly
  • Each specialist has a fundamentally different conversation style
  • You want to minimize latency for the end user
  • The workflow is naturally sequential (triage → specialist)
  • Specialists need their own tool sets and model configurations

Choose Hybrid when:

  • You have a triage/routing layer followed by deep specialist work
  • Specialists need their own sub-agents for complex tasks
  • The system serves multiple distinct use cases under one entry point

Common Pitfalls

Over-centralization: Making the manager agent responsible for too much logic. If your manager prompt exceeds 2000 tokens of instructions, consider breaking it into handoffs.

Under-specified handoffs: Not providing clear descriptions for when each handoff should trigger. The SDK uses the handoff description to help the agent decide when to transfer.

Ignoring context limits: In the manager pattern, every sub-agent call adds tokens to the manager's context. For long workflows, this can hit model limits.

Missing error boundaries: In the delegation pattern, if a specialist agent fails, there is no manager to catch the error. Build fallback handoffs or error handling into each specialist.

Summary

The OpenAI Agents SDK gives you two powerful orchestration primitives. The Manager pattern provides centralized control and is ideal for synthesis tasks. The Delegation pattern provides decentralized routing and is ideal for interactive support systems. Most production systems use a hybrid of both. Choose based on your specific requirements around control flow, user interaction, and error handling.

Share
C

Written by

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.