Concepts
Handoffs
Peer-to-peer agent handoffs — declarative handoffs[] + Handoff.create.
Canonical contract:
packages/sdk/docs.md— "Agent handoffs (v1.16+)".
Handoffs let an agent transfer control to another peer agent — useful for routing, specialization, and multi-agent flows.
Declarative
const billing = await Agent.create({
apiKey, model,
name: "billing-agent",
systemPrompt: "You handle billing questions.",
});
const router = await Agent.create({
apiKey, model,
name: "router",
systemPrompt: "Triage. Transfer to billing-agent if the user mentions invoice or charge.",
handoffs: [billing], // synthesized tool: transfer_to_billing-agent
});
await (await router.send("I was charged twice this month")).wait();
// Router calls transfer_to_billing-agent → billing handles the rest.Handoff-as-tool
Handoffs are implemented as synthetic tools (ADR D214). The agent decides to "call" transfer_to_<name> like any other tool. Inspired by openai-agents-python — proven pattern.
Handoff.create for customization
import { Handoff } from "@theokit/sdk";
import { z } from "zod";
const handoff = Handoff.create(billing, {
toolName: "escalate_to_billing",
inputType: z.object({ reason: z.string() }),
onHandoff: async (input) => console.log("[handoff]", input.reason),
inputFilter: (history) => history.slice(-5), // only last 5 messages
});Guards
- Peer-to-peer (D217) — handoffs are not parent-child. The receiver runs independently.
- Max depth 5 (D218) — default chain limit. Configurable.
- Single-flight per pair (D221) — same (sender, receiver) pair can't recurse within one
send(). - First-wins on parallel handoff tools (D226) — if the model emits 2 handoffs in one turn, only the first executes.
- CloudAgent throws
UnsupportedRunOperationError(D122) — handoffs are local-only in v1.