issues: When forwarding a call, we passing Agents’...
# ask-ai
r
issues: When forwarding a call, we passing Agents’ phone number as the caller id. In the old system (non live kit), we pass the original caller’s number in the caller id. The issue is that staff calls the customer back based on the caller id, so they’re not able to do that now. It seems that it doesn’t work well with SIP Invite and warm transfers, it creates issues, also we don’t want to use SIP REFER we want to record after the live transfer. What’s the recommandation to have it working with all of the above?
t
Thanks for reaching out, luisa. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I understand you need the original caller’s phone number to appear as the caller ID when a call is forwarded (so staff can call back the customer), while using SIP INVITE and warm transfers, and you want to avoid SIP REFER because you need recording to continue after the transfer. Below is a clear recommendation that addresses each constraint and practical steps to implement it. Short summary recommendation • Use warm transfers (not SIP REFER) and ensure the outbound SIP leg is created with the original caller’s number set as the SIP “from”/caller ID (in LiveKit this is the
sip_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)
Copy code
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 elements
r
we use twillio would any of these settings help? to swtich them or will they cause issue in the warm transfer
t
Thanks — this is a helpful screenshot and a clear question. I’ll respond to the specific Twilio settings shown and how they interact with your warm-transfer + recording requirement (no SIP REFER). Short answer up front: those Twilio SIP REFER settings will not break LiveKit warm transfers, and they are not required for the LiveKit warm-transfer flow to preserve caller ID and keep recording. The way to guarantee the original caller’s number is shown and recording continues is to use LiveKit’s warm transfer flow and set
sip_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 elements
r
check this for me: Confirm Twilio/trunk allows caller-ID override for that number.
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!
r
So what I’ve figured out is this is very easy for cold transfers where we do REFER, because it treats it as an actual forward. When we do INVITE (warm and some cold transfers) it won’t work because it’s being treated as a new call on the SIP trunk. They don’t allow this new call to have an origin that isn’t verified in twilio. Unfortunately this means for any INVITE based transfer, we can’t do it. It also complicates cold transfers, because we need the INVITE to record after the transfer leg. In summary Having recording on during the transfer leg, and having caller id passed through as original number is not possible. Having warm transfer on and the caller id passed through as original number is not possible Having cold transfer with the recording off on the transfer leg, and passing the original number as the caller id IS possible [8:14 PM]We essentially can’t get this to work with warm in our current setup, and to get it with cold + full recording we need to change recording logic
hello?