Escalate a live call from an AI agent to a human without dropping the audio or minting a new call. This is the telephony-plane view of a handoff: what the SIP gateway does on the wire when you call transfer(...), how the sid survives, and how a human — on a browser softphone or a real deskphone — gets rung and takes over the media. For the product-level model and the bidirectional (bot ⇄ human) framing, start at Handoffs; this page is the mechanics underneath it. A handoff can be driven two ways over the same gateway. You (your app, or an operator dashboard) call transfer(...) on the SDK. Or the AI agent itself decides mid-conversation and calls a built-in telephony tool — transfer_call, route_to_skill, warm_transfer / complete_transfer, or consult / consult_transfer / consult_cancel — with no operator config required. Both land on the same B2BUA and preserve the same sid; the tool path just lets the model pick the moment and the style. These tools are the same operations exposed to ISV apps as CSTA verbs — see CTI call control.

The one call keeps its sid

A call is a SIP dialog with two legs — caller and agent — held together by a back-to-back user agent (B2BUA) in the SIP gateway. The sid names that dialog and is the universal key: the same value addresses the CDR, the recording, the analytics segments, and the media tracks. A handoff re-points the agent leg only; the caller leg never moves, so the caller hears uninterrupted audio and the sid is unchanged before, during, and after.
   caller leg  ─────────┐
   (never moves)        │      ┌─── agent leg ─▶  AI agent      segment 1 (handler=ai)
                   B2BUA ┤─────┤
   same sid  ───────────┘      └─── agent leg ─▶  human agent   segment 2 (handler=human)
                              (only this leg re-points)
Because the dialog is preserved, the call-events pipeline emits a transfer transition on the existing sid (not an END), and downstream folds the call into multiple segments under one sid, split by whether an AI or a human handled each stretch — the ”12s with the bot, 4m18s with a human” breakdown. See Call lifecycle for the full event sequence and Sessions, calls, tracks & streams for the object model.
When is a sid created vs preserved? A sid is minted once, when the call first exists — at the inbound INVITE, or when you call calls.originate() outbound. Every handoff after that preserves it. You never create a sid for a transfer; you pass the one you already hold.

Two mechanisms, picked by target

The SDK exposes one method — transfer(...) — and the gateway chooses the mechanism from which field you set:
You passMechanismMedia stays on our plane?
agent: "<id>"In-place re-attach of the agent leg (skill-queue router or a named human/AI agent)Yes
to: "<E.164>"SIP REFER — ask the far end to re-target its leg to a phone number or PBXNo (once accepted, off-net)
Exactly one of agent / to per transfer. A bare string is shorthand for { to }.

Escalate to a human (re-attach)

Route the caller into the skill-queue router (ACD), which rings an available human and bridges them in on accept — or transfer to one named person. The caller leg holds; the agent leg re-points to the human once they answer.
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" });
The human who answers can be a browser softphone or a real SIP deskphone/softphone — the accept signal is unified, so your transfer code is identical either way. When the human claims the call, the gateway dials their endpoint (an INVITE to the registered contact, or out through a trunk for a PSTN callback), waits for the 200 OK, and bridges the leg into the same B2BUA. How agents register, get rung, and claim a call — including ring strategy and glare handling — is in PBX & ACD.

Transfer off-net via SIP REFER

When the target is a phone number (a PSTN destination or another PBX), the gateway performs a SIP REFER (RFC 3515) — the standard request that asks the far end to re-target its leg. You don’t build the REFER yourself; passing to is enough.
await call.transfer({ to: "+15557654321" });  // → SIP REFER
await call.transfer("+15557654321");          // shorthand, same thing
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, so recording, barge-in, supervise, and re-attach are gone for the rest of the call. When you want to keep those, prefer transfer({ agent }) to a human on a softphone or deskphone; that keeps the media on our plane.

Handoff tools the AI agent calls itself

Everything above is the operator-driven view — your code holds the sid and calls transfer(...). But most escalations should be the agent’s own decision, made in the flow of the conversation. Every AI agent gets a built-in telephony toolset with no operator config: the runtime advertises these tools to the model automatically, and when the model calls one, the gateway runs the exact same B2BUA operation on the live sid. (These are first-class runtime tools, not user-declared functions — see Tool calling for how the toolset is advertised and how an operator tool of the same name overrides a built-in.) There are three transfer styles, and the right one is a caller-experience choice — does the caller hear the handoff, and does the AI stay on the line?
ToolWhat the caller hearsAI stays or leavesWhen to use
transfer_callBrief pause, then the destination — no handoff spokenLeaves immediatelyFastest path. You know exactly where the caller should go (a queue URI, a PSTN number, another PBX) and no context needs to pass by voice.
route_to_skillQueue treatment (ringback / hold audio) until a human answersLeaves (steps out to the ACD)“Get me a human” with no specific number — hand to a human skill/queue and let the ACD pick the agent.
warm_transfercomplete_transferEverything — the AI and the human brief each other in a shared conference, caller includedStays through the brief, then leaves on complete_transferA smooth, human-feeling handoff where the caller hears “I’ve got Priya here, she can take it from…”. Context passes out loud.
consultconsult_transfer / consult_cancelNothing — caller is held (hold audio) while the AI checks privatelyStays; can return to the caller with consult_cancelVerify a human is available / get an answer before committing the caller. If it works out, consult_transfer; if not, consult_cancel and keep talking to the caller.
destination for transfer_call, warm_transfer, and consult accepts a skill name, an extension, a SIP URI (sip:queue@pbx.example.com), or a PSTN number in E.164 (+15551234567); transfer_call also accepts a tel: URI.

Blind — transfer_call

The fastest exit. The AI hands the caller away and drops off the call in one step (a SIP REFER under the hood, same as an operator transfer({ to })). Nothing is spoken to the receiving party first.
destination
string
required
Where to send the caller — a skill name, extension, SIP URI, tel: URI, or E.164 number.
referred_by
string
Optional Referred-By identity to present on the REFER. Defaults to the trunk identity.

Queue to a human skill — route_to_skill

Send the caller to a human skill/queue (the ACD) without naming a person or number. The AI steps out; the skill-queue router rings an available human and bridges them onto the same sid.
skill
string
The target skill/queue. Omit to use the agent’s default escalation skill.

Warm (attended) — warm_transfer then complete_transfer

The AI dials the destination and joins a conference so it can speak the handoff. The caller hears everything and the AI stays live — this is the transfer that feels human.
1

AI calls warm_transfer { destination }

The gateway dials destination and joins it into a conference with the caller. The caller hears the ring, then all three parties are connected — caller, human, and AI.
2

The AI briefs the human, out loud, in the conference

“This is Sam calling about order 4471, they need a refund exception.” The caller hears the whole brief, so nothing feels like it happened behind their back. The human can ask the AI (or the caller) questions before accepting.
3

AI calls complete_transfer { }

The AI leg stops. Caller and human stay connected on the same sid; a transfer transition is recorded and analytics opens a new human segment.

Private consult — consult then consult_transfer / consult_cancel

An attended, one-to-one check with a third party that the caller does not hear. The caller is effectively on hold while the AI confirms availability or gets an answer, then commits or backs out.
1

AI calls consult { destination }

The caller is placed on hold (hold audio) and the AI dials destination on a private leg. The caller hears none of the consult conversation.
2

The AI speaks privately with the consulted party

“I have a caller who needs a refund exception on order 4471 — can you take it?” Only the AI and the consulted party are on this leg.
3

Commit — consult_transfer { }

Connects the caller to the consulted party and drops the AI out. The caller comes off hold already bridged to the human.
4

…or back out — consult_cancel { }

Hangs up on the consulted party and returns the AI to the caller (the caller comes off hold). Use this when the human can’t take it — the AI keeps handling the call and can try another path.
Transfer-rule policy still applies. Whichever tool the model calls, the transfer passes the realm’s transfer-rule policy. A denied cross-realm transfer returns a structured error the model can react to (apologize, try route_to_skill, offer a callback) rather than failing silently.

Supporting in-call tools

The same built-in toolset gives the AI the rest of the mid-call controls, so it can shape the caller experience around a handoff:
ToolParamsWhat it does
hold_call / unhold_callPark the caller on hold audio and bring them back.
disconnect_callreason?End the call; reason is written to the CDR.
send_dtmfdigit (0-9*#A-D), duration_ms? (default 100), mode (rfc2833|inband)Play DTMF into the call — e.g. to navigate a downstream IVR before or after a transfer.
request_supervisorreason, urgency (low|medium|high)Ask a supervisor to monitor / whisper / barge in without moving the caller leg.

What happens on the wire

1

You call transfer(sid, …)

The control-plane API forwards the request to the SIP gateway over its correlated RPC channel. The gateway looks up the live dialog by sid.
2

The agent leg is re-pointed, REFERred, or conferenced

For agent: / route_to_skill the gateway re-attaches the agent leg in the B2BUA (dial the human endpoint or hand to the skill-queue router). For to: / transfer_call it issues a SIP REFER toward the leg you’re forwarding. For warm_transfer it joins the destination into a conference with the caller; for consult it holds the caller and opens a private leg to the consult target.
3

A transfer lifecycle event fires on the same sid

The gateway emits a transferred transition (and, when it is the receiver of a peer REFER, auto-acknowledges with 202 Accepted). No END is emitted — the sid lives on. Recording continues; analytics opens a new segment tagged with the new handler (AI vs human).
4

The far end takes over

For a re-attach, the human’s 200 OK completes the bridge and audio flows to the new agent leg. For an off-net REFER, the referred party accepts and the caller is now talking to the external number.

Peer-initiated REFER (inbound)

The reverse also happens: a remote party sends us a REFER (a carrier or upstream PBX asking us to forward a call). The gateway auto-answers it with 202 Accepted and records a transferred lifecycle event on the sid, so the transfer shows up correctly in traces and CDRs.
Honest status — executing the outbound leg from a peer REFER. We acknowledge an incoming REFER today, but automatically placing the new outbound leg it asks for (following the referred-to target end to end) is partially in progress. If your topology depends on upstream-initiated blind or attended transfer driving a fresh outbound call, validate it against your carrier in staging before you rely on it. Operator-initiated transfer (you calling transfer(...)) and off-net REFER from us are the fully supported paths.

Bot ⇄ human re-attach on the media plane

For an on-plane handoff (agent:), the media stays on our transport the whole time, which is what makes bot → human → bot bouncing possible on one sid:
  • The caller’s audio is carried as a caller-audio track keyed on the sid; the human agent takes over by picking up that track and injecting their mic into the caller’s egress. Because subscription is by sid (not a fixed shard), the human can live on a different core or host and still hear the caller with no central funnel.
  • Handing back to an AI agent is the same transfer({ agent }) primitive with an AI agent id — the bridge re-points in place, the sid is unchanged, and the call remains one continuous record.
// Human is done; hand back to an automated wrap-up agent.
await call.transfer({ agent: "post-call-summary" });
Human-agent return audio (browser softphone). The human agent’s mic uplink into the caller is live. The downlink — the human hearing the caller over the media-over-QUIC track in the browser softphone — 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 today, validate the return-audio path in staging. Real SIP deskphone/softphone agents are not affected — their media rides the normal RTP bridge.

Handoffs (concept)

The product model: AI ⇄ human, warm handoff, sid preservation.

Tool calling

How the built-in telephony toolset is advertised to the AI agent.

CTI call control

The same transfer / consult operations as CSTA verbs for ISV apps.

PBX & ACD

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

Call lifecycle

Every event a call emits, including transfer transitions.

SIP trunking

The trunk edge REFER rides out over for off-net transfers.

Support agent with handoff

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

Transfer to a human

Copy-paste transfer snippet.