---
title: "Multi-Agent Orchestration Patterns: Manager vs Delegation in OpenAI Agents SDK"
description: "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."
canonical: https://callsphere.ai/blog/multi-agent-orchestration-patterns-manager-vs-delegation-openai-agents-sdk
category: "Learn Agentic AI"
tags: ["OpenAI", "Multi-Agent", "Orchestration", "Architecture", "Patterns"]
author: "CallSphere Team"
published: 2026-03-14T00:00:00.000Z
updated: 2026-05-06T18:44:23.277Z
---

# 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.

```mermaid
flowchart LR
    INPUT(["User input"])
    AGENT["Agent
name plus instructions"]
    HAND{"Handoff to
another agent?"}
    SUB["Sub-agent
specialist"]
    GUARD{"Guardrail
passed?"}
    TOOL["Tool call"]
    SDK[("Tracing
OpenAI dashboard")]
    OUT(["Final output"])
    INPUT --> AGENT --> HAND
    HAND -->|Yes| SUB --> GUARD
    HAND -->|No| GUARD
    GUARD -->|Yes| TOOL --> AGENT
    GUARD -->|Block| OUT
    AGENT --> OUT
    AGENT --> SDK
    style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
    style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
    style SDK fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
    style OUT 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.

```python
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:

```python
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.

```python
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:

```python
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:

**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.

---

Source: https://callsphere.ai/blog/multi-agent-orchestration-patterns-manager-vs-delegation-openai-agents-sdk
