Can I access the "call" entity displayed in the li...
# ask-ai
w
Can I access the "call" entity displayed in the livekit UI from within my livekit js agent?
t
Thanks for reaching out, Oliver. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m following up on your question about accessing the "call" entity shown in the LiveKit UI from a LiveKit JavaScript agent. Short answer: The available information does not confirm a distinct UI "call" entity that is directly exposed to a LiveKit JS agent. However, agents can interact with the LiveKit primitives that represent calls: rooms, participants, tracks, and any metadata attached to those resources. To help you further, could you clarify which specific piece of the UI you mean by "call"? Please tell me: • Are you referring to a specific screen or label in the LiveKit UI (a “Calls” list, a call detail page, etc.)? If possible, paste a screenshot or the UI path. • What data or actions do you need programmatically? Examples: room ID, participant list, participant metadata, SIP call details, start/stop recording, or call-level metadata. • Are you using the LiveKit JS SDK running in a browser or a server-side agent (Node)? What I can help with next: • If you need room/participant/track data or metadata, I can show the specific LiveKit JS SDK methods to get or subscribe to those. • If you need SIP-specific call details (if you’re using SIP features), tell me which SIP fields you need and whether you’re using the SIP gateway so I can suggest the right approach. • If the UI is showing extra “call” data that’s stored outside LiveKit (e.g., in your app database), I can suggest ways to surface that data to your agent alongside LiveKit data. Reply with the UI element you mean and the data/actions you want to perform, and I’ll provide concrete code examples and steps.
w
I'm interested in SIP call details, like the sip attributes
t
Thanks — I’m responding to your follow-up asking specifically about SIP call details (the
sip
attributes) from a LiveKit JavaScript agent. Short answer: Yes. SIP participants expose SIP-specific attributes on the participant object, and you can read those attributes and listen for changes from a LiveKit JS/Node agent. What to look for • SIP participants have a participant
kind
that identifies them as SIP. • SIP metadata is available on the participant’s
attributes
object under keys like: ◦
sip.callStatus
(e.g., "dialing", "ringing", "active", "hangup") ◦
sip.phoneNumber
◦
sip.callID
◦
sip.trunkID
◦
sip.trunkPhoneNumber
Example (Node/JS agent) 1. Listen for participants joining and check
kind
. 2. Read the SIP attributes from
participant.attributes
. 3. Listen for attribute changes to track status updates.
Copy code
// pseudocode using LiveKit JS/agent-style events
room.on('participantConnected', (participant) => {
  // check if participant is a SIP participant (SDK exposes a kind field)
  if (participant.kind === 'sip' || participant.kind === 'SIP') {
    const attrs = participant.attributes || {};
    console.log('SIP attributes on connect:', {
      callStatus: attrs['sip.callStatus'],
      phoneNumber: attrs['sip.phoneNumber'],
      callID: attrs['sip.callID'],
      trunkID: attrs['sip.trunkID'],
    });
  }
});

room.on('participantAttributesChanged', (participant, updatedAttributes) => {
  if (participant.kind === 'sip' || participant.kind === 'SIP') {
    if ('sip.callStatus' in updatedAttributes) {
      console.log('SIP call status changed:', updatedAttributes['sip.callStatus']);
    }
    // handle other sip.* attribute updates similarly
  }
});
Permissions / token notes • Ensure your agent’s access token includes the necessary SIP grants so it can observe SIP participants and their attributes. If you want, I can: • Provide a concrete code sample tailored to the specific LiveKit JS SDK version you’re using (browser SDK vs Node agent). • Show how to filter existing participants for SIP kind on initial room join. • Help you handle specific SIP attribute events (for example, translate
sip.callStatus
changes into application state). Which would you prefer, and are you using the browser SDK or a server-side Node agent? Sources: livekit/livekit_composite | DeepWiki | SIP Lifecycle Management Agent | LiveKit Documentation | sip | livekit/livekit_composite | DeepWiki
w
Is it possible to retrieve these informations ealier, as part of the agent dispatch?
t
Thanks — I’m responding to your question about getting SIP attributes earlier in the flow, specifically “as part of the agent dispatch.” Short answer: You can read SIP attributes as soon as the agent can see the SIP participant in the room. If by “earlier” you mean before the participant fully joins the room on the agent side, that isn’t directly available — SIP attributes are surfaced on the participant object and via participant-attribute change events once the room state is available to the agent. That said, there are ways to get these details at or immediately after dispatch so your agent can act on them fast. A few clarifying questions so I give the right approach: • By “agent dispatch” do you mean when the agent process is being assigned a call (before it connects to the LiveKit room), or the moment the agent connects to the LiveKit room and should immediately receive call info? • Are you using a server-side Node agent or a browser-based agent? • Does your call flow use the SIP gateway/trunking (so SIP attributes are set by LiveKit), or are you also storing call metadata in your app DB? Options you can use depending on your flow • If your agent connects to the room and you want SIP info immediately: ◦ Have the agent join the room and immediately read existing participants (filter for SIP-kind) and their
participant.attributes
. This gives you SIP attributes right away on connect. ◦ Also subscribe to
participantAttributesChanged
so you catch status updates that happen after connect. • If you want the info before the agent joins the room (truly pre-dispatch): ◦ Maintain the SIP call metadata in your application (for example, store
sip.*
attributes in your call record when the call is created). Your dispatch system can query that store and include the SIP details with the dispatch message to the agent. ◦ Or, if your dispatch system can call LiveKit server-side APIs (or inspect room state on the server), it can read participant attributes from the LiveKit room before instructing the agent to connect — then pass those attributes to the agent as part of the dispatch payload. • If you need near-instant updates for call state transitions (e.g., ring → active): ◦ Combine immediate read-on-connect with attribute-change events for real-time updates. ◦ Optionally push the current state to the agent via your dispatch channel to avoid waiting for the SDK lifecycle. Practical example (fast read-on-connect) 1. Agent connects to room. 2. Immediately enumerate
room.participants
and look for
participant.kind === 'sip'
(or equivalent). 3. Read
participant.attributes['sip.callStatus']
, etc. 4. Also register
participantAttributesChanged
to catch updates. Permissions note • Ensure the agent’s access token includes SIP/room observation grants so it can see participants and attributes when it connects. If you tell me which of the three scenarios above matches your flow (pre-dispatch, immediate-on-connect, or server-side pre-read), and whether you’re using a Node agent or browser SDK, I’ll provide a concrete code sample and a recommended dispatch pattern you can implement.
w
I'm using SIP trunking. I'm interested to access the SIP attributes already when the agent receives the job to join the room
t
Thanks — you want SIP trunking call attributes available right when the agent receives the job to join the room (i.e., at dispatch time), not waiting for the agent’s SDK lifecycle. That’s a valid requirement and there are two reliable approaches you can use depending on your architecture: fetch the SIP attributes server-side before dispatch, or have the agent connect and read them immediately on join. I’ll outline both and give recommended steps and sample logic. Which approach to pick • If you need attributes before the agent even attempts to connect (so the dispatch message contains the SIP info) — use a server-side pre‑dispatch fetch from LiveKit or your call store. • If it’s acceptable for the agent to open a connection and read attributes immediately (milliseconds after connect) — have the agent join the room and read existing participant attributes on connect, then act without waiting for further events. Option A — Server-side pre-dispatch fetch (recommended if you must have data in the dispatch) • Overview: When a SIP call is created or when the SIP participant joins the room, the SIP attributes (sip.callStatus, sip.phoneNumber, sip.callID, sip.trunkID, etc.) are present on the participant object in the LiveKit room. Query that room state from a server-side component before sending the job to the agent and include the attributes in the dispatch payload. • Steps: a. From your server (with credentials that can inspect room state), fetch current room participants and their attributes. Identify the SIP participant by
kind === SIP
(or the SIP participant marker you use). b. Extract
participant.attributes['sip.callStatus']
,
['sip.phoneNumber']
,
['sip.callID']
,
['sip.trunkID']
, etc. c. Include these fields in the dispatch job you send to the agent so the agent has the SIP details immediately. • Notes: ◦ This requires a server-side method to read room state (your server must be able to access LiveKit room participants/attributes). If you store call metadata in your app DB when the call is created, you can read from there instead. ◦ This avoids waiting for the agent to connect and eliminates race conditions where the agent could join slightly before attributes are available locally. Option B — Immediate read-on-connect by the agent (if pre-dispatch fetch is not possible) • Overview: Have the agent connect to the room and immediately enumerate existing participants to find the SIP participant and read its
attributes
. Also subscribe to attribute-change events to catch rapid updates. • Steps (agent-side): a. Agent receives the job and connects to the LiveKit room. b. Immediately after connect, enumerate
room.participants
(or the SDK equivalent) and filter for SIP participant (check
participant.kind
). c. Read
participant.attributes['sip.callStatus']
,
['sip.phoneNumber']
,
['sip.callID']
,
['sip.trunkID']
. d. Register a
participantAttributesChanged
handler to catch any updates that occur after connect. • Notes: ◦ This method gives you the attributes effectively immediately after the agent connects; it’s fast but not strictly “before connect.” ◦ To minimize latency, have your agent connect as soon as dispatch is received and read attributes before presenting or routing the job internally. Practical considerations and best practices • Token permissions: Ensure the token used by whichever component reads participant attributes (server pre-read or agent) has permission/grants to observe room participants and attributes. • Race conditions: Attributes are available once the SIP participant exists in the room. If you pre-read too early (before the SIP participant has been created), you’ll not see them. If you rely on server-side reads, trigger the read after the SIP participant join or after LiveKit has set the attributes. • App-level store: To make dispatch deterministic, store SIP metadata in your application database when the SIP call is created or when LiveKit reports the call. Then the dispatcher reads from your DB and sends attributes in the job payload — this is the most robust approach for strict pre-dispatch requirements. • Real-time updates: Combine pre-dispatch data with agent-side attribute-change subscriptions for state transitions (ringing → active → hangup) that happen after dispatch. Quick pseudocode sketches • Server pre-dispatch read (conceptual)
Copy code
// server retrieves SIP participant attributes, then sends job to agent
const participants = await livekitServerApi.getRoomParticipants(roomName);
const sipParticipant = participants.find(p => p.kind === 'SIP');
const sipAttrs = sipParticipant ? sipParticipant.attributes : {};
dispatchToAgent(agentId, {
  room: roomName,
  sipAttributes: {
    callStatus: sipAttrs['sip.callStatus'],
    phoneNumber: sipAttrs['sip.phoneNumber'],
    callID: sipAttrs['sip.callID'],
    trunkID: sipAttrs['sip.trunkID'],
  }
});
• Agent immediate read-on-connect (conceptual)
Copy code
// agent connects and immediately reads SIP attributes
await agent.connectToRoom(token, roomName);
const sipParticipant = Array.from(room.participants.values()).find(p => p.kind === 'SIP');
const sipAttrs = sipParticipant ? sipParticipant.attributes : {};
// use sipAttrs right away
room.on('participantAttributesChanged', (participant, updated) => {
  if (participant.kind === 'SIP') {
    // handle updates like sip.callStatus
  }
});
Next step • Do you want a concrete code sample tailored to the exact LiveKit SDK you’re using (browser JS vs Node agent vs server-side API)? If you prefer the server pre-read pattern, tell me whether you can query room state from your server or if you keep call metadata in an app DB — I’ll provide specific code and dispatch message structure.
w
Do I need to manually delete the room if the participant disconnects, or is that done automatically?
Or if I want to end the call from the agent?
t
Thanks — you’re asking how to end a call from the agent side and whether you need to manually delete the room. Short answer • To end a call from the agent, you should delete the room programmatically. Deleting the room immediately disconnects all participants and stops any active egress (recordings). • Rooms are not guaranteed to be removed immediately when a participant leaves; LiveKit can auto-close rooms after the last non-agent leaves and a short grace period, but for deterministic, immediate teardown you should call the DeleteRoom API. What happens automatically • When the last non-agent participant leaves, LiveKit will auto-close the room after a short departure timeout (default ~20s). The room may still persist if agents or egress processes are present. • Because agents or recordings can keep the room alive, relying solely on automatic cleanup can leave orphaned rooms or extra audio in recordings. How to end the call from an agent (recommended) • Call the LiveKit room deletion API from your agent or server when you want to end the call. This: ◦ Immediately disconnects all participants. ◦ Stops any active egress/recording. ◦ Ensures prompt cleanup of room resources. Example approaches 1) Server/agent API call to delete the room (conceptual) • Node.js (RoomService client):
Copy code
await roomServiceClient.deleteRoom({ room: roomName });
• Python (API client):
Copy code
await ctx.api.room.delete_room(api.DeleteRoomRequest(room=ctx.room.name))
2) Agent-controlled cleanup flag (if using agent session helpers) • In some agent session flows you can set session options to delete the room on agent session end (check your session config if using that helper). If available, this can automate deletion when the agent session finishes. Permissions & notes • Ensure the caller of DeleteRoom has the correct API privileges (server API key or a token with appropriate room management rights). • If you need to preserve recordings after deletion, verify egress behavior in your setup (deleting the room will stop active egress). • For deterministic behavior in your app, prefer explicit DeleteRoom at call end or have your app store call-end state and drive deletion from a central controller. If you’d like, I can: • Provide a concrete code snippet tailored to the exact SDK and client you’re using (Node, browser agent, or Python). • Show the exact request shape for the RoomService/DeleteRoom call for your environment. Which language or SDK would you like the exact example in? Sources: Why is there extra audio at the end of my recordings of an agent session? |... | Server lifecycle | LiveKit Documentation | Agent session | LiveKit Documentation | Agents telephony integration | LiveKit Documentation | examples/frontdesk | livekit/livekit_composite | DeepWiki