Skip to main content

Export traces

Export agent traces to any OpenTelemetry-compatible backend.

Overview

Only Available inPython

LiveKit Agents instruments each session with OpenTelemetry traces: the same spans that power Agent insights in LiveKit Cloud. Set a tracer provider to export these spans to any OpenTelemetry-compatible backend.

The following example sends spans to Langfuse , an open-source LLM observability platform. The same approach works for any backend that accepts traces over the OpenTelemetry Protocol (OTLP). To learn more, see Other backends.

Set environment variables

Create an API key pair in your Langfuse project settings, then add the following to your agent's .env.local file:

  • LANGFUSE_PUBLIC_KEY: The public key for your Langfuse project.
  • LANGFUSE_SECRET_KEY: The secret key for your Langfuse project.
  • LANGFUSE_BASE_URL: The URL for your Langfuse instance, such as https://cloud.langfuse.com (EU) or https://us.cloud.langfuse.com (United States).

The example script reads these variables to build the OTLP endpoint and authentication headers that the exporter sends to Langfuse. To export to a different backend, set those values directly instead. See Other backends.

Trace a complete agent

Call setup_langfuse before the session starts so the agent's spans route to Langfuse. Pass metadata to set attributes on every span. For example, set langfuse.session.id to the room name to group all of a session's spans together in Langfuse:

import base64
import os
from dotenv import load_dotenv
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.util.types import AttributeValue
from livekit.agents import (
Agent,
AgentServer,
AgentSession,
JobContext,
JobProcess,
cli,
inference,
)
from livekit.agents.telemetry import set_tracer_provider
from livekit.plugins import silero
from livekit.plugins.turn_detector.multilingual import MultilingualModel
load_dotenv(".env.local")
def setup_langfuse(metadata: dict[str, AttributeValue] | None = None) -> TracerProvider:
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor
public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
base_url = os.environ.get("LANGFUSE_BASE_URL")
if not public_key or not secret_key or not base_url:
raise ValueError("LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, and LANGFUSE_BASE_URL must be set")
langfuse_auth = base64.b64encode(f"{public_key}:{secret_key}".encode()).decode()
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = f"{base_url.rstrip('/')}/api/public/otel"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {langfuse_auth}"
trace_provider = TracerProvider()
trace_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
set_tracer_provider(trace_provider, metadata=metadata)
return trace_provider
class Assistant(Agent):
def __init__(self) -> None:
super().__init__(
instructions="You are a helpful voice AI assistant.",
llm=inference.LLM(model="openai/gpt-5.2-chat-latest"),
)
server = AgentServer()
def prewarm(proc: JobProcess):
proc.userdata["vad"] = silero.VAD.load()
server.setup_fnc = prewarm
@server.rtc_session(agent_name="my-agent")
async def entrypoint(ctx: JobContext):
# Route spans to Langfuse before the session starts.
trace_provider = setup_langfuse(metadata={"langfuse.session.id": ctx.room.name})
# Flush any remaining spans before the process exits.
async def flush_trace():
trace_provider.force_flush()
ctx.add_shutdown_callback(flush_trace)
session = AgentSession(
stt=inference.STT(model="deepgram/nova-3", language="multi"),
tts=inference.TTS(model="cartesia/sonic-3"),
turn_detection=MultilingualModel(),
vad=ctx.proc.userdata["vad"],
preemptive_generation=True,
)
await session.start(agent=Assistant(), room=ctx.room)
await ctx.connect()
if __name__ == "__main__":
cli.run_app(server)

For a larger example with multiple agents, fallback models, and metrics logging, see the Langfuse trace example on GitHub .

Other backends

The preceding pattern works for any backend that accepts OpenTelemetry traces over OTLP. To export elsewhere, point the exporter at the OTLP endpoint for that backend and set the authentication it requires:

  • OTEL_EXPORTER_OTLP_ENDPOINT: The OTLP HTTP endpoint for the backend.
  • OTEL_EXPORTER_OTLP_HEADERS: Any authentication headers the backend requires, such as an API key.

The rest of the agent stays the same: build a TracerProvider, add a BatchSpanProcessor with an OTLPSpanExporter, and pass it to set_tracer_provider before the session starts.

Additional resources