Transfers are made by the agent's transfer_call tool. When one goes wrong, the call record tells you which step failed: the transcript has a transfer item for each step, the call has a transfer_destination, and the disconnection_reason says how the call ended.
Transfer types#
| Type | transfer_option.type |
What happens |
|---|---|---|
| Cold, new call (default) | cold_transfer, cold_transfer_mode: sip_invite |
The runtime dials the destination into the same room. The caller hears ringback, the legs bridge, the agent leaves |
| Cold, SIP REFER | cold_transfer, cold_transfer_mode: sip_refer |
Tried asks the carrier to redirect the caller with SIP REFER |
| Warm | warm_transfer |
The caller hears hold music. The runtime dials the transferee, waits for a human, whispers a private handoff to them, then bridges and plays the public handoff |
| Agentic warm | agentic_warm_transfer |
A second agent (the transfer agent) talks to the transferee, then bridges or cancels |
Events#
Each transfer records items with role: "transfer" in transcript_with_tool_calls, and sends webhooks for the events listed in the agent's webhook_events:
| Event | Meaning |
|---|---|
transfer_started |
The agent called the tool. Records the destination and type |
transfer_bridged |
The caller and the destination are connected. The call ends with call_transfer |
transfer_cancelled |
The transfer failed. Records a reason. The agent stays on the call |
transfer_ended |
The bridged legs hung up |
Tried does not charge for the transferred leg. It runs on your own trunk, so your carrier bills it.
Failure reasons#
When a transfer is cancelled, the agent gets Transfer failed (<reason>). as the tool result and can tell the caller. Common reasons:
| Reason | Meaning | What to do |
|---|---|---|
caller_not_sip |
The caller is not on a phone line (for example a web call) | Transfers need a phone call. The builder's Test Audio panel notes that call transfer is not supported in web calls |
busy |
The destination returned SIP 486 or 600 | Try another destination, or tell the caller to try later |
no_answer |
480, 408 or 487, or the ring timed out | Raise transfer_ring_duration_ms (5,000 to 300,000 ms) on the transfer option |
invalid_destination |
404 | Check the number is E.164 with a country code, or the SIP URI |
declined |
603 | The destination rejected the call |
human_not_detected |
Warm transfer: no human answered within agent_detection_timeout_ms |
Raise the timeout for destinations with long queues, or set opt_out_human_detection |
failed |
Any other SIP error | Check the SIP trace below |
error: ... |
An exception in the runtime, with its message | Check the destination and the trunk |
Transfer failed: no destination. means the destination was empty: a static number that renders to nothing because of a missing dynamic variable, or an inferred destination the model could not fill.
Checklist#
The destination#
- Static destinations accept
{{dynamic_variables}}. Check the variable is set on every call that can transfer. - With an inferred destination, the model chooses the number from your prompt. Give it a clear list of numbers and when to use each.
- An
extensionon the destination is sent as DTMF after the destination answers.
The trunk#
- Transfers dial out on the number's outbound trunk, like outbound calls. If outbound calls from that number fail, transfers will too. See Debug outbound calls.
sip_referneeds your carrier or PBX to accept REFER. If it does not, usesip_invite(the default) or warm transfer, which place a new call.show_transferee_as_callerpresents the caller's number to the destination. Some carriers reject calls whose caller ID is not a number you own. Turn it off if transfers fail only when it is on.
Warm transfers#
- Destinations that answer with an IVR or a queue message can look like a machine. Use the transfer option's
ivr_optionto navigate, raiseagent_detection_timeout_ms, or setopt_out_human_detection. on_hold_musicsets what the caller hears:none,relaxing,uplifting,ringtone, or a custom asset.enable_bridge_audio_cueplays a cue when the legs connect.
Agentic warm transfers#
- The transfer agent (
transfer_agent.agent_id) must exist in the workspace. transfer_timeout_ms(10,000 to 600,000) withaction_on_timeout(bridge_transferorcancel_transfer) decides what happens if the transfer agent does not finish.
Read the SIP trace#
For phone calls, GET /v2/get-call-sip-trace/:call_id returns the SIP log lines captured for the call when the operator has set TRIED_SIP_LOG_PATH for livekit-sip. Look for the response code on the INVITE or REFER to the destination. Per-call packet capture is a deployment step and returns 404 until capture is set up.
Test without a phone#
The runtime's simulated transport records transfers (destination and whether they are warm or cold) without dialling. Use tests and simulations to check that the agent transfers at the right moment before you try it on a real line.