Overview
The self-hosted LiveKit integration monitors voice agents built on the open-source LiveKit Agents framework that run against your own LiveKit server. Drop theroark-analytics[livekit] helper into your agent entrypoint and call lifecycle, transcripts, tool calls, and a recording are forwarded to Roark automatically — no other code changes required.
The SDK talks only to Roark’s own API; it never connects to your LiveKit server.
Using LiveKit Cloud? You can use this SDK there too, but the dashboard-managed webhook integration is usually simpler — see LiveKit Cloud.
Prerequisites
- A LiveKit Agents worker (Python 3.10+,
livekit-agents1.x) - Your own LiveKit server
- A Roark API key with WRITE scope (generate one)
Setup Instructions
Step 1: Install the SDK
Step 2: Configure your API key
The only setting you need to provide is your Roark API key..env
Step 3: Wire observe_session into your entrypoint
Call observe_session(...) before session.start() so the audio taps are installed before the session begins streaming frames. That single call wires up everything:
Step 4: Verify the connection
Run your worker against your LiveKit server and place a test call:- The agent appear under the LiveKit source filter
- The call appear in the calls table with status
In Progress - After the call ends — the transcript, tool invocations, and recording attached to the call
How It Works
observe_session subscribes to the standard AgentSession event surface and ships a compact event timeline to Roark:
Failures are logged and swallowed — the helper never raises into your session. Your agent keeps running even if Roark is unreachable.
What Gets Synced
- Calls — Lifecycle with timing and end reason
- Agents — Lazy-registered on first sight using the
agent_id/agent_nameyou pass - Prompts — System prompt captured at call start as a prompt revision
- Transcripts — Per-turn messages with role, content, and timestamp
- Tool Invocations — Tool call IDs, names, JSON arguments, and results
- Recordings — Audio recording of the call
Agent Management
LiveKit agents are lazy-registered the first time the helper reports them:- The first
call-startedevent with a newagent_idcreates the agent in Roark - Subsequent events update the agent’s name and prompt if they change
- These agents appear on the agents page under the LiveKit source filter
Kill Switch
Disable instrumentation at runtime without touching code. SetROARK_OBSERVABILITY_ENABLED=false to make observe_session a no-op (it returns None). Values treated as off: false, 0, no, off (case-insensitive); anything else (or the variable being absent) keeps it enabled.
Troubleshooting
Calls aren't finalizing on Roark
Calls aren't finalizing on Roark
The helper registers a shutdown callback on the
JobContext, which fires when LiveKit ends the job. If your transport tears down without firing the hook, call await state.aflush(reason="...") explicitly from your own disconnect handler — aflush() is idempotent, so the normal shutdown path will no-op if both fire.Transcripts arrive empty
Transcripts arrive empty
Transcripts come from the
conversation_item_added event on AgentSession. If you use a custom pipeline that bypasses AgentSession.start(room=…, agent=…), that event may never fire — verify by adding your own session.on("conversation_item_added", print) listener.Recording is missing one side
Recording is missing one side
The user side is tapped from
session.input.audio; the agent side from session.output.audio. Because the taps are installed by observe_session, it must be called before session.start(). Check worker logs for the tapping user audio input / tapping agent audio output lines — if one is missing, that side will be silent on the merged recording.No calls or recordings reaching Roark
No calls or recordings reaching Roark
Confirm
api_key is a WRITE-scope key and that ROARK_OBSERVABILITY_ENABLED is not set to a falsy value.Next Steps
Enable Tracing
Send OpenTelemetry traces — they auto-link to the call via the room sid
Run Simulations
Test your LiveKit agents
Configure Evaluators
Set up evaluation criteria
LiveKit Cloud
Use the dashboard-managed webhook integration instead