Multi-Agent
Multi-agent work in Shiro is built on handoffs: control moves to another registered agent while the same runner continues the run. You are not starting a disconnected second chat — you are changing who is responsible mid-execution.
Why handoffs exist#
Different domains need different tools and policies. A support agent that can also delete accounts or issue refunds is a footgun. A billing agent with refund tools and approval gates is clearer — and the handoff shows up in traces and Studio’s graph.
Support Triage
│ handoff (invoice domain)
▼
Billing Agent ──► lookupInvoice / issueRefund (+ approval)How it fits the runtime#
- Define specialist agents
engine.registerAgent(...)so they can be resolved- Attach a
handoffstrategy on the source agent (seeHandoffStrategyin core) - Execute once — the runner records handoff events
engine.registerAgent(billing);
engine.registerAgent(research);
const support = new Agent({
name: "support",
instructions: "Triage issues. Hand off billing questions.",
provider: "openai",
tools: [classifyIssue],
handoff: myHandoffStrategy, // HandoffStrategy
});Implement HandoffStrategy.evaluate to return HandoffDecisionStatus.Handoff with a
targetAgent name, or Continue to stay on the current agent.
When to hand off#
| Use a handoff | Do not |
|---|---|
| Tools / approval policy change | Prompt is slightly long |
| Domain ownership changes | You want a second opinion in parallel (model that explicitly) |
| Specialist needs narrower permissions | Cosmetic “agent personas” with the same tools |
Depth limits#
Unbounded handoff loops are a real failure mode. The engine owns a handoff depth limiter so a misconfigured strategy cannot recurse forever. Design acyclic happy paths; if you need cycles, document why.
Observability#
Handoffs emit events and appear as:
- Terminal lines (
→ Handoff → billing) - Graph edges between agents
- Trace events you can export
Best practices#
- Register every handoff target on the engine
- Give specialists fewer tools, not more
- Put approval on the specialist’s mutating tools
- Keep reasons in the handoff decision for operators
Common mistakes#
- Calling
engine.execute(specialist)manually and calling it a handoff - Sharing one mega-tool-list across all agents
- Circular handoffs without a depth policy
- Hiding the transfer outside the runner (Studio will not see it)