Skip to main content

Testing your telephony setup

Place a test call and inspect the resulting room, SIP participant, and logs.

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 list or review Phone numbers to list the phone numbers you own.
    • For third-party providers, run lk sip inbound list or lk sip outbound list, or review SIP trunks and confirm there is a trunk associated with the correct phone number.
  • A dispatch rule exists (for inbound calls):

    • For LiveKit Phone Numbers, run lk number list and 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 list or review Dispatch rules for all dispatch rules. A dispatch rule must match the inbound trunk (for example, via the trunks parameter, or by omitting the parameter to match all trunks).
  • 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 through roomConfig.agents, the agent_name in 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 EndCallTool to your agent's tools.
  • Node.js or custom implementations: use the delete_room pattern shown in Hang up.
Agent names must match

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:

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:

  • CreateSIPParticipant request: the API call succeeds and returns a SIPParticipantInfo object. A Twirp error here means the request itself was rejected before any SIP traffic was sent. Verify sip_trunk_id, sip_call_to, and room_name are valid. For details, see Creating a SIP participant.
  • Outbound trunk lookup: LiveKit resolves the sip_trunk_id to an outbound trunk. Run lk sip outbound list and confirm the trunk exists, the address points to the provider's SIP endpoint (no subdomain or extra path), and the transport is correct. A 503 response often indicates a wrong address. 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's auth_username and auth_password must 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 trunks filter match all trunks.
  • Agent participant present: confirms agent dispatch. If the agent is missing, review the agent worker logs and verify that its agent_name matches an entry in roomConfig.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:

AttributeExpected value
kindEquals SIP. Any other value indicates the wrong participant is being inspected.
sip.trunkPhoneNumberFor inbound calls, the number that was dialed. For outbound calls, the caller ID presented via the trunk.
sip.phoneNumberMatches the caller's phone number (inbound) or the dialed destination (outbound). Not present if HidePhoneNumber is set on the dispatch rule.
sip.trunkIDFor 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.ruleIDMatches the dispatch rule ID (inbound only). Confirms that the expected rule matched.
sip.callID and sip.callIDFullPresent and non-empty. Use these values to cross-reference calls against provider logs.
Provider-specific attributesFor Twilio trunks, sip.twilio.callSid and sip.twilio.accountSid are populated. Use the call SID to locate the call in the Twilio Console.
Custom attributesAny 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 kind and 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.callID or sip.callIDFull to 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:

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, or transport=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) or waitUntilAnswered: 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 the TwirpError and reads metadata['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 default AgentSession (via RoomIO) automatically closes the session for that reason. If you need custom logic, register a participant_disconnected handler and inspect disconnect_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.