Overview
After you configure your trunks, dispatch rules, and agent, place a test call to validate the setup. A successful call confirms that LiveKit and your caller or callee can reach each other, that a SIP participant is created with the expected attributes, and that your agent joins the room and responds. When a call fails, the same checks help you isolate where it broke down. The verifications in this topic apply to both inbound and outbound calls.
The exact setup you validate depends on how you provisioned your number:
- LiveKit Phone Numbers: Inbound calls only require a dispatch rule. There are no third-party SIP trunks or trunk credentials to verify, so you can skip the trunk-specific and provider-side steps below.
- Third-party SIP provider (Twilio, Telnyx, Plivo, Wavix, Exotel, and others): Inbound calls require both an inbound trunk and a dispatch rule. Outbound calls always require an outbound trunk regardless of how inbound is configured.
Pre-call checks
Before placing a test call, confirm the following prerequisites:
The phone number is provisioned and assigned:
- For LiveKit Phone Numbers, run
lk number listor review Phone numbers to list the phone numbers you own. - For third-party providers, run
lk sip inbound listorlk sip outbound list, or review SIP trunks and confirm there is a trunk associated with the correct phone number.
- For LiveKit Phone Numbers, run
A dispatch rule exists (for inbound calls):
- For LiveKit Phone Numbers, run
lk number listand verify there is an assigned dispatch rule in the SIP Dispatch Rules column for the phone number you want to test. - For third-party providers, run
lk sip dispatch listor review Dispatch rules for all dispatch rules. A dispatch rule must match the inbound trunk (for example, via thetrunksparameter, or by omitting the parameter to match all trunks).
- For LiveKit Phone Numbers, run
An agent worker is running, connected to LiveKit, and available for dispatch with the expected
agent_name. Verify the worker is up by hitting its health check endpoint, or check the Agents dashboard in LiveKit Cloud. When using explicit agent dispatch throughroomConfig.agents, theagent_namein the dispatch rule must match the name your agent worker registers with. If you don't have an agent, see Create a test agent.For third-party providers: trunk credentials match between LiveKit and the SIP provider. A mismatch returns 403 Forbidden. LiveKit Phone Numbers don't require trunk credentials.
Create a test agent
If you don't already have an agent to test with, follow the Voice AI quickstart to create a base agent. Add a way for the agent to end the call when the conversation is complete:
- Python: add the prebuilt
EndCallToolto your agent's tools. - Node.js or custom implementations: use the
delete_roompattern shown in Hang up.
For inbound calls, configure the dispatch rule to send calls to your agent, and ensure the agent_name matches in both the rule and your code. If you're using the quickstart, the default is my-agent. For details, see Dispatch to an agent.
Place a test call
Test your telephony setup with a phone call.
Test inbound calls
Dial the phone number from any phone. Your agent should answer the call. If the phone rings but the agent doesn't respond, confirm the agent is running and registered with the expected agent_name. To learn more, see Call rings, but agent doesn't answer.
After the caller and the agent are connected and in the same room, continue verifying the call with Verify the room.
If the call doesn't connect:
- LiveKit Phone Numbers: review the call logs in the LiveKit Cloud Telephony dashboard.
- Third-party SIP provider: review provider-side logs first (see Provider-side verification), then the call logs in the LiveKit Cloud Telephony dashboard.
- Review agent logs: review the agent worker logs to confirm the agent didn't encounter any errors while trying to start a session.
For additional troubleshooting, see the SIP troubleshooting guide for common issues and solutions. For deeper context, see the SIP primer for an overview of how SIP calls flow in LiveKit, and the SIP handshake guide for details on the handshake process.
Test outbound calls
Outbound calls require a third-party outbound trunk. LiveKit Phone Numbers do not currently support outbound calling.
Place an outgoing call using the CreateSIPParticipant API. The destination phone should ring. If your agent initiates the call, your agent is already in the room when the callee answers. This is the typical setup for outbound calls. To learn more, see Agent initiated outbound calls.
If you initiate the call using the server API or CLI, you must dispatch an agent to the room.
Outbound call flow
If an outbound call doesn't go through, work through the following checkpoints in order to isolate where it failed:
CreateSIPParticipantrequest: the API call succeeds and returns aSIPParticipantInfoobject. A Twirp error here means the request itself was rejected before any SIP traffic was sent. Verifysip_trunk_id,sip_call_to, androom_nameare valid. For details, see Creating a SIP participant.- Outbound trunk lookup: LiveKit resolves the
sip_trunk_idto an outbound trunk. Runlk sip outbound listand confirm the trunk exists, theaddresspoints to the provider's SIP endpoint (no subdomain or extra path), and thetransportis correct. A 503 response often indicates a wrongaddress. See 503 - Service Unavailable. For details, see SIP outbound trunk. - INVITE to the SIP provider: LiveKit sends a SIP INVITE to the trunk's
address. The trunk'sauth_usernameandauth_passwordmust match what the provider expects. A credential mismatch returns 403 Forbidden. - Provider or downstream response: if the INVITE is accepted by the provider but the call fails, inspect the final SIP response code (for example, 404, 486, 603) in provider logs.
If you can't isolate the step from API errors and participant attributes alone, download the PCAP of the call and walk the SIP handshake to find the first non-success response.
Verify the room
Each call creates a LiveKit room. Confirm the room was created with the name configured by the dispatch rule:
lk room list
For an individual dispatch rule with roomPrefix: "call-", the room name follows the pattern call-<random_suffix>. For a direct dispatch rule, the room name matches roomName exactly.
Verification criteria
- Room exists: indicates the dispatch rule matched and LiveKit attempted to create a room for the call.
- Correct room name or prefix: confirms the intended dispatch rule matched. If the name is incorrect, multiple dispatch rules might be competing. Rules without a
trunksfilter match all trunks. - Agent participant present: confirms agent dispatch. If the agent is missing, review the agent worker logs and verify that its
agent_namematches an entry inroomConfig.agents[]on the dispatch rule.
Verify the SIP participant
Every caller joins as a SIP participant with attributes that describe the call. List participants in the test room:
lk room participants list <ROOM_NAME>
Retrieve full details, including attributes, for the SIP participant:
lk room participants get --room <ROOM_NAME> <PARTICIPANT_ID>
Confirm the following attributes are set as expected:
| Attribute | Expected value |
|---|---|
kind | Equals SIP. Any other value indicates the wrong participant is being inspected. |
sip.trunkPhoneNumber | For inbound calls, the number that was dialed. For outbound calls, the caller ID presented via the trunk. |
sip.phoneNumber | Matches the caller's phone number (inbound) or the dialed destination (outbound). Not present if HidePhoneNumber is set on the dispatch rule. |
sip.trunkID | For third-party providers, matches the trunk ID created during setup. A different value indicates that another trunk matched the call. For LiveKit Phone Numbers, this references a LiveKit-managed trunk and does not need to be verified. |
sip.ruleID | Matches the dispatch rule ID (inbound only). Confirms that the expected rule matched. |
sip.callID and sip.callIDFull | Present and non-empty. Use these values to cross-reference calls against provider logs. |
| Provider-specific attributes | For Twilio trunks, sip.twilio.callSid and sip.twilio.accountSid are populated. Use the call SID to locate the call in the Twilio Console. |
| Custom attributes | Any attributes configured through the dispatch rule or headers_to_attributes appear alongside the standard SIP attributes. |
For the full list of attributes, see SIP participant.
Inspect LiveKit and agent logs
With the SIP participant in the room, the agent should log the join and begin responding. Review the following log sources:
Agent worker logs: confirm the agent received the job, connected to the room, and started publishing audio. Log the participant
kindand SIP attributes at the start of the entrypoint to verify what the agent observes. See Identifying SIP callers.You can view agent worker logs in the LiveKit Cloud Agents dashboard. To learn more about viewing runtime logs, see Log collection.
LiveKit Cloud Sessions: open the session for the test call to review participant join and leave events, published tracks, and timing.
Call ID cross-reference: use
sip.callIDorsip.callIDFullto correlate agent logs with LiveKit Cloud and the SIP provider. See Cross-referencing calls with Call IDs.
Provider-side verification
This section applies to third-party SIP providers only. If you're using LiveKit Phone Numbers, the inbound path is fully managed by LiveKit and there is no provider-side dashboard to inspect. Use the LiveKit Cloud Telephony dashboard instead.
When a call fails before reaching LiveKit, the SIP provider's logs are the primary diagnostic source. The following list includes some common locations:
- Twilio: Call logs. Use the Twilio call SID from
sip.twilio.callSidto locate the call. - Telnyx: Generate CDR reports.
- Plivo: Voice logs.
- Wavix: Call history logs.
For other providers, each offers a call detail record (CDR) or SIP debug view in its portal. Review SIP response codes and the trunk that handled the call.
Verify the following on the provider side:
The call reached the correct trunk or endpoint.
The transport on the call matches what the trunk is configured for:
transport=udp,transport=tcp, ortransport=tls(for secure trunking):- For inbound calls, the provider directs the call to the LiveKit SIP URI using the configured transport.
- For outbound calls, the provider receives the INVITE from LiveKit on the configured transport.
Check the final SIP response code on the call. A non-200 response (for example, 403 or 404) indicates a specific troubleshooting path:
- For inbound calls, this is LiveKit's response to the provider's INVITE.
- For outbound calls, this is the provider's (or downstream PSTN's) response to LiveKit's INVITE.
Test hangups and failure paths
In addition to verifying successful call connections, test hangups and failure scenarios.
- Confirm the agent handles hangups cleanly and ends the session. To learn more, see Hang up.
- Test pre-answer failure paths for outbound calls. Use
wait_until_answered=True(Python) orwaitUntilAnswered: true(Node.js) and call a number that rejects the call (USER_REJECTED) or one that doesn't answer (USER_UNAVAILABLE). Confirm your code catches theTwirpErrorand readsmetadata['sip_status_code']. See Catching call failures. - Test mid-call disconnections. After the call connects, have the caller or callee hang up. The SIP participant disconnects with
CLIENT_INITIATED, and by defaultAgentSession(viaRoomIO) automatically closes the session for that reason. If you need custom logic, register aparticipant_disconnectedhandler and inspectdisconnect_reason. See Handling mid-call disconnections.
To learn more, see Handling call outcomes.
Additional resources
The following resources provide additional details about the topics covered in this guide.