what warm transfer essentially needs?
# ask-ai
c
what warm transfer essentially needs?
t
Thanks for reaching out, faiq. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
You're asking what a warm transfer needs — here’s a concise checklist of essentials and how LiveKit supports them. • Hold mechanism — put the caller on hold (disable two‑way audio) and optionally play hold music so the caller stays connected. • Private consultation room — create a separate room where the transferring agent can brief the supervisor without the caller hearing. • Dial supervisor (SIP/outbound) — reach the human agent via an outbound SIP trunk or custom SIP connection. • Context transfer (“evidence pack”) — pass conversation transcript, detected intent + confidence, extracted entities (e.g., account numbers), sentiment, and relevant customer history so the supervisor doesn’t need repeats. • Tools for the human agent — functions to join the caller (
connect_to_caller
), decline the transfer (
decline_transfer
), and handle voicemail (
voicemail_detected
). • Orchestration task — use an automated workflow (LiveKit’s
WarmTransferTask
) to sequence hold, consultation room creation, dialing, context handoff, and merging the call. • Return identity — the task should return the
human_agent_identity
after completion for logging or follow-up. Would you like a short example flow (API calls or sequence) showing these steps with LiveKit’s
WarmTransferTask
? Sources: WarmTransferTask | LiveKit Documentation | Prebuilt tasks | LiveKit Documentation | The Human-in-the-Loop (HITL) Pattern for Voice Agents | LiveKit | The Handoff Pattern for Voice Agents That Replaces IVR Menus | LiveKit, with interactive elements
c
how will we do warm transfer on Inbound calls dispatch?
t
Thanks — you’re asking how to perform a warm transfer for inbound call dispatch. Here’s a concise, actionable flow using LiveKit’s tools and what you need to configure. Acknowledgement • This covers inbound SIP calls routed by your inbound trunk/dispatch rules into LiveKit rooms, then transferring the caller to a human supervisor with full context. Requirements (setup) • Inbound trunk and dispatch rules enabled so each inbound call becomes a SIP participant in a LiveKit room. • Outbound SIP trunk configured to call supervisors. • Access to LiveKit Agents SDK (to run
WarmTransferTask
). High-level warm-transfer flow for inbound dispatch 1. Inbound call arrives → SIP participant is created and placed in a LiveKit room per your dispatch rule. 2. Agent/AI places caller on hold (disable caller audio + optional hold music). 3. Create a private consultation room and pass the caller’s
chat_ctx
(transcript, intent, entities, sentiment, history). 4. Use
WarmTransferTask
to dial the supervisor via your outbound SIP trunk and join them into the consultation room. 5. Supervisor is briefed (sees evidence pack) in the consultation room. 6. When ready, move the supervisor into the caller’s room (use
MoveParticipant
/ equivalent) and disconnect the AI/agent participants. 7.
WarmTransferTask
returns
human_agent_identity
for logging. Minimal code example (concept)
Copy code
result = await WarmTransferTask(
    sip_call_to = "+15551234567",
    sip_trunk_id = "outbound-trunk-id",
    chat_ctx = self.chat_ctx,  # passes transcript, intents, entities, etc.
)
# result contains human_agent_identity on success
Caller experience • Caller hears hold music while muted; no overlap during briefing; seamless handoff once supervisor joins. If you want, I can: • Provide a concrete code example for your language (Python/Node) or • Show how to structure the
chat_ctx
evidence pack, or • Walk through steps to configure your inbound/outbound trunks. Which would you like next? Sources: Agents telephony integration | LiveKit Documentation | The Human-in-the-Loop (HITL) Pattern for Voice Agents | LiveKit | WarmTransferTask | LiveKit Documentation | Prebuilt tasks | LiveKit Documentation | The Handoff Pattern for Voice Agents That Replaces IVR Menus | LiveKit, with interactive elements
c
what is this outbound trunk ID ? and how should I configure it??
t
Great question — I’ll explain what the outbound trunk ID is and how to configure it for warm transfers. Acknowledgement • You’re asking what the outbound trunk ID is and how to set it up so LiveKit can dial supervisors during a warm transfer. What the outbound trunk ID is • The outbound trunk ID is the unique identifier for an outbound SIP trunk you configure in LiveKit. It tells LiveKit which SIP provider/connection to use when placing outbound PSTN calls (e.g., calling a human supervisor). How to configure it (high level) 1. Choose a SIP provider (Twilio, Telnyx, Plivo, etc.) and get required details: SIP domain/host, username, password, and transport (UDP/TCP/TLS). 2. Create an outbound SIP trunk in LiveKit via the server API/SDK (
create_sip_outbound_trunk()
): ◦ Provide provider domain, credentials, transport, and any region pinning options. 1. Save the returned
sip_trunk_id
— this is the outbound trunk ID you pass to
WarmTransferTask
(or
CreateSIPParticipantRequest
). 2. Test dialing a supervisor number through that trunk to confirm connectivity and codecs. 3. Use the trunk ID in your warm transfer call: ◦ Example:
Copy code
await WarmTransferTask(
       sip_call_to = "+15551234567",
       sip_trunk_id = "your-outbound-trunk-id",
       chat_ctx = self.chat_ctx,
     )
Configuration tips • Ensure provider-side settings allow outbound calls from LiveKit (IP allowlist, credentials). • Verify SIP transport and codec compatibility (e.g., ulaw/opus). • If you need regional compliance or lower latency, enable region pinning when creating the trunk. • Keep the trunk credentials secure and rotate them per your security policy. If you want, I can: • Show the exact API call/payload to create an outbound trunk in your preferred language (Python/Node), or • Walk through testing steps for a specific SIP provider. Which would you like next? Sources: Making calls overview | LiveKit Documentation | Agents telephony integration | LiveKit Documentation | WarmTransferTask | LiveKit Documentation | LiveKit Phone Numbers | Connect voice agents to phone lines | LiveKit | Python SDKs | livekit/livekit_composite | DeepWiki, with interactive elements
c
Show the exact API call/payload to create an outbound trunk in your preferred language (Python/Node) . twilio , python
t
Below is a concise Python example showing the API call/payload to create an outbound SIP trunk in LiveKit configured to use Twilio. It uses the LiveKit server SDK style from the examples (adjust to your exact SDK/client if names differ). Notes: • Replace placeholders with your Twilio credentials and desired settings. • The response returns
sip_trunk_id
— use that in
WarmTransferTask
.
Copy code
# Example: create outbound SIP trunk (LiveKit server-side)
from livekit import LiveKitServerClient  # adjust import to your SDK
import os

LIVEKIT_URL = os.environ["LIVEKIT_URL"]
LIVEKIT_API_KEY = os.environ["LIVEKIT_API_KEY"]
LIVEKIT_API_SECRET = os.environ["LIVEKIT_API_SECRET"]

client = LiveKitServerClient(base_url=LIVEKIT_URL,
                             api_key=LIVEKIT_API_KEY,
                             api_secret=LIVEKIT_API_SECRET)

payload = {
    "name": "twilio-outbound-trunk",
    "provider": "twilio",
    "settings": {
        # Twilio SIP Domain or SIP URI (from Twilio console)
        "sip_domain": "example.sip.twilio.com",
        # Auth method: could be 'ip_access_control' or 'username_password'
        "auth_method": "username_password",
        # If using username/password auth (common for outbound)
        "username": "twilio_username",
        "password": "twilio_password",
        # Transport: 'udp', 'tcp', or 'tls'
        "transport": "udp",
        # Optional: region pinning (if supported/needed)
        "region": "us-east-1"
    },
    # Optional: default caller ID to use for outbound calls
    "default_outbound_caller_id": "+15551234567"
}

# Create the SIP outbound trunk
resp = client.create_sip_outbound_trunk(payload)  # adapt method name per SDK
# Example response contains sip_trunk_id
sip_trunk_id = resp["sip_trunk_id"]
print("Created outbound trunk id:", sip_trunk_id)
Field explanations: • `name`: Human-friendly name for the trunk. • `provider`: SIP provider identifier (use
twilio
here). • `settings.sip_domain`: The Twilio SIP Domain/SIP URI you create in Twilio. • `settings.auth_method`: Auth approach;
username_password
is common for outbound trunking. •
settings.username
/ `settings.password`: Twilio SIP username and credential for your domain. • `settings.transport`: SIP transport protocol. • `default_outbound_caller_id`: (Optional) phone number displayed when LiveKit dials out. After creation, use the returned
sip_trunk_id
in `WarmTransferTask`:
Copy code
await WarmTransferTask(
    sip_call_to = "+15559876543",
    sip_trunk_id = sip_trunk_id,
    chat_ctx = self.chat_ctx,
)
If you want, I can provide a concrete request using your LiveKit HTTP API (cURL) or adapt this to a specific LiveKit Python client package you use — which client or package are you using? , with interactive elements
c
can I use at sip trunk ID ?
t
Yes — the
sip_trunk_id
is the identifier for an outbound SIP trunk you create in LiveKit, and you can (and should) use that ID when initiating warm transfers. Key points: • The trunk ID is returned when you create an outbound SIP trunk (via the server API/SDK). • Use that
sip_trunk_id
in
WarmTransferTask
or
CreateSIPParticipantRequest
to route the outbound dial through that provider. • You can reuse the same trunk ID for multiple transfers/outbound calls (common practice) as long as the trunk’s credentials and provider settings remain valid. • If you need different behavior (different caller IDs, regions, or providers), create additional trunks and use their respective IDs. If you want, tell me the existing trunk ID you have (or the provider/caller ID requirements) and I’ll show the exact call to use it in
WarmTransferTask
. , with interactive elements
c
lk commands for outbound trunk ID
t
When you say “lk commands for outbound trunk ID,” do you mean: • How to list/get existing outbound trunk IDs with the
lk
CLI, or • How to create an outbound trunk via CLI, or • How to set the
LIVEKIT_SIP_OUTBOUND_TRUNK
env var / use the trunk ID in commands? LiveKit does not document a specific
lk
CLI command to create outbound trunks. I can: • Show how to list/get trunks (if your CLI/project supports it), or • Provide the exact HTTP/SDK (Python) request to create a Twilio outbound trunk (returns
sip_trunk_id
), or • Show how to set/use the trunk ID in
WarmTransferTask
or env var. Which of the above would you like me to provide? Sources: Agents telephony integration | LiveKit Documentation | WarmTransferTask | LiveKit Documentation | Agents (Node.js) | livekit/livekit_composite | DeepWiki | sip | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki, with interactive elements
c
yes lk cli
t
Thanks — regarding the
lk
CLI: • LiveKit does not currently provide a documented
lk
CLI command to create outbound SIP trunks. • If your CLI/project supports it, you can list or inspect existing trunks to get their IDs; however, no official
lk create-sip-outbound-trunk
command is shown in the docs. What I can do next (pick one): • Show the exact
lk
command to list/get trunks if your environment has a CLI extension that supports it (tell me your lk version), or • Provide the HTTP API cURL or the Python SDK example to create an outbound trunk (returns
sip_trunk_id
) — you previously asked for Twilio+Python, I can give the full HTTP request or SDK payload, or • Show how to set/use the
LIVEKIT_SIP_OUTBOUND_TRUNK
env var and call
WarmTransferTask
with an existing trunk ID. Which would you like? , with interactive elements
c
list command
t
You can’t list outbound SIP trunks with the
lk
CLI — there’s no documented
lk
command to list or create SIP trunks. Options to get outbound trunk IDs: • Use the Python SDK to list or create trunks (example below). • Use the HTTP API (cURL) to query trunks. • If you already created a trunk via the dashboard, copy the returned
sip_trunk_id
from that creation response. Python example to list outbound trunks (returns
sip_trunk_id
):
Copy code
from livekit import api, LiveKitAPI
import asyncio

async def list_trunks():
    lk = LiveKitAPI(url="https://your-instance.livekit.cloud",
                    api_key="YOUR_API_KEY",
                    api_secret="YOUR_API_SECRET")
    resp = await lk.sip.list_sip_outbound_trunks()  # method name may vary by SDK
    for t in resp.trunks:
        print(t.name, t.sip_trunk_id)

asyncio.run(list_trunks())
If you’d like, I can: • Provide the exact HTTP cURL for your LiveKit instance to list trunks, or • Adapt the Python snippet to the specific LiveKit Python client version you use. Which do you prefer? Sources: Python SDKs | livekit/livekit_composite | DeepWiki | WarmTransferTask | LiveKit Documentation | The Human-in-the-Loop (HITL) Pattern for Voice Agents | LiveKit | The Human-in-the-Loop (HITL) Pattern for Voice Agents | LiveKit | LiveKit Phone Numbers | Connect voice agents to phone lines | LiveKit, with interactive elements
c
so basically the agent number in order to use warm transfer , if the domain is Inbound, she have livekit Inbound trunk and also outbound trunk ? and that same ID of outbound will be act as warm transfer.
t
Short answer: yes. • Inbound trunks handle incoming calls into LiveKit; outbound trunks handle dialing out from LiveKit to PSTN. • For warm transfers you need an outbound SIP trunk (the
sip_trunk_id
) so LiveKit can call the human supervisor. The inbound trunk ID is not used to place that outbound call. • It’s common to have both: an inbound trunk to receive calls and an outbound trunk (can be the same provider or different) to perform warm transfers. • Use the outbound trunk’s
sip_trunk_id
in
WarmTransferTask
(or in
CreateSIPParticipant
) to route the supervisor call. If you want, I can show a one‑line example of
WarmTransferTask
using your outbound trunk ID. , with interactive elements
c
can we not use warm transfer without outbound trunk ID?
t
Short answer: no — you need outbound routing to dial the human supervisor. Details: • A warm transfer requires LiveKit to place an outbound SIP call to the supervisor. That outbound routing must be provided either as a saved outbound trunk (
sip_trunk_id
) or as an inline `sip_connection`/`SIPOutboundConfig` (username/password, sip_uri) in the API call. • You cannot perform a warm transfer without providing either a trunk ID or an inline SIP connection because LiveKit needs credentials/endpoint to reach the PSTN/SIP provider. If you want, I can: • Show the exact
WarmTransferTask
call using an inline
sip_connection
, or • Show the
WarmTransferTask
call using an existing
sip_trunk_id
. Which do you prefer?, with interactive elements
c
• LiveKit returned 404 Phone Number Route Not Found
t
Sorry you hit that — a 404 "Phone Number Route Not Found" means LiveKit couldn't find a routing configuration for the number or route you attempted to use. Quick checklist to diagnose and fix: • Confirm which action produced the 404 (receiving an inbound call, dialing out, or warm transfer). • Verify the phone number is provisioned and associated with an inbound route in LiveKit (dashboard or API). Inbound calls require a phone-number → route mapping. • If this happened during warm transfer, ensure you used the correct trunk/route for the outbound call (warm transfers use an outbound trunk; inbound trunk IDs do not route outbound dialing). • Check the route ID or phone-number route you passed in your request is correct and not deleted/typoed. • Inspect LiveKit logs for the incoming request and the route lookup to see which number/route was requested. If you tell me: • the exact operation you ran (API call or WarmTransferTask) and its payload (redact secrets), and • the phone number involved and whether it’s configured under Inbound Trunks / Phone Numbers in your project, I’ll point to the specific config or API field that needs correcting and give the exact request to fix it. , with interactive elements
c
warm transfer
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!
c
write me the code for warm transfer