@theokit/sdk-handoff
v0.1.0
Published
Inter-agent dispatch for @theokit/sdk — typed Handoff descriptors, loop protection, plugin-based wiring.
Readme
@theokit/sdk-handoff
Inter-agent dispatch for @theokit/sdk. Typed Handoff descriptors with loop protection (self-reference, A↔B pair, multi-hop, receiver-disposed).
Extracted from @theokit/[email protected] as part of the SDK 2.0 package split (ADRs D214-D229).
Install
pnpm add @theokit/sdk @theokit/sdk-handoffQuick start
import { Agent } from "@theokit/sdk";
import { Handoff } from "@theokit/sdk-handoff";
const billing = await Agent.create({
name: "billing",
model: { id: "openai/gpt-4o-mini" },
});
const support = await Agent.create({
name: "support",
model: { id: "openai/gpt-4o-mini" },
// Preferred (new in 2.x): handoffs wire via Plugin protocol.
plugins: [Handoff.asPlugin({ targets: [billing] })],
});
await support.send("I need help with my invoice"); // → support delegates to billingThe previous Agent.create({ handoffs: [...] }) option is deprecated in 2.x. It still works while @theokit/sdk-handoff is installed (the framework lazy-imports the tool-injector at runtime), but the codemod marks every call site with a CODEMOD comment recommending the plugins: [Handoff.asPlugin({...})] pattern. Plan removes the option entirely in 2.0.0 cohort.
API
Handoff.asPlugin({ targets, maxHandoffDepth? }): Plugin
Returns a Plugin consumed by Agent.create({ plugins: [...] }). The plugin runs at agent initialization and appends one CustomTool per target agent into the host's tool registry. Each invocation of the tool dispatches the conversation to the target agent (loop-protected).
| Option | Type | Default | Notes |
|---|---|---|---|
| targets | Array<SDKAgent \| HandoffDescriptor> | (required) | Agents the host can hand off to. |
| maxHandoffDepth | number | 5 | Hop count cap. 0 disables handoff entirely. |
Errors
All errors extend Error and live in @theokit/sdk-handoff:
HandoffLoopError— multi-hop loop detected at runtime (A→B→C→A).HandoffPairLoopError— A→B and B→A registered simultaneously.HandoffSelfReferenceError— agent handoffs to itself.HandoffReceiverDisposedError— target was disposed before dispatch.HandoffNameCollisionError— two targets share the same agent name.
handoffTo(agent, opts?): HandoffDescriptor
Helper for one-off descriptor construction without going through Handoff.create.
How it fits with @theokit/sdk
- Foundation:
definePlugin,Plugin,CustomTool, andSDKAgenttypes come from@theokit/sdk. - Optional peer model:
@theokit/[email protected]lazy-imports@theokit/sdk-handoff/internal/tool-injectoronly whenAgent.create({ handoffs: [...] })is called. Without the package installed, the option throws an actionable error. - No kernel coupling beyond types: sdk-handoff never imports from
@theokit/sdk/internal/runtimeor the agent loop.
Migration from @theokit/[email protected]
Before (1.x):
import { Agent, Handoff, handoffTo } from "@theokit/sdk";
const support = await Agent.create({
name: "support",
handoffs: [billing],
});After (2.x):
import { Agent } from "@theokit/sdk";
import { Handoff } from "@theokit/sdk-handoff";
const support = await Agent.create({
name: "support",
plugins: [Handoff.asPlugin({ targets: [billing] })],
});See docs/migration/1-x-to-2-0.md in the monorepo root.
License
Apache-2.0.
