rich-megabyte-73517
03/20/2026, 4:11 AMtall-airline-16756
03/20/2026, 4:11 AMtall-airline-16756
03/20/2026, 4:11 AMsip_number field).
• Keep both legs inside LiveKit (warm transfer flow or WarmTransferTask) so recording continues after the transfer completes.
• Confirm your SIP trunk provider allows caller-ID override / passthrough for the sip_number you will send.
Why this works
• SIP REFER hands the call off and typically removes LiveKit from the media/recording path, so post-transfer recording is lost. Warm transfers keep LiveKit in control of both legs, so egress/recording can continue.
• When you set sip_number on the outbound INVITE, LiveKit will populate the INVITE From header with that number so the receiving phone shows the original caller’s number (if your trunk/provider allows it).
Practical steps to implement
1) Use warm transfer flow (recommended)
1. Dial the target (supervisor/third party) from LiveKit using CreateSIPParticipantRequest or the prebuilt WarmTransferTask.
2. In the request, set sip_number to the original caller’s phone number (the number you want displayed to the recipient).
3. Wait until the target answers, then merge the legs into the same/connected LiveKit room and remove hold music for the caller.
Example (pseudocode / conceptual)
create_request = api.CreateSIPParticipantRequest(
sip_trunk_id = <your_trunk>,
sip_call_to = <target_number>,
sip_number = <original_caller_number>, # <<— pass original caller ID here
room_name = <room>,
participant_identity = <target_identity>,
wait_until_answered = True,
)
2) Use LiveKit WarmTransferTask (simpler)
• Use the WarmTransferTask workflow which dials the target, plays hold to the caller, and merges calls when answered. The task preserves the call in LiveKit and supports recording after transfer when sip_number is set.
3) Ensure recording continues after the transfer
• Because both legs remain in LiveKit, enable auto-egress recording at the room/dispatch level or programmatically start composite egress (StartRoomCompositeEgress / StartTrackCompositeEgress) once the transfer completes.
• Do not use SIP REFER if you need the call to remain recordable by LiveKit after transfer.
4) Verify SIP trunk/provider requirements
• Confirm your SIP trunk allows ANI/caller-ID override or explicit setting of the From/ANI. Some carriers reject arbitrary caller IDs unless the number is verified. If your provider blocks it, caller ID will not change even if you set sip_number.
• Ensure you have an outbound trunk configured for originating the transfer leg.
5) Watch for integrations that bridge instead of transfer
• If your PBX or dialer uses bridging (B2BUA) instead of a true warm transfer, it can interfere with caller ID propagation and LiveKit control. If you use systems like Vicidial, confirm they support external SIP URIs and allow IP authentication or caller-ID passthrough.
Checklist to validate behavior
• [ ] Outbound transfer leg is created via CreateSIPParticipantRequest or WarmTransferTask.
• [ ] sip_number is set to original caller number on the outbound INVITE.
• [ ] SIP trunk accepts caller-ID override for that number.
• [ ] Warm transfer merges both legs inside LiveKit; no SIP REFER is used.
• [ ] Recording/egress is enabled or started and verified after transfer.
If you want, I can help with any of the following next steps:
• Review a sample CreateSIPParticipantRequest you’re currently using and point out exactly where to set sip_number.
• Walk through a WarmTransferTask example for your language (Python/JS).
• Suggest tests to run with your SIP trunk provider to confirm caller-ID passthrough.
Which would be most useful right now: reviewing your current request/workflow or a code example for WarmTransferTask in your language?
Sources: Preserving Caller ID During SIP Transfers in LiveKit Agents | WarmTransferTask | LiveKit Documentation | examples/voice_agents | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki | SIP Lifecycle Management Agent | LiveKit Documentation, with interactive elementsrich-megabyte-73517
03/20/2026, 4:14 AMtall-airline-16756
03/20/2026, 4:15 AMsip_number on the outbound SIP call.
Details and recommendations
• Why Twilio’s SIP REFER settings don’t affect LiveKit warm transfers
◦ LiveKit warm transfers do not rely on SIP REFER. LiveKit dials the next party using an outbound INVITE created by the LiveKit API (CreateSIPParticipantRequest) or the WarmTransferTask, keeps both legs in the LiveKit room, and then merges the calls. Because REFER is not used, Twilio’s REFER-specific settings are not in the signal path for warm transfers and therefore won’t interfere.
• The specific Twilio settings in your screenshot
◦ Call Transfer (SIP REFER) Enabled: This only controls whether Twilio will accept incoming SIP REFERs from other systems. It does not change LiveKit warm-transfer behavior. You may leave it enabled if you still want Twilio to handle cold transfers from other systems.
◦ Caller ID for Transfer Target (Set caller ID as Transferee): This controls what Twilio uses as the caller ID when it itself performs a transfer in response to a REFER. It does not affect LiveKit warm transfers. Only change this if you need Twilio-handled REFER/cold-transfer behavior to present the original caller ID.
◦ Enable PSTN Transfer: Allows REFERs to target PSTN numbers. This is about Twilio accepting REFERs to PSTN and does not impact LiveKit warm transfers.
• How to guarantee original caller ID and keep recording (recommended LiveKit approach)
a. Use warm transfers (the WarmTransferTask or manual flow) — not SIP REFER. Warm transfers keep LiveKit in the media path so recording continues.
b. When creating the outbound SIP participant, set sip_number to the original caller’s phone number. That ensures the outbound INVITE’s From header contains the original caller number so the transfer target sees the caller’s number (assuming your trunk allows it).
• Example (conceptual): set sip_number = original_from_number in CreateSIPParticipantRequest.
a. Ensure your Twilio trunk/carrier allows caller ID override/passthrough for that number. If Twilio or the upstream carrier enforces verification, the desired caller ID may be blocked even if LiveKit sends it.
• When you might want to change the Twilio UI settings
◦ If you use cold transfers via SIP REFER from other systems and you want Twilio to present the original caller number for those REFER-based transfers, change “Caller ID for Transfer Target” to the option that sets the caller ID as the transferor (original caller).
◦ If you do not use SIP REFER at all and want to reduce attack surface, you could disable Twilio’s REFER handling — but this is optional and not required for LiveKit.
Quick checklist for your setup
• [ ] Use LiveKit warm transfer (WarmTransferTask or manual warm flow).
• [ ] Set sip_number = original caller number on the outbound call created by LiveKit.
• [ ] Confirm Twilio/trunk allows caller-ID override for that number.
• [ ] Start/keep egress recording in the LiveKit room so recording continues through and after transfer.
• [ ] Leave Twilio’s SIP REFER settings unchanged unless you also need Twilio to handle cold transfers (in which case set caller-ID-for-transfer to “transferor” for REFER flows).
If you’d like, I can:
• Review the exact CreateSIPParticipantRequest payload you’re using and show where to put sip_number.
• Provide a WarmTransferTask example in your preferred language (Python/JS).
• Suggest specific tests to run with your Twilio trunk to confirm caller-ID passthrough.
Which would help most right now?
Sources: WarmTransferTask | LiveKit Documentation | Preserving Caller ID During SIP Transfers in LiveKit Agents | Agents telephony integration | LiveKit Documentation, with interactive elementsrich-megabyte-73517
03/20/2026, 4:17 AMtall-airline-16756
03/20/2026, 4:18 AMrich-megabyte-73517
03/20/2026, 4:51 AMrich-megabyte-73517
03/20/2026, 5:40 AM