Skip to main content

AI-voice warm handoff to a human agent

When an AI voice agent hits something it cannot resolve — a caller asks for a person, an account action needs approval, the caller is frustrated — the worst outcome is a cold hangup followed by a redial. The warm handoff keeps the caller connected: the call is bridged straight into one of your ACD queues, and the human agent who picks up sees a screen-pop containing an AI summary of the call so far, caller sentiment, key topics, action items, and every piece of data the bot already collected. The caller never has to repeat themselves. This guide covers the inbound AI → human bridge end to end: the transfer_to_human tool, the handoff packet, the read endpoint the agent desktop uses, and the internal mirror the agent runtime calls. For outbound-dialer overflow (routing excess campaign volume to humans), see Live-human overflow for AI voice-agent campaigns.

1. The handoff contract

Two tenant-facing endpoints drive the handoff:
  • POST /api/v1/voice/calls/:id/ai-handoff — bridge a live call into an ACD queue and stamp the handoff packet onto the call record.
  • GET /api/v1/voice/calls/:id/ai-handoff — read the persisted packet for the screen-pop.
The POST is invoked by the agent runtime when the voice agent invokes the transfer_to_human tool (see §5 for how that reaches the API), or by your own integration when you build a custom escalation path. It accepts queue_id (the ACD queue to enqueue into) and a free-text reason for the escalation. Optional fields include collected_slots, priority, required_skills, and the conference_id when the bot is in a multi-party session. The orchestration runs in a fixed order so the caller never loses audio:
  1. Generate (or reuse the cached) AI call summary.
  2. Assemble and persist the handoff packet onto the call record.
  3. Enqueue the live caller into the ACD queue — the warm bridge.
  4. Drop the bot leg from the conference, only after the caller is safely queued.
Routing back into your own ACD queue means no outbound leg is dialled; the caller stays on the line they already have.

2. Enable the transfer_to_human tool on the voice agent

transfer_to_human is one of the built-in tools listed when you create an agent — the built-in name is transfer_agent in the agent creation flow (Creating agents). On a live voice session the tool takes two parameters: Write an escalation rule into the agent’s instructions — for example, “if the caller asks for account unlock, verify their member ID, then call transfer_to_human”. By the time the tool fires, any slots the agent filled (member ID, email, intent) travel into the handoff packet as collected_slots. For tenant-specific escalation logic — picking a queue by business hours, checking VIP status before choosing a skill group — wrap the decision in a custom tool that resolves the queue and have the agent pass the result to transfer_to_human. See Custom tools.

3. What’s in the handoff packet

The packet is a versioned JSON blob stored on the call record, and the agent desktop renders it as the screen-pop on pickup. Every summary field is fail-open: if the call had no usable transcript at escalation time, summary and transcript are null and the handoff still completes — a missing summary never blocks the bridge.

4. Reading the packet back: the GET endpoint

The agent desktop calls GET /api/v1/voice/calls/:id/ai-handoff when the dispatcher matches the caller to a human agent, so the screen-pop renders at pickup. It returns:
  • 200 with handoff: <packet> for a call that was AI-escalated.
  • 200 with handoff: null for a real call that was never AI-escalated — the common case, not an error.
  • 404 only when the call id itself does not resolve in your tenant.
Poll once at pickup; the packet is stamped once at handoff time and does not change.

5. How the internal mirror fits

The tenant-facing POST is gated behind dashboard/API auth, so the live bot itself cannot call it. The agent runtime instead calls the machine-to-machine twin:
  • POST /api/v1/internal/voice/ai-handoff — same orchestrator, same packet, authenticated by an internal service token instead of a user session.
You only call this endpoint if you operate your own voice-agent runtime against Orbit and need to hand off directly. For dashboard-built agents the runtime fires it automatically when the agent invokes transfer_to_human. Treat it as infrastructure: no sandbox key, no customer API key — internal token only.

6. Warm handoff vs supervisor takeover

This guide covers the Agent → Agent (AI → human) bridge: the AI decides to escalate and the caller moves into a queue. It is a different operation from supervisor-driven monitoring, where a supervisor actively snoops, whispers, or takes over a call a human agent is handling. If a supervisor action fails, see Supervisor takeover failures. The AI warm handoff and supervisor takeover never interact — a handoff packet on the call record does not change what a supervisor can do with the call.

7. Worked example: the account-lock escalation

An inbound caller reaches your AI concierge. The concierge verifies their member ID, determines the account is locked, and decides a human must handle it. 1. The agent invokes the tool. With the built-in tool name transfer_agent enabled on the agent, the voice session receives the tool call as transfer_to_human with:
2. Direct API invocation (optional). If you drive the handoff from your own integration instead, POST to the tenant-facing endpoint:
The endpoint returns 202 with the queue position, whether a summary was generated, whether the bot leg was dropped, and the full packet:
3. The screen-pop renders. When a support agent accepts the queued call, the desktop reads the packet with the GET endpoint and renders the reason, summary, sentiment chips, collected-slot fields, and the transcript — the human picks up knowing everything the bot learned.

Troubleshooting

  • 422 with queue_id is required — the tool fired without a queue id. Configure the escalation queue and re-run the agent simulation.
  • 404 on the GET — the call id is not in this tenant’s call records; check you are reading with the same tenant key that owns the call.
  • handoff: null on the GET — the call exists but no AI escalation was recorded. Either the tool never fired (check the agent’s tool-call history) or the POST failed upstream (check the agent runtime logs for a non-2xx from the internal endpoint).