Pass it on (default)
All steps
"I was charged twice"
"The app crashes on login"
Parts of this pattern
- User Input / output
- The customer, who talks to whichever agent currently holds the conversation, e.g. 'I was charged twice'.
- Triage Agent
- Front-desk agent. Works out what the user needs and hands off to billing or tech, without solving it itself.
- Billing Agent
- Specialist for charges, invoices and plans. Owns the conversation after handoff and may pass it to refunds.
- Tech support Agent
- Specialist for errors, bugs and how-to questions, e.g. an app that crashes on login.
- Refunds Agent
- Specialist that issues refunds and replies to the user itself.
- User → Triage
- The user's first message lands with the triage agent.
I was charged twice for my March invoice.
- Triage → Billinghandoff
- Triage passes the whole conversation and a one-sentence goal to billing, then steps out.
transfer_to_billing: "User says they were charged twice on the March invoice and wants it fixed."
- Triage → Tech supporthandoff
- Triage passes the whole conversation to tech support, then steps out.
transfer_to_tech: "User reports the app crashes whenever they log in."
- Billing → User
- Billing answers the user directly, with no manager in between.
I can see two charges of $29 on March 3. Want me to look into a refund?
- Tech support → User
- Tech support answers the user directly.
Let's try clearing the app cache. Go to Settings > Storage > Clear cache, then log in again.
- Billing → Refundshandoff
- Billing passes the baton, with the full history, when the user asks for money back.
transfer_to_refunds: "Duplicate $29 charge on March 3 confirmed; user wants a refund."
- Refunds → User
- Refunds replies to the user itself, ending the run with this agent holding the conversation.
Done: I've refunded $29 to your card. It should arrive in 3-5 days.
Hand back
A specialist hands the conversation back to triage when its part is done, with a summary, so triage can route whatever is left.
All steps
Parts of this pattern
- User Input / output
- The customer, with two problems in one message: 'I was charged twice, and the app crashes on login.'
- Triage Agent
- Front-desk agent. Routes each open part of the request to a specialist, and takes the conversation back when a specialist is done.
- Billing Agent
- Specialist for charges, invoices and plans. Fixes the double charge, then hands the conversation back to triage.
- Tech support Agent
- Specialist for errors, bugs and how-to questions. Takes the crash report that triage passes on after billing is done.
- User → Triage
- The user's message lands with the triage agent.
I was charged twice for March, and the app crashes whenever I log in.
- Triage → Billinghandoff
- Triage passes the conversation to billing with the first goal.
transfer_to_billing: "User was charged twice on the March invoice and wants it fixed. They also report a login crash."
- Billing → User
- Billing answers the user directly about its part.
I've refunded the duplicate $29 charge from March 3. It should reach your card in 3-5 days.
- Billing → Triagehand back
- Billing hands the conversation back to triage with a summary of what is done and what is still open.
transfer_back_to_triage: "Duplicate March charge refunded. Still open: the app crashes on login."
- Triage → Tech supporthandoff
- Triage passes the open part, the crash, to tech support.
transfer_to_tech: "Billing is resolved. User reports the app crashes whenever they log in."
- Tech support → User
- Tech support answers the user directly.
Let's fix the crash: go to Settings > Storage > Clear cache, then log in again.
Remembers active agent
The system stores which agent was last active, so the user's next message goes straight to that agent and skips triage.
All steps
Parts of this pattern
- User Input / output
- The customer, who sends a follow-up message after billing has already helped them.
- Triage Agent
- Front-desk agent. Only sees a conversation when no agent is active yet, or when a specialist hands it back.
- Billing Agent
- Specialist for charges, invoices and plans. Once active, it gets the user's follow-up messages directly.
- Tech support Agent
- Specialist for errors, bugs and how-to questions; not needed in this conversation.
- Active agent Memory
- A small store per conversation holding the name of the agent that last held it, such as billing.
- User → Triage
- With no active agent stored, the first message goes to triage.
I was charged twice for my March invoice.
- Triage → Billinghandoff
- Triage passes the conversation to billing.
transfer_to_billing: "User says they were charged twice on the March invoice."
- Triage → Tech supporthandoff
- The route triage would use for a technical problem.
transfer_to_tech: "User reports the app crashes on login."
- Billing → Active agentrecord
- The handoff writes billing to the store as the active agent before billing runs.
conversation 7f3a: active_agent = billing
- Billing → User
- Billing answers the user directly.
I can see two charges of $29 on March 3. I've refunded one; it arrives in 3-5 days.
- User → Active agentnext message
- The user's next message is routed by the store, not by triage.
Thanks. Can you also send me the corrected March invoice?
- Active agent → Billingresume
- The store names billing, so billing is called first, with the full history.
active_agent = billing: calling billing with 4 messages of history.
← → neighboursesc atlas
Handoffs
Also known as Decentralized pattern · Swarm · Peer-to-peer
Agents pass the whole conversation to each other; the agent holding it talks directly to the user, and there's no central manager.
Popularized by OpenAI Solutions team (2024) · OpenAI
Swarm, an experimental, educational framework released in 2024, made a handoff a tool call that passes the conversation on. The OpenAI Agents SDK replaced it, and the 2025 agent guide calls this the decentralized pattern.
Measured over one run
Pass it on
- Nodes
- 5. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 5. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 0. Messages sent to a tool node in the first scenario.
- Steps
- 6. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 2. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- no. Whether two or more messages are in flight at the same time.
- Branch
- yes. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- high. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- medium. Relative token spend per request.
- Latency
- medium. Relative wall-clock time per request.
Hand back
- Nodes
- 4. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 6. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 0. Messages sent to a tool node in the first scenario.
- Steps
- 6. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 1. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- no. Whether two or more messages are in flight at the same time.
- Branch
- yes. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- high. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- medium. Relative token spend per request.
- Latency
- medium. Relative wall-clock time per request.
Remembers active agent
- Nodes
- 5. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 3. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 0. Messages sent to a tool node in the first scenario.
- Steps
- 5. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 1. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- no. Whether two or more messages are in flight at the same time.
- Branch
- yes. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- high. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- medium. Relative token spend per request.
- Latency
- medium. Relative wall-clock time per request.
Counted from the first scenario's timeline when the site is built.
Problem
A customer chat starts as a vague complaint and turns into three different jobs: diagnose a charge, explain a plan, issue a refund. A single agent prompted for all of them is bloated and error-prone. A central manager fixes that but puts a middleman between the user and every answer, adding a hop and a place to lose context.
How it works
Treat control of the conversation as a baton. Each agent has instructions, tools, and a list of other agents it may transfer to. A handoff is just a tool call, such as transfer_to_billing, and its effect is that the next agent takes over the same message history.
The user first reaches the triage agent. It works out the goal and hands off to billing, or to tech support for a crash report. From then on billing answers the user directly. When the user asks for their money back, billing hands the baton on to refunds, which finishes the job.
Notice what is absent: no manager sits in the middle. The agent holding the baton is the only one active, and the others wait. Because the history travels with the baton, the user never repeats themselves. This is the decentralized style described in OpenAI’s agent guide and demonstrated in its Swarm example, now succeeded by the Agents SDK.
Two variants extend the baton. With a hand-back, a specialist returns the conversation to triage with a summary when its part is done, so one message can be served by several specialists in turn. With active-agent memory, the system stores who last held the conversation, so the user’s next message goes straight back to that agent instead of through triage.
When to use
- The right specialist only becomes clear during the conversation.
- You want the user to talk directly to the expert, with low latency.
- Each agent has distinct instructions or tools, and tasks flow naturally from one to the next.
When to avoid
- You need one place to control, log or veto all work. Use a supervisor.
- The request needs one classification and a one-shot answer. Routing is simpler.
- Agents must work in parallel on the same task.
Trade-offs
Handoffs are fast and conversational, but control is spread out, so there is no single view of what is going on. Each agent needs a clear picture of when to transfer and to whom, and the transfer graph grows quickly as agents are added.
Failure modes
- Ping-pong: two agents keep passing the user back and forth. Add a hop limit and make boundaries explicit.
- Lost context: the new agent re-asks things already said. Have the sender summarize the goal in the handoff.
- Premature handoff: the agent transfers before it should. Say in the instructions what it must try first.
- Dead ends: the user lands with an agent that cannot help and cannot transfer onward. Give every agent a way back to triage or a human.
Build it with your AI
Pass it on
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the Handoffs pattern in this codebase, using the LLM client and language we already use.
## Goal
Let a user talk directly to whichever specialist agent fits the conversation, by passing one shared message history between agents through handoff tool calls, with no manager in the middle.
## How it works
1. Define each agent with its instructions, its own tools, and one handoff tool for each agent it may transfer to, such as transfer_to_billing, each taking a one-sentence goal.
2. Keep one message history per conversation and an active-agent pointer that starts at the triage agent, which runs with the Triage agent instructions.
3. On each user message, call the active agent with the full history.
4. If it calls a handoff tool, append the handoff and its goal to the history, move the pointer to the target agent, and call that agent, with the Specialist agent instructions, on the same history in the same turn.
5. If it replies without handing off, send the reply to the user; the pointer stays where it is for the next message.
## Prompts
### Triage agent instructions
```markdown
You are the front desk for {{company}}. Greet the user and work out what
they need. Do not try to solve the problem yourself.
Hand off with exactly one tool:
- transfer_to_billing: charges, invoices, plans
- transfer_to_tech: errors, bugs, how-to questions
Before you hand off, state the user's goal in one sentence so the next
agent does not have to ask again.
```
### Specialist agent instructions
```markdown
You are the {{role}} agent for {{company}}. You now own this conversation.
The full history above is yours to read.
Help the user directly. If the request belongs to another agent, hand off
with {{handoff_tools}} and say what you are passing on.
Never ask the user to repeat something already in the history.
```
## Stop rule
A turn ends when the active agent replies to the user. Allow at most 3 handoffs per user message; on the cap, send a short apology and route the conversation to a human.
## Requirements
- Make the per-message handoff cap a parameter (default 3), to stop two agents passing the user back and forth.
- Treat a handoff to an unknown or disallowed agent as a tool error returned to the calling agent, not a crash.
- Require the goal argument; if it is empty, return a tool error asking the agent to state the user's goal.
- Log every handoff with the agent it came from, the agent it went to, and the goal.
- Add a test with a stub LLM where triage hands off to billing and billing hands off to refunds, which replies; assert the pointer ends at refunds and exactly two handoffs were logged.
Hand back
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the Handoffs pattern (Hand back variant) in this codebase, using the LLM client and language we already use.
## Goal
Serve a request that spans several specialists by letting each one hand the conversation back to triage when its part is done, so triage can route the rest.
## How it works
1. Give triage, which runs with the Triage agent instructions, one handoff tool per specialist; give every specialist, which runs with the Specialist agent instructions, a transfer_back_to_triage tool that takes a summary of what is done and what is left.
2. Keep one message history and an active-agent pointer that starts at triage; call the active agent with the full history on each user message.
3. When an agent calls a handoff tool, append the handoff and its argument to the history, move the pointer, and call the new agent in the same turn. An agent may send the user a message and call a handoff tool in one response: send the message, then follow the handoff.
4. When a specialist hands back, triage reads the summary and either hands the open part to another specialist or replies to the user.
5. Send whichever agent's reply ends the turn to the user.
## Prompts
### Triage agent instructions
```markdown
You are the front desk for {{company}}. Work out what the user needs.
Do not try to solve the problem yourself.
Hand off with exactly one tool:
- transfer_to_billing: charges, invoices, plans
- transfer_to_tech: errors, bugs, how-to questions
State the user's goal in one sentence when you hand off.
When a specialist hands the conversation back, read its summary. If
something is still open, hand that part to the right specialist;
otherwise ask the user whether there is anything else.
```
### Specialist agent instructions
```markdown
You are the {{role}} agent for {{company}}. You now own this conversation.
The full history above is yours to read.
Help the user with the part that is yours. When it is done, or if the
rest belongs to someone else, call transfer_back_to_triage with a
summary: what you did, and what is still open.
Never ask the user to repeat something already in the history.
```
## Stop rule
A turn ends when the active agent replies to the user without calling a handoff tool; a message sent together with a hand-back does not end it. Allow at most 4 handoffs per user message, hand-backs included; on the cap, apologize and route the conversation to a human.
## Requirements
- Make the per-message handoff cap a parameter (default 4).
- Require a non-empty summary on transfer_back_to_triage; if it is empty, return a tool error asking for one.
- Stop triage from handing straight back to the agent that just handed back with no new user message; return a tool error instead, to prevent ping-pong.
- Log every handoff and hand-back with its from, its to and its argument.
- Add a test with a stub LLM where triage hands off to billing, billing hands back saying 'refund done; crash still open', and triage hands off to tech; assert the pointer visits triage, billing, triage, tech in that order.
Remembers active agent
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the Handoffs pattern (Remembers active agent variant) in this codebase, using the LLM client and language we already use.
## Goal
Keep a multi-turn conversation with the specialist the user was last talking to, by storing the active agent per conversation and starting each new message there instead of at triage.
## How it works
1. Keep a store keyed by conversation id that holds the active agent's name; a new conversation starts at triage, which runs with the Triage agent instructions.
2. On each user message, load the active agent from the store and call it with the full history.
3. When an agent calls a handoff tool, write the target agent to the store first, then call the target, with the Specialist agent instructions, on the same history in the same turn.
4. Send the reply that ends the turn to the user; the stored agent stays active for the next message.
5. Have specialists hand back to triage when the user changes topic, which writes triage to the store.
## Prompts
### Triage agent instructions
```markdown
You are the front desk for {{company}}. Greet the user and work out what
they need. Do not try to solve the problem yourself.
Hand off with exactly one tool:
- transfer_to_billing: charges, invoices, plans
- transfer_to_tech: errors, bugs, how-to questions
Before you hand off, state the user's goal in one sentence so the next
agent does not have to ask again.
```
### Specialist agent instructions
```markdown
You are the {{role}} agent for {{company}}. You now own this conversation.
The full history above is yours to read.
Help the user directly. If the request belongs to another agent, hand off
with {{handoff_tools}} and say what you are passing on.
Never ask the user to repeat something already in the history.
```
## Stop rule
A turn ends when the active agent replies. Allow at most 3 handoffs per message; on the cap, reply with an apology and route to a human.
## Requirements
- Persist the store so a restart does not send every user back to triage.
- If the stored agent no longer exists, fall back to triage and log it.
- Reset the active agent to triage after a configurable idle time (default 30 minutes).
- Write the store before calling the new agent, so a crash mid-turn resumes with the right agent.
- Add a test with a stub LLM: on message 1 triage hands off to billing; on message 2 assert triage is never called and billing is called first.
Prompt templates
Pass it on · Remembers active agent
You are the front desk for {{company}}. Greet the user and work out whatthey need. Do not try to solve the problem yourself.
Hand off with exactly one tool:- transfer_to_billing: charges, invoices, plans- transfer_to_tech: errors, bugs, how-to questionsBefore you hand off, state the user's goal in one sentence so the nextagent does not have to ask again.You are the {{role}} agent for {{company}}. You now own this conversation.The full history above is yours to read.
Help the user directly. If the request belongs to another agent, hand offwith {{handoff_tools}} and say what you are passing on.Never ask the user to repeat something already in the history.Hand back
You are the front desk for {{company}}. Work out what the user needs.Do not try to solve the problem yourself.
Hand off with exactly one tool:- transfer_to_billing: charges, invoices, plans- transfer_to_tech: errors, bugs, how-to questionsState the user's goal in one sentence when you hand off.
When a specialist hands the conversation back, read its summary. Ifsomething is still open, hand that part to the right specialist;otherwise ask the user whether there is anything else.You are the {{role}} agent for {{company}}. You now own this conversation.The full history above is yours to read.
Help the user with the part that is yours. When it is done, or if therest belongs to someone else, call transfer_back_to_triage with asummary: what you did, and what is still open.Never ask the user to repeat something already in the history.Related patterns
Composes well with:
Sources
From the Agentic Atlas by Joran Kikke · Edit on GitHub · Suggest a correction