Multi-Agent Handoff
%%{init: {'look': 'handDrawn', 'theme': 'base', 'themeVariables': {'primaryColor': '#eef2ff', 'primaryBorderColor': '#1e40af', 'primaryTextColor': '#1e293b', 'lineColor': '#1e3a8a', 'edgeLabelBackground': '#ffffff', 'clusterBkg': '#fbfcff', 'clusterBorder': '#2563eb', 'fontFamily': '-apple-system, system-ui, Segoe UI, Roboto, Helvetica, Arial, sans-serif', 'fontSize': '15px'}, 'flowchart': {'nodeSpacing': 50, 'rankSpacing': 58, 'padding': 14, 'htmlLabels': true, 'curve': 'basis'}}}%%
flowchart LR
R(["Customer request"]) --> S("Supervisor")
subgraph team["specialists · the model picks one"]
direction TB
B("Billing")
T("Technical")
L("Sales")
end
S --> B
S --> T
S --> L
B --> O(["Answer"])
T --> O
L --> O
style team stroke-dasharray: 6 5Outcome: one supervisor agent fronts a team of specialists. The supervisor's model sees each specialist as a callable tool and delegates; each delegation is its own durable execution.
How it works
- Sub-agents become tools. With
Strategy.HANDOFFthe supervisor's model chooses one by name. - Each specialist keeps its own tools and instructions, so their reach stays separate.
- Every delegation is a durable execution. A specialist can retry without re-running the routing decision.
Handoff strategies
strategy= accepts any of these. The values come from Strategy in the SDK:
| Strategy | What the parent does |
|---|---|
handoff |
The model picks one sub-agent and hands the conversation over |
router |
The model classifies the request and routes it, without conversing |
sequential |
Runs sub-agents in order, each seeing the previous output |
parallel |
Runs all sub-agents at once and collects every answer |
swarm |
Sub-agents pass control between themselves until one finishes |
round_robin |
Takes the next sub-agent in rotation |
random |
Picks a sub-agent at random — useful for A/B comparison |
plan_execute |
Plans a sequence of sub-agent calls, then executes and replans |
manual |
You choose the sub-agent in code, not the model |
Prerequisites
A Conductor server with an LLM provider, and CONDUCTOR_SERVER_URL set.
The agents
Save this as agent_handoff.py:
"""Multi-agent handoff — a supervisor delegates to the specialist that fits.
Derived from sdk/python-sdk/examples/agents/05_handoffs.py.
With Strategy.HANDOFF the sub-agents are exposed to the supervisor's model as
callable tools, and the model picks one. Each delegation is its own durable
Conductor execution, so a specialist can retry without re-running the router.
"""
from conductor.ai.agents import Agent, AgentRuntime, Strategy, tool
MODEL = "openai/gpt-4o-mini"
@tool
def check_balance(account_id: str) -> dict:
"""Check the balance of a bank account."""
return {"account_id": account_id, "balance": 5432.10, "currency": "USD"}
@tool
def lookup_order(order_id: str) -> dict:
"""Look up the status of an order."""
return {"order_id": order_id, "status": "shipped", "eta": "2 days"}
@tool
def get_pricing(product: str) -> dict:
"""Get pricing information for a product."""
return {"product": product, "price": 99.99, "discount": "10% off"}
billing = Agent(
name="billing",
model=MODEL,
instructions="You handle billing questions: balances, payments, invoices.",
tools=[check_balance],
)
technical = Agent(
name="technical",
model=MODEL,
instructions="You handle technical questions: order status, shipping, returns.",
tools=[lookup_order],
)
sales = Agent(
name="sales",
model=MODEL,
instructions="You handle sales questions: pricing, products, promotions.",
tools=[get_pricing],
)
support = Agent(
name="support_supervisor",
model=MODEL,
instructions="Route each request to the right specialist: billing, technical, or sales.",
agents=[billing, technical, sales],
strategy=Strategy.HANDOFF,
)
if __name__ == "__main__":
with AgentRuntime() as runtime:
result = runtime.run(support, "What's the balance on account ACC-123?")
result.print_result()
print("execution id:", result.execution_id)
Run it
Asking for an account balance routes to billing, which calls check_balance. Open Executions to see the supervisor and the chosen specialist as separate executions.
The same example in other SDKs
The agent API is the same shape in every SDK. These are the upstream sources this recipe was derived from:
| SDK | Example |
|---|---|
| Python | 05_handoffs.py |
| Java | Example05Handoffs.java |
| TypeScript | 05-handoffs.ts |
| C# | Program.cs |
Production notes
- Specialist instructions are the routing signal. Overlapping descriptions cause wrong handoffs.
- Scope each specialist's tools separately. A billing agent should not reach order-fulfilment tools.
- Pick the strategy for the shape of the problem, not for novelty —
routeris cheaper thanhandoffwhen no conversation is needed. - Bound each specialist independently so one can't consume the whole budget.
- Handoff decisions are model output. Log which specialist ran and why.