Transfer Ownership Only With a Contract
A handoff changes the active executor. So it must pass not all the accumulated noise but the goal, the needed artifacts, the constraints, and the remaining budget. A handoff is needed when the specialist must continue the interaction directly: after triage, technical support asks the user for clarifications, while the billing agent runs its own process. If the specialist does only background analysis, it's better to keep its tool with the manager.
import { Agent } from "@openai/agents";
const billing = new Agent({
name: "Billing specialist",
instructions: "Own billing requests after transfer."
});
const technical = new Agent({
name: "Technical specialist",
instructions: "Own technical support requests after transfer."
});
const triage = Agent.create({
name: "Triage",
instructions: "Classify the request and transfer it to exactly one specialist.",
handoffs: [billing, technical]
});In the companion project a handoff is a provider-independent envelope that checks the allowed topology edge, the goal's clarity, and the remaining budget before the transfer.
import type { AgentContract, AgentId, HandoffEnvelope } from "./types.js";
export function createHandoff(
source: AgentContract,
target: AgentId,
input: Omit<HandoffEnvelope, "from" | "to">
): HandoffEnvelope {
if (!source.allowedHandoffs.includes(target)) {
throw new Error(`Handoff ${source.id} -> ${target} is not allowed`);
}
if (input.goal.trim().length < 8) {
throw new Error("Handoff goal is too vague");
}
if (input.remainingCalls < 1) {
throw new Error("Handoff has no remaining call budget");
}
return { from: source.id, to: target, ...input };
}To choose between manager, router, and handoff for a specific case, use the lab.
Choose manager, router, or handoff
Router or an ordinary code switch: the path is known and ownership doesn't change.
Context transfer is not trust transfer. A subagent's summary stays untrusted input. Sign provenance, filter history, and re-verify important claims against the original tool results - otherwise prompt injection passes through "our own" agent.
Ownership is transferred with a contract. Where the branches are many and their number is set by the input, orchestrator-workers apply.