can a participan disconect and reconnect right aft...
# ask-ai
s
can a participan disconect and reconnect right after through sip?
t
Thanks for reaching out, aric. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about whether a participant can disconnect and then immediately reconnect via SIP. Short answer: Yes. A SIP participant can hang up (disconnect) and then immediately rejoin by placing a new SIP call. Each reconnect creates a new SIP + WebRTC session, so media and signaling state are reset. How you can reconnect: • Inbound: Have the participant call the phone number attached to your LiveKit SIP trunk and a dispatch rule that places them into the same room. • Outbound: Programmatically create a new SIP call with the CreateSIPParticipant API to dial the participant and join them into a room. What to expect: • Webhook events such as participant_left or room_finished may fire when the disconnect occurs. • Because reconnection creates a new session, any previous session state (tracks, ephemeral data) will not be preserved automatically. • For transient network drops, consider ICE restarts or other reconnect mechanisms for preserving session where possible; but a full SIP hangup/redial is a fresh call. If you’d like, tell me: • Are you planning to reconnect the same phone number into the same room programmatically (outbound) or by having the user call back (inbound)? • Do you need example code for CreateSIPParticipant in a specific language? I can provide a code example or step-by-step guidance based on which method you’ll use. Sources: sip | livekit/livekit_composite | DeepWiki | Server-side | livekit/livekit_composite | DeepWiki | Agents telephony integration | LiveKit Documentation | SIP Lifecycle Management Agent | LiveKit Documentation | Company directory phone assistant | LiveKit Documentation
s
The problem is that I have some calls where the sip participant joins the room and then leaves the room without any apparent reason. We see a participant_disconnect event firing and that's it
t
Thanks — I’m responding to your note that SIP participants are joining then immediately leaving, and you only see a
participant_disconnect
event. Let’s narrow this down and get you a path to a fix. Below are the most likely causes and targeted checks you can run now. After you try these, please share the results and I’ll help interpret them and suggest next steps. Likely causes and checks • STATE_MISMATCH or other server-side disconnect reason ◦ Check the disconnect reason attached to the
participant_disconnect
event (if available). If you see
STATE_MISMATCH
, that usually means the server stopped seeing the expected keep‑alives or the client disconnected uncleanly. • Network / media path failure ◦ Inspect ICE / connection state for the SIP leg. If ICE keep‑alives stop for ~20s the server may assume the media path is dead and disconnect. ◦ Look for transient packet loss, NAT timeouts, or firewall behavior that could interrupt SIP or RTP. • SIP lifecycle or API actions ◦ Verify no server-side logic is deleting the room or calling
removeParticipant()
around the same time (a room delete will produce
ROOM_DELETED
disconnects). ◦ Check any automated workflows, call-transfer logic, or SIP trunk dispatch rules that might complete or terminate the call. • SIP trunk / gateway behavior ◦ Confirm the SIP trunk or PSTN gateway isn’t sending a BYE or disconnecting due to SIP timers, auth, or codec negotiation issues. ◦ Review SIP signaling logs (INVITE/200/ACK/BYE) for unexpected call teardown. • Server-side events and resource issues ◦ Look for correlated server logs like node migrations, restarts, or resource limits that coincide with the disconnect times. • Webhooks & event timing ◦ Correlate the
participant_disconnect
webhook timestamp with SIP signaling logs and any room events (e.g.,
room_finished
, track updates). Actionable steps to gather diagnostic info 1. Capture the disconnect reason from your webhook payload for the affected events and paste it here. 2. Share timestamps (UTC) for a few recent incidents so we can correlate SIP logs and room events. 3. Provide SIP signaling logs (INVITE→BYE) or the SIP response codes around the disconnect time. 4. Check and report: ◦ Were the calls inbound (user called in) or outbound (CreateSIPParticipant)? ◦ Whether disconnects happen for specific carriers, regions, or phone numbers. ◦ Any recent changes to SIP trunk configuration, dispatch rules, or server deployment. 1. If possible, enable more verbose logging for a short window on your SIP gateway and LiveKit server and collect: ◦ Webhook payloads for participant events ◦ SIP signaling traces (call IDs) ◦ ICE / peer connection state transitions What I can do once you share the above • Help interpret the disconnect reason and correlate it with SIP signaling and room events. • Recommend specific config changes (SIP timers, ICE settings, retry logic) based on the root cause. • Provide example code for safer reconnect handling (e.g., re-dial via CreateSIPParticipant) if the disconnects are expected and you want automatic recovery. If you want to start with the easiest checks, please share the disconnect reason from one of the webhook payloads and a timestamp of the event — I’ll walk through the next diagnostic steps with you. Sources: Understanding the STATE_MISMATCH Disconnect Reason | Understanding the STATE_MISMATCH Disconnect Reason | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation | Server-side | livekit/livekit_composite | DeepWiki | server-sdk-ruby | livekit/livekit_composite | DeepWiki
s
how can I correlate a call in livekit with a call in twilio ?
t
Thanks — you’re asking how to correlate a LiveKit call with its Twilio counterpart. Below are clear, actionable ways to link the two so you can trace and troubleshoot calls reliably. Quick summary • Best approach: pass a Twilio identifier into LiveKit via a SIP header (e.g., CallSid) and map it to a participant attribute. That gives you a single ID to join LiveKit events and Twilio logs. • Fallbacks: correlate by phone number + timestamp or by SIP Call‑ID if headers aren’t available. Recommended methods 1) Pass Twilio’s CallSid into LiveKit (recommended) • In Twilio, include the call’s unique ID (CallSid) as a custom SIP header in the INVITE (for example, X-CallSid). • In LiveKit’s inbound trunk config, map that SIP header into a participant attribute (e.g., map X-CallSid → twilio.call_sid). • In LiveKit, read participant.attributes (or listen for participant_attributes_changed) to get
twilio.call_sid
. Use that value to look up the Twilio call. Why this works: • CallSid is unique per Twilio call and persists through Twilio’s logs/webhooks, so mapping it into LiveKit provides a one-to-one correlation. 2) Use SIP Call-ID • SIP sessions carry a Call‑ID header which LiveKit surfaces (e.g.,
sip.callID
on the participant). • If Twilio exposes or logs the same Call‑ID for the SIP leg, you can match on that value between systems. 3) Phone number + timestamp (fallback) • If you can’t pass headers, match LiveKit’s
sip.phoneNumber
and the call timestamp to Twilio’s call logs. • This is less robust (possible collisions) but often works when traffic is low or timestamps are precise. Practical steps to implement the header approach 1. Configure Twilio to add a SIP header with CallSid: ◦ Add
X-CallSid: {CallSid}
(naming your header consistently). 1. Configure LiveKit inbound trunk to map headers to attributes: ◦ Use
headers_to_attributes
so the header becomes, for example,
twilio.call_sid
on the participant. 1. Log or store the participant attribute at join time: ◦ Capture it from the webhook or via the participant object in your application. 1. Correlate in your dashboard/ELK/DB: ◦ Join LiveKit events (participant join/leave/webhooks) and Twilio webhooks/logs by
twilio.call_sid
. What to check if something’s not matching • Ensure Twilio actually sends the header in the INVITE (inspect SIP traces for X-CallSid). • Verify LiveKit’s header mapping is configured correctly and that participant attributes are populated. • Confirm you’re reading the attribute from the right place (participant attributes vs. other metadata). • If using Call‑ID, confirm Twilio and LiveKit show the same Call‑ID value in their logs. If you’d like, tell me: • Are your calls inbound (PSTN → Twilio → LiveKit) or outbound from LiveKit to Twilio? • Do you already have any headers being sent (e.g., X-CallSid) or do you want example TwiML/SIP configuration to add them? • I can provide a small example of the header mapping configuration and the code snippet you’d use to read the attribute in your app. Sources: How to do call transfers with Five9 | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation
s
show me the javascript createSipParticipant code to send an id for mapping
t
Thanks — I’m responding to your request for a JavaScript example that creates a SIP participant and sends a custom ID for mapping (so you can correlate the LiveKit call with Twilio). Below is a concise example using the LiveKit server SDK. It shows two ways to send an ID: • As a participant attribute/metadata (stored on the participant in LiveKit) • As a SIP header (sent in the INVITE, which Twilio or your SIP gateway can read)
Copy code
// Example: createSipParticipant.js
// Install: npm install livekit-server-sdk
const { createSipParticipant } = require('livekit-server-sdk'); // adjust import if your SDK version differs
const LIVEKIT_URL = process.env.LIVEKIT_URL;
const API_KEY = process.env.LIVEKIT_API_KEY;
const API_SECRET = process.env.LIVEKIT_API_SECRET;

async function dialWithMapping() {
  // unique external id you want to map (e.g., Twilio CallSid)
  const externalId = 'TW_CALLSID_123456';

  // Build request payload
  const req = {
    roomName: 'support-room-1',
    participantIdentity: 'sip-agent-001',
    participantName: 'Agent SIP Participant',
    sipTrunkId: 'ST_abcdef',         // your SIP trunk id
    sipCallTo: '+15551234567',       // number to dial
    waitUntilAnswered: true,
    playDialtone: true,
    krispEnabled: false,

    // 1) Participant metadata/attributes stored with the participant in LiveKit
    participantMetadata: JSON.stringify({ externalId }),

    // 2) Custom SIP headers included in the INVITE (Twilio will see these headers)
    headers: {
      'X-External-Id': externalId,
      // you can include other headers as needed
    },
  };

  // Create the SIP participant (SDK initialization pattern may vary across versions)
  const resp = await createSipParticipant(LIVEKIT_URL, API_KEY, API_SECRET, req);

  console.log('Create SIP Participant response:', resp);
}

dialWithMapping().catch(err => {
  console.error('Failed to create SIP participant:', err);
});
Notes and recommendations • Participant metadata: Use
participantMetadata
to store structured data (like CallSid) that you can read from LiveKit participant attributes or from the
participant_attributes_changed
webhook. • SIP headers: Send the external ID in a custom SIP header (e.g.,
X-External-Id
or
X-CallSid
) so Twilio can log it or include it in its traces/webhooks. Then map that header in your trunk configuration if you want it reflected in LiveKit attributes. • Pick one canonical key (e.g.,
twilio.call_sid
or
externalId
) so your logs and dashboards use a consistent field. • Verify by inspecting SIP INVITE traces to ensure the header is sent, and check the participant attributes or webhook payload when the SIP participant joins. If you tell me which server SDK version you’re using (or paste how you currently call CreateSIPParticipant), I can tailor the exact import/constructor and provide a ready-to-run snippet for that version. Sources: server-sdk-ruby | livekit/livekit_composite | DeepWiki | How to do call transfers with Five9 | LiveKit