1Overview
Control transfer between agents: a triage or orchestrator agent deciding that a different agent, with different tools and instructions, should continue the conversation.
CrewAI, Flowise and Langflow teach you to author agents and give them roles. None of them teaches the moment that actually defines a multi-agent system: one agent transferring control, and state, to another. → What travels across a handoff, what silently does not, and what happens when the receiving agent was the wrong choice. → The chapter opens with the test most multi-agent projects fail: whether a second agent is doing anything a second prompt could not.
One agent hands control to another. That transfer — what it carries, what it loses, and what happens when it picks wrong — is the whole of multi-agent design. The chapter starts by trying to talk you out of it, because most multi-agent systems are a single agent with extra latency.
1.2After this chapter you can
→Say what a handoff transfers and what it drops
→Build a triage agent that routes to specialists and can hand back
→Carry state across a transfer without re-sending the whole history
→Put a guardrail on the boundary rather than inside every agent
→Diagnose a handoff loop and a handoff that went to the wrong specialist
→Apply the test for when a single agent with more tools is the better design
1.3When to reach for it
When sub-tasks need genuinely different tools, permissions or system prompts — not merely different phrasing.
1.4Key parts
A router, a set of specialists, the state that travels with the handoff, guardrails on the boundary, and a way back to the router.
1.5Free vs paid
All three anchors are free and open. The cost is tokens: every handoff re-establishes context, and a chatty router can double a task's bill.
1.6Watch out
A framework in maintenance mode still installs cleanly. Check the banner before you build on it — one of the best-known multi-agent frameworks now redirects users elsewhere from its own README.
2Lessons 8
2.1 Decide if a handoff really needs a second agent
The decision point determines if a sub‑task truly needs a separate specialised agent or can be handled by extending the current one with extra tools.
Choose whether to add a second agent or enrich the existing agent with additional capabilities
- Assess whether the sub‑task requires a different set of tools, a distinct system prompt, or another model that the current agent cannot handle while keeping context
- If it does not, rewrite the existing prompt or attach the required tool to the current agent instead of creating a new one
- If it does, design a second specialised agent for that sub‑task and plan a handoff between the agents
- You'll see A clear decision about using one enriched agent versus two linked agents
- Takeaway Add a second agent only when a sub‑task truly needs a different toolset, prompt or model – otherwise extend the first agent’s capabilities
- Check What criteria tell you that a sub‑task should be delegated to a new specialised agent rather than handled by extending the original agent with extra tools?
- Cost Free to reason about — this lesson is a question you ask before writing any code, not a tool you run.
2.2 Control what data crosses an agent handoff
The RunContextWrapper.context attribute is the shared context object passed to agent.run and used by handoffs.
Pass only conversation history automatically and supply any additional state explicitly through the run context
- Open the openai‑agents‑python repository and locate the SDK source for RunContextWrapper.context
- When calling agent.run, provide a dictionary in the context argument containing any IDs, flags or variables you need to share
- Verify that only the chat transcript moves automatically while other state is supplied via the context object
- You'll see The receiving agent can quote earlier messages but asks for information that was never part of the transcript
- Takeaway A handoff carries the full conversation by default; everything else must be supplied through a shared context object
- Check How do you make sure that only the chat history is transferred automatically while other required data is passed explicitly during an agent handoff?
- Cost Free — this is a property of the handoff mechanism, not a paid call.
2.3 Route requests between agents and hand them back
A handoffs list on an Agent declares which other agents it may transfer control to and receive it back from.
Create a triage router that forwards queries to specialists and regains control when the request is mis‑routed
- Define a triage_agent with
handoffs=[billing_agent, technical_agent] so it can forward to either specialist - Create billing_agent and technical_agent, each listing triage_agent in their own handoffs array for returning control
- Write the triage prompt to instruct the model to only read the request and call the appropriate handoff tool
- Implement each specialist so that, if the query is out of scope, it invokes its own handoff back to triage_agent
- Run a test conversation that triggers forward from triage to billing, handback to triage, then forward to technical
- You'll see The transcript shows control moving from triage to billing, back to triage, and finally to technical with each handoff named in the log
- Takeaway A handoffs list on every Agent enables two‑way routing so mistakes can be corrected without dead ends
- Check What structure lets a triage router forward a request to specialist agents and regain control when the specialist determines the request is mis‑routed?
- Cost One model call per agent turn, same as a single-agent conversation — a handoff adds a routing decision, not a second full request per hop by itself.
2.4 Trim handoff history for the next agent
The input_filter parameter lets you rewrite the conversation data that a specialist receives during a handoff.
Show only the relevant parts of the transcript to the receiving specialist
- Open the handoff definition file and locate the input_filter argument
- Write a function that accepts a HandoffInputData object, removes unwanted tool calls or irrelevant messages, and returns the trimmed data
- Assign this function to the input_filter field for the specific handoff you want to customise
- Optionally set a default filter in RunConfig.handoff_input_filter to apply globally
- You'll see The specialist’s first reply no longer references hidden tool calls that were stripped by the filter
- Takeaway Input filters, set per‑handoff or globally via
RunConfig.handoff_input_filter, control exactly what history each specialist receives and per‑handoff settings override the global one - Check Which parameter allows you to prune the incoming handoff data so a specialist only sees the conversation parts that matter?
- Cost Fewer tokens per hop than the unfiltered default — trimming the input to a handoff is one of the few things in this chapter that actively reduces cost rather than just avoiding avoidable extra cost.
2.5 Place guardrails at the edges of a multi‑agent chain
Guardrails can be attached to the first agent’s input, the final agent’s output, and any shared tool used mid‑chain.
Protect the workflow boundaries by validating inputs at the start and outputs at the end of a multi‑agent chain
- Locate the first agent in the chain and enable its input guardrails setting
- Find the final agent that produces the answer and enable its output guardrails setting
- Identify any shared function tool that may be called by multiple specialists and add a tool guardrail to enforce validation
- You'll see A malformed request is rejected immediately at the triage stage before any specialist runs
- Takeaway Guardrails fire only at the chain edges, so place mid‑chain checks on the tool itself via a tool guardrail
- Check Where should you enable input and output guardrails in a multi‑agent workflow to keep the ends safe while allowing specialists to run freely?
- Cost One guardrail evaluation per boundary per run — cheaper than the naive version of a check on every agent, since most agents in the chain never trigger it anyway.
2.6 Detect handoff loops and misrouted specialists in a trace
Each handoff_span() entry in the trace records a single handoff event, enabling detection of loops or misroutes.
Identify looping or misrouted handoffs directly from the execution trace
- Open the trace view in your observability console
- Read each handoff_span() entry in order as they appear in the timeline
- Spot a repeating pair of identical handoff spans with no intervening tool calls – that indicates a loop
- Recognise a single handoff followed by unrelated tool calls as evidence of a misrouted specialist
- You'll see The trace shows
handoff_span() entries where a repeated pair marks a loop and an isolated mismatched handoff signals a wrong‑specialist route - Takeaway Tracing handoffs reveals routing errors so you can fix loops or misroutes without altering code
- Check What pattern in the sequence of handoff_span() entries tells you that a handoff loop has occurred?
- Cost Reading a trace is free; a live handoff loop is not — every repeated hop is a full model call plus whatever the input filter still lets through of the growing history.
2.7 Calculate token impact of handoffs and optimise routing
The token count displayed in the trace reflects the impact of each handoff on cost, showing how filtered inputs lower duplication.
Reduce unnecessary token costs by evaluating each handoff and configuring the router to limit context duplication.
- Review the trace to compare token usage between direct and multi‑agent paths.
- Apply an input filter to trim the transferred conversation history before each handoff.
- Configure the router to forward only when a single agent with a tool cannot handle the request.
- You'll see A trace shows two token counts for the same request: one from a direct single‑agent response and another from a triage‑then‑specialist path that pays for the transcript twice.
- Takeaway Token cost grows with each hop because the receiving agent reprocesses the full context, so deliberate routing and fewer handoffs minimise expense
- Check How can applying an input filter before each handoff reduce token duplication costs?
- Cost Each handoff adds at minimum one full re-read of the transferred history by the receiving model, on top of whatever new work that agent does — the SDK doesn't discount a repeated context the way a human skimming a forwarded email would.
2.8 Identify superseded multi‑agent frameworks
The top banner of a repository’s README.md file indicates whether the framework has been superseded or is still maintained.
Determine whether a multi‑agent framework is still actively maintained by checking its repository README
- Search for the repository using GitHub search
- Open the repository by clicking its name link
- Select the README.md file to view its contents
- Read the top banner of the README for a maintenance‑mode notice
- You'll see Two READMEs, opened directly, each stating in its own words that the project has been superseded
- Takeaway A framework’s early popularity doesn’t guarantee it remains current; always verify its maintenance status in the README before building on it
- Check Which file and section should you inspect to confirm whether a multi‑agent framework has been marked as superseded?
- Cost A few minutes to read a README before committing a project to a framework — far cheaper than migrating off one mid-build.