1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
25 small wins to finish your pathNext lesson →
Handing work to another agent
One agent with twelve tools and a thousand words of instructions is hard to work on. Two agents, each with one job, are not.
Two specialists
billing = Agent(name="Billing", instructions="You handle refunds and charges.",
model=PretendModel(["I have started your refund."]))
technical = Agent(name="Technical", instructions="You handle bugs and logins.",
model=PretendModel(["Try logging out and back in."]))And a router
triage = Agent(
name="Triage",
instructions="Send the customer to the right team.",
model=PretendModel([call("transfer_to_billing")]),
handoffs=[billing, technical],
)transfer_to_billing is not a name anyone typed. The SDK builds one tool per handoff, named after the agent, and putting an agent in that list is all it takes.
result = await Runner.run(triage, "I was charged twice")
print("answer: ", result.final_output)
print("ended with: ", result.last_agent.name)The answer came from Billing, and last_agent says so. Triage contributed nothing to the reply except the decision to step aside.
Why this is worth doing
- Each agent gets short instructions. Billing does not need to know how logins work.
- Tools stay where they belong. Only Billing has the refund tool, so Technical cannot issue one by accident.
- You can test them alone. Billing is an agent, so run it directly.
It does not come back
A handoff is one way. Billing does not report back to Triage, it takes over the conversation. When you want an answer back instead, that is the next lesson.
Try it yourself
- Script
transfer_to_technicalinstead and watch the other path. - Print
[type(i).__name__ for i in result.new_items]and find the handoff. - Give Billing a tool and confirm Technical cannot see it.
Slow is fine. Stopping is the only problem.