For call transfer, what is the difference between ...
# ask-ai
l
For call transfer, what is the difference between using
sip.transfer_sip_participant()
and
sip.create_sip_participant()
?
t
Thanks for reaching out, Deepak. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
The primary difference between
sip.transfer_sip_participant()
and
sip.create_sip_participant()
in LiveKit lies in their functionality: •
create_sip_participant()
is used to create a new SIP participant, initiating a call and connecting it to a LiveKit room. It returns information about the newly created participant. •
transfer_sip_participant()
is used to transfer an existing SIP participant to a different SIP endpoint or URL. It does not create a new participant but rather relocates an existing one. Both methods are essential for managing SIP calls within LiveKit, serving different purposes in call management and transfer scenarios. Sources: protobufs/livekit_sip.proto
l
If I am using transfer_sip_participant(), will the existing SIP participants (BOT and the user) be removed from the Livekit Room?
t
Just a heads-up: when you use
transfer_sip_participant()
, it only moves the specific SIP participant to a new endpoint. The other participants, like the BOT or users, will stay in the LiveKit room. So, non-SIP participants and other SIP participants will still be there unless you remove them separately. Hope that helps clear things up!
l
For my use case, I want the AI assistant to transfer the customer to a transfer-target. The transfer-target should see the customer's number, not the AI assistant's phone no. Also if the transfer-target doesn't pick, then the AI assistant should continue talking to customer.
t
Hey there! To help you set up your AI assistant so it transfers the customer to the right person while showing the customer's number—and makes sure the assistant is still there if the transfer doesn’t go through—here’s a simple rundown: 1. Show Customer's Number: Use the
participant.identity
property to pass along the customer’s number to the transfer-target. This way, the person receiving the call sees the customer’s number instead of the AI assistant’s. 2. Transfer Logic: Use
transfer_sip_participant()
to send the customer to the right endpoint. Just make sure the
transfer_to
parameter points to the transfer-target’s SIP URL or phone number. 3. Fallback Handling: Add some error handling so if the transfer doesn’t work, the AI assistant sticks around and keeps chatting with the customer. 4. Enable SIP REFER: Double-check that SIP REFER is enabled with your SIP trunk provider to allow call transfers. For example, if you’re using Twilio, you’ll want to enable “PSTN Transfer.” If you want, I can share some detailed code examples or walk you through any of these steps—just let me know! Sources: Company directory phone assistant | LiveKit Docs | agent.py | Agents telephony integration | LiveKit Docs
l
does transfer_sip_participant() usess SIP REFER?
t
Absolutely! The
transfer_sip_participant()
function in LiveKit uses the SIP REFER method to transfer calls. You can see this clearly in both its implementation and documentation. Sources: protobufs/rpc/sip.proto | Transferring calls | LiveKit Docs | Agents telephony integration | LiveKit Docs | Transferring calls | LiveKit Docs | SIP overview | LiveKit Docs
l
what should be sent in request body of transfer_sip_participant
t
When you're putting together the request body for
transfer_sip_participant
, here are the fields you'll want to include: • Required Fields: ◦ `participant_identity`: This is the identity of the SIP participant you want to transfer. ◦ `room_name`: The name of the room where the SIP participant is currently connected. ◦ `transfer_to`: Where you want to transfer the participant. It can be a phone number (like
tel:+15105550100
) or a SIP URI (like
<sip:+15105550100@sip.telnyx>.com
). • Optional Fields: ◦ `play_dialtone`: A true or false value to decide if a dial tone should play to the participant during the transfer. ◦ `headers`: A set of headers you can add to the SIP REFER request. ◦ `ringing_timeout`: How long the system should wait for the transfer destination to pick up before timing out. Here's a quick example of what that request body might look like in JSON:
Copy code
{
  "participant_identity": "example-participant",
  "room_name": "example-room",
  "transfer_to": "tel:+15105550100",
  "play_dialtone": true,
  "headers": {
    "X-Custom-Header": "value"
  },
  "ringing_timeout": "30s"
}
Sources: rpc/sip.go | Transferring calls | LiveKit Docs
l
after successful tranfer, is the AI assistant still in room?
t
Just so you know, after you successfully use
transfer_sip_participant
to transfer someone, the AI assistant will still be hanging out in the LiveKit room. The transfer only moves the specific SIP participant you choose, so everyone else—including the AI assistant—stays right where they are.
l
after the transfer, are AI assistant and customer in separate rooms. In which room is the transfer-target?
t
When you use
transfer_sip_participant
to transfer a call, the customer gets connected to the transfer-target, which can be a phone number or a SIP endpoint. While the exact status of the AI assistant and whether it stays in the original room isn’t clearly mentioned in the sources, you can be sure that the customer is connected to the transfer-target as requested. If you have any more questions about how this works, feel free to ask! Sources: Transferring calls | LiveKit Docs
l
if the transfer-target doesn;t pick the call, how to make the AI assistant still talk to the customer
t
To make sure the AI assistant keeps chatting with the customer if the transfer-target doesn’t pick up, here are some friendly steps you can follow: 1. Error Handling: Try wrapping the
transfer_sip_participant
call in a try-except block. This way, if the transfer doesn’t go through, the assistant can gently let the customer know and keep the conversation going. 2. Resume Conversation: When a transfer doesn’t work out, guide the conversation back to the main menu or a fallback option. This gives the customer a chance to pick something else or try the transfer again. 3. Session Persistence: Make sure the AI assistant’s session stays active during and after the transfer attempt. That way, it can keep interacting with the customer if the transfer doesn’t succeed. 4. DTMF Handling: Let the customer use DTMF input to retry the transfer or choose a different option — keeping things flexible and easy for them. If you’d like, I can share some detailed code examples or walk you through these steps a bit more. Just let me know! Sources: examples/voice_agents/error_callback.py | Agents telephony integration | LiveKit Docs
l
I mean, if the transfer-target doesn;t pick the call, I want AI assistant still talk to the customer
t
If the transfer-target doesn’t pick up the call, no worries! You can make sure the AI assistant keeps chatting with the customer by adding some error handling during the transfer. Here’s a friendly way to do that: 1. Wrap the Transfer in Error Handling: Try using a try-except block when you call
transfer_sip_participant
. If the transfer doesn’t go through (like if the target doesn’t answer), catch the error and handle it smoothly. 2. Notify the Customer: Let the customer know the transfer didn’t work and offer to help them right away. For example, the assistant could say, "I’m sorry, I couldn’t transfer your call. Is there something else I can help with?" 3. Keep the Conversation Going: Make sure the AI assistant stays in the session and continues talking with the customer. You can suggest other options or even try the transfer again if that makes sense. Would you like me to share some detailed code examples or explain anything else about how to set this up?
l
Can I use create_sip_participant() and show the customer's phone number to the transfer target?
t
Absolutely! You can use
create_sip_participant()
to show the customer's phone number to the transfer target. Just set the
from_number
parameter with the customer's phone number, and that number will show up as the caller ID for the transfer target. Here’s a quick example:
Copy code
create_sip_participant(trunk_id, "tel:+1234567890", "my_room", from_number: "+1234567890")
Also, make sure the
hide_phone_number
option isn’t turned on in your dispatch rule, so the number can be seen.
l
there is no from_number
t
Hey there! If you want to show the customer's phone number to the transfer target using
create_sip_participant()
without including a
from_number
parameter, LiveKit has a neat way to help you out with attribute-to-header mapping. Here’s a quick rundown: 1. Automatic Attribute Population: When you create a SIP participant, LiveKit automatically saves the customer's phone number in the
sip.phoneNumber
attribute. 2. Configure Attribute-to-Header Mapping: Just set up your SIP trunk to map that
sip.phoneNumber
attribute to a custom SIP header, like
X-Customer-Phone
. 3. Include Headers in Transfer: Then, when you do the transfer, the mapped headers get included in the SIP REFER request—so the transfer target can see the customer’s phone number. Here’s an example of how you might configure your trunk:
Copy code
{
  "attributesToHeaders": {
    "sip.phoneNumber": "X-Customer-Phone"
  }
}
This way, the customer’s phone number shows up as a SIP header for the transfer target—pretty handy, right? Sources: rpc/sip.go | SIP participant | LiveKit Docs | livekit-protocol/src/livekit.rs | Transferring calls | LiveKit Docs
l
show the code
t
Here’s a simple example to help you configure and use
create_sip_participant()
so the customer's phone number shows up for the transfer target: 1. Create SIP Participant
Copy code
const sipClient = new SipClient('your-livekit-server', 'your-api-key', 'your-api-secret');

// Create SIP participant
const result = await sipClient.createSipParticipant(
  'your-trunk-id',
  customerPhoneNumber, // This will be stored in the sip.phoneNumber attribute
  'your-room-name',
  {
    participantIdentity: 'customer-call',
    participantAttributes: {
      'customer.name': 'John Doe',
      'customer.id': '12345'
    }
  }
);
2. Configure Attribute-to-Header Mapping
Copy code
// When creating or updating your outbound trunk
const trunk = await sipClient.createSipOutboundTrunk(
  'trunk-name',
  'sip-server-address',
  ['+1234567890'],
  {
    attributesToHeaders: {
      'sip.phoneNumber': 'X-Customer-Phone',
      'customer.name': 'X-Customer-Name',
      'customer.id': 'X-Customer-ID'
    }
  }
);
3. Transfer with Headers
Copy code
await sipClient.transferSipParticipant(
  'room-name',
  'participant-identity',
  'tel:+15105550100', // Transfer target
  {
    playDialtone: false,
    headers: {
      'X-Transfer-Reason': 'Customer Request'
    }
  }
);
This setup makes sure the customer's phone number is passed along to the transfer target as a SIP header (like
X-Customer-Phone
), so everything stays clear and connected.
l
so we are using both transferSipParticipant and createSipParticipant
t
Absolutely! In this approach, we use both
create_sip_participant()
and
transfer_sip_participant()
to make things work smoothly: • `create_sip_participant()`: This helps us create a SIP participant and set important details like the customer's phone number. These details can then be mapped to SIP headers. • `transfer_sip_participant()`: This lets us transfer the SIP participant to the right transfer target, including those mapped details (like the customer's phone number) as SIP headers in the transfer request. Putting these together makes sure the transfer target gets the customer's phone number during the transfer process—pretty neat, right?