Hand a live call between an AI agent and a human — in either direction — without dropping the audio and without changing the identifier the call is addressed by. A handoff swaps who is on the far end of the media bridge; it does not tear down and re-create the call. The same sid keeps addressing it before, during, and after, so every recording, transcript, and analytics row keyed on that sid stays one continuous story. There are three moves you’ll actually make:
HandoffWhat happensMechanism
AI → humanThe bot escalates; a human takes over the live audio.Re-attach the bridge to a human agent or queue
Human → AIA human hands back to an AI agent (deflection, after-hours, ACW).Re-attach the bridge to an AI agent
Transfer off-netForward the caller to an external number or PBX.SIP REFER from the gateway

Everything hangs off one sid

A call is a SIP dialog with two legs — caller and agent — held together by a B2BUA (back-to-back user agent) in the SIP gateway. The sid names that dialog. When you hand off, only the agent leg is re-pointed; the caller leg never moves, so from the caller’s perspective the audio path is uninterrupted.
                        ┌──────────────  same sid  ──────────────┐
                        │                                          │
   caller leg  ─────────┤  B2BUA  ├─── agent leg ──▶  AI agent      │  segment 1 (handler=ai)
   (never moves)        │  (SIP gateway)                            │
                        │         └─── agent leg ──▶  human agent   │  segment 2 (handler=human)
                        └───────────────────────────────────────────┘
Because the sid survives, the call events pipeline emits a TRANSFER_INITIATED (or REFER_RECEIVED) transition rather than an END, and downstream folds the call into multiple segments under one sid — split by whether an AI or a human handled each stretch. That’s what powers a correct ”12s with the bot, 4m18s with a human” breakdown instead of two unrelated calls. See Sessions, calls, tracks & streams for the object model and Call traces for the segment rows.

AI → human

The bot decides it needs a person — an intent it can’t satisfy, a compliance trigger, an explicit “let me talk to someone”. You transfer the live call to a human. Two flavors:
  • To a skill queue — route the caller into the ACD (skill-queue router), which rings an available human agent and bridges them in on accept. Use this when any qualified agent will do.
  • To a specific human — transfer to a named agent, a browser softphone, or a phone number. Use this for warm escalations to a known owner.
import { Voice } from "@telequick/sdk/voice";

const v = new Voice({
  baseUrl: "https://engine.telequick.dev",
  apiKey:  process.env.TELEQUICK_CREDENTIALS!,
  orgId:   "org_abc",
});

// A call is already live with a triage bot; you hold its sid.
const call = await v.calls.get({ sid });

// Escalate to the human support queue — the ACD picks the agent.
await call.transfer({ agent: "human-support" });

// …or hand straight to one on-call person's number.
await call.transfer({ to: "+15557654321" });
The human who answers can be a browser softphone or a real SIP deskphone/softphone — the accept path is unified, so your transfer code is identical either way. How agents get rung and claim a call is covered in PBX & ACD.
Warm handoff / screen-pop. The product thesis for regulated verticals is that the AI does intent, qualification, auth, and compliance capture first, then a context bundle screen-pops to the human before audio cuts in. The routing and accept legs are shipped today; the rich context payload that travels with the transfer is assembled at your application layer — you build the context bundle, there is no turnkey field for it yet.

Human → AI

The reverse move re-attaches an AI agent to a live call — deflect a queued caller to a self-service bot, drop into an after-hours agent, or run automated wrap-up. It’s the same transfer({ agent }) call; you just name an AI agent instead of a human queue. The bridge re-points in place and the sid is unchanged, so a call can bounce bot → human → bot and still be one record.
// Human is done; hand back to an automated wrap-up agent.
await call.transfer({ agent: "post-call-summary" });

Transfer off-net via SIP REFER

When you transfer to a phone number (a PSTN destination or another PBX), the gateway performs a SIP REFER — the standard way to ask the far end to re-target its call leg. You don’t construct the REFER yourself; passing to is enough, and a bare string is shorthand for { to }.
await call.transfer({ to: "+15557654321" });  // → SIP REFER
await call.transfer("+15557654321");          // shorthand, same thing
The gateway records the transfer as a REFER_RECEIVED lifecycle transition on the same sid. Rule of thumb: to → SIP REFER (off-net); agent → in-place re-attach (on our media plane). Either way the original sid keeps addressing the call.
A blind REFER to a PSTN number hands the caller to the carrier and off our media plane — once the far end accepts, you no longer control that audio. Prefer transfer({ agent }) to a human on a softphone or deskphone when you want to keep recording, barge-in, and re-attach available for the rest of the call.

Bot ⇄ human re-attach, step by step

1

Hold the sid

You get a sid from calls.originate() (outbound) or the inbound call webhook. It is the only identifier you need for every later step — transfer, hang up, fetch recordings, read analytics.
2

Decide the target

Human queue (agent: "human-support"), a specific human, an AI agent, or an off-net number (to). Exactly one of agent / to per transfer.
3

Transfer

Call transfer(...). The caller leg stays put; the agent leg re-points. The caller hears continuous audio (optionally hold media while the queue rings).
4

It re-attaches, it doesn't restart

A TRANSFER_INITIATED / REFER_RECEIVED event fires on the same sid. Recording continues, and analytics opens a new segment tagged with the new handler (AI vs human) — no new call is created.

Honest status

  • AI → human transfer — shipped. Routing into the queue and human accept work end to end (a prior transfer-teardown crash is fixed).
  • Human → AI re-attach — shipped, same transfer({ agent }) primitive.
  • sid preservation across handoffs — shipped; segments fold under one sid by handler.
  • Human-agent two-way audio (browser softphone). The agent’s mic uplink is live; the downlink leg (the human hearing the caller over the media-over- QUIC track) is still being hardened — the caller-audio origin publish needs to be bridged into the relay fan-out. If you’re standing up browser softphone agents right now, validate the return audio path in staging. Real SIP deskphone agents are not affected.
  • Warm screen-pop context payload — application-level today (see the Note above), not a turnkey feature.

AI-to-Human Handoff

The telephony-plane view of escalation and accept.

PBX & ACD

How the skill-queue router rings and claims human agents.

Support agent with handoff

A full inbound bot that escalates to a human, end to end.

Transfer to a human

Copy-paste transfer snippet.

Call lifecycle

Every event a call emits, including transfers.

Sessions, calls, tracks & streams

Why the sid is the one identifier that matters.