A handoff lets one AI agent transfer control of a task to another without a separately coded transition. Think of a research assistant passing its findings to a planner, which passes a plan to a file-writing assistant. Each agent has a focused job, while the flow continues across agents. section 4.3.1
Choose how much control the routing code should retain:
- Conversational handoff keeps communication on a shared conversation thread and reduces orchestration code. The trade-off is that routing dependencies live partly in agent instructions, where they can be harder to inspect. section 4.3 section 4.3.1
- Pass-off routing calls each agent explicitly in code. It takes more code but gives you precise control over each input, output, and decision point. section 4.3
Research → planning → file
Give the research agent instructions to hand off to the thinking agent, and connect it with `research_agent.handoffs = [thinking_agent]`. Give the thinking agent instructions to hand off to the filesystem agent, and connect that route too. Start the run with the research agent; the agents then make the configured transfers without separate calls for each transition. The research agent must know the next agent’s name, so changing names or routes also means checking its instructions. section 4.3.1 section 4.5
Listing 4.6 05_visualizing_agent_flows.py
research_agent.mcp_servers = [research_srv]
research_agent.handoffs = [thinking_agent]
thinking_agent.mcp_servers = [thinking_srv]
thinking_agent.handoffs = [filesystem_agent]
filesystem_agent.mcp_servers = [fs_srv]
from agents.extensions.visualization import draw_graph
draw_graph(research_agent).view() #1
input("Press Enter to continue...") #2
The listing shows the two `handoffs` connections and uses `draw_graph(research_agent)` to make the resulting agent-to-agent route visible. section 4.3.2
Inspect the route as well as the result. `draw_graph()` shows the agent flow; Dashboard Traces lets you examine calls within it. For transfer data that the default handoff view does not expose, wrap a handoff with an `on_handoff` callback and a typed input model. Use that callback to observe and log what passes between agents, not as the main way to reject bad data. section 4.3.2 section 4.3.3
A smooth transfer is not necessarily a safe one. Watch for data in the wrong shape, excess context, or upstream content treated as instructions. Put guardrails at high-stakes boundaries, especially before writes, sends, or irreversible actions; use them to block or correct bad data. If a guardrail triggers, handle recovery deliberately and limit retries. For larger flows, keep agent names stable and visualize routes early: names identify agents in routing, traces, and dashboards. section 4.4.3 section 4.3.2

