This integration is in beta, so its API may change.
The LiveKit integration requires
langsmith[livekit]>=0.9.7.Install
Install the integration along with the LiveKit plugins your agent uses:Set environment variables
The integration reads your LangSmith credentials from the environment and exports to LangSmith for you via OpenTelemetry:.env
Set up tracing
Importconfigure_livekit and call it once before creating your AgentServer. It builds the tracer provider, registers the LangSmith span processor, and wires it into LiveKit:
lk_openai.realtime.RealtimeModel(...)) need one extra call to capture the user’s transcript. Refer to When using LiveKit with a realtime model.
Use your own tracer provider
configure_livekit() builds a TracerProvider, registers the LangSmith span processor, and wires it into LiveKit. To use a TracerProvider you already manage, construct the processor yourself, add it to your provider, and register that provider with LiveKit’s tracer hook. LiveKit only emits spans through the provider its tracer is bound to:
Group a conversation into a thread
To group a conversation’s runs into a LangSmith thread, for thread-level views and token and cost aggregation, callset_thread_id once per conversation, inside its @server.rtc_session() handler before its spans are emitted:
When using LiveKit with a realtime model
With a speech-to-speech (realtime) model there is no separate speech-to-text step, so LiveKit transcribes the user’s audio asynchronously and delivers the transcript through the session’suser_input_transcribed event rather than on the OTel traces it emits.
instrument_session requires langsmith[livekit]>=0.10.4.instrument_session once, right after creating the AgentSession, so the SDK subscribes to that event for you and pairs each transcript with its turn. It correlates by thread id, so set that first with set_thread_id, and pass the same id:
instrument_session for realtime models. In the STT/LLM/TTS cascade the transcript is already captured (from the speech-to-text step), so calling it there would record the user’s turns a second time.
Record the conversation audio
The integration attaches the call recording to the conversation root span. How you capture that recording differs between local development and production.Development: embed a local file
In console and local development, enable LiveKit’s session recording and pointaudio_path_provider at the audio.ogg LiveKit writes under ctx.session_directory. The integration reads that file and embeds the bytes in the trace.
--record on the command line. The recording reflects what was played to the client, so a barge-in shows up truncated.
Production: record with Egress and attach the file
In production, record the room with LiveKit Egress into your own object storage, then attach the finished recording to the trace as a real audio attachment. Egress finishes uploading after the call ends, so the integration holds the conversation’s root span open until you supply the bytes:- Call
processor.expect_recording(thread_id)when you start egress. - After the call, wait for egress to complete, download the file from your storage, and call
processor.complete_recording(thread_id, audio_bytes). The integration embeds the bytes and exports the trace.
thread_id for expect_recording and complete_recording, so the recording is matched to the right conversation.
wait_for_egress polls list_egress until the status is EGRESS_COMPLETE (or subscribe to the egress_ended webhook), and download_from_storage reads the object with your cloud provider’s client. LiveKit Egress also writes to Google Cloud Storage and Azure: swap s3= for gcp=api.GCPUpload(...) or azure=api.AzureBlobUpload(...).
Always call
complete_recording because the trace’s root span is held until it runs, including on failure with data=None. If the worker stops first, the integration will flush the trace without audio.Next steps
Voice fundamentals
Core conventions for tracing voice agents.
Upload files with traces
Attach the conversation audio recording to your trace.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

