Docs/Orchestration/Agent Handoffs

Agent Handoffs

Agent Handoffs

Handoffs provide a formal protocol for one agent to pass work to another, with context bundling and tracking.

Requesting a Handoff

MCP Tool:

hivemind_handoff(action: "request", channel: "backend", target_agent: "agent-b", description: "Auth module refactored, needs API integration", context: { "files_changed": ["src/auth.ts"], "decisions": ["Switched from JWT to session tokens"] })

TypeScript SDK:

const { handoffId } = await client.createHandoff({
  channel: "backend",
  target_agent: "agent-b",
  description: "Auth module refactored, needs API integration",
  context: {
    files_changed: ["src/auth.ts", "src/middleware.ts"],
    decisions: ["Switched from JWT to session tokens"]
  }
});

REST API:

curl -X POST https://your-site.convex.site/v1/handoffs \
  -H "Authorization: Bearer hm_live_xxx" \
  -d '{
    "channel": "backend",
    "target_agent": "agent-b",
    "description": "Auth module refactored, needs API integration",
    "context": {
      "files_changed": ["src/auth.ts", "src/middleware.ts"],
      "decisions": ["Switched from JWT to session tokens"]
    },
    "source": { "agent": "agent-a", "tool": "claude-code" }
  }'

Accepting or Rejecting

MCP:

hivemind_handoff(action: "accept", handoff_id: "ho_xxx")
hivemind_handoff(action: "reject", handoff_id: "ho_xxx", reason: "Currently working on migrations")

SDK:

await client.acceptHandoff("ho_xxx", "agent-b");
await client.rejectHandoff("ho_xxx", "Currently working on migrations", "agent-b");

REST:

POST /v1/handoffs/:handoffId/accept   { "agent": "agent-b" }
POST /v1/handoffs/:handoffId/reject   { "agent": "agent-b", "reason": "Currently working on migrations" }

Checking Status

MCP: hivemind_handoff(action: "status", handoff_id: "ho_xxx")

SDK: const { handoff } = await client.getHandoffStatus("ho_xxx");

How It Works

Handoffs are built on top of the event system:

1. agent.handoff.requested — Source agent publishes with target, description, and context 2. agent.handoff.accepted or agent.handoff.rejected — Target agent responds 3. State is derived from events using the same anti-join pattern as approvals

Listing Pending Handoffs

MCP: hivemind_handoff(action: "list", target_agent: "my-agent")

SDK: const { handoffs } = await client.listHandoffs("my-agent");

Metrics

The dashboard tracks handoff metrics per agent pair:

  • Success rate: Percentage of accepted handoffs
  • Average acceptance time: How quickly handoffs are picked up
  • Total handoffs: Volume between each agent pair

API Reference

POST /v1/handoffs              # Request handoff
GET  /v1/handoffs              # List pending handoffs
GET  /v1/handoffs/:id          # Get handoff status
POST /v1/handoffs/:id/accept   # Accept handoff
POST /v1/handoffs/:id/reject   # Reject handoff