> ## Documentation Index
> Fetch the complete documentation index at: https://arize-ax.mintlify.site/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# LiveKit Agents

> Export LiveKit Agents OpenTelemetry spans to Arize AX over OTLP for voice and multimodal agent observability.

[LiveKit Agents](https://docs.livekit.io/agents/) includes built-in OpenTelemetry tracing for real-time voice and multimodal agents. Configure the LiveKit tracer provider with an OTLP exporter to send agent session, turn, speaking, and model spans to Arize AX.

<Note>
  This page uses LiveKit's native OpenTelemetry pipeline. It does not require a LiveKit-specific OpenInference instrumentor.
</Note>

## Prerequisites

* Python 3.9+
* A LiveKit Agents application
* An Arize AX account ([sign up](https://arize.com/sign-up/))
* Your Arize AX **Space ID** and **API Key**

## Launch Arize AX

1. Sign in to your [Arize AX account](https://app.arize.com/).
2. From **Space Settings**, copy your **Space ID** and **API Key**.

## Install

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
pip install livekit-agents opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
```

## Configure credentials

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="livekit-agents-tracing-example"
```

## Setup tracing

Create a shared tracer provider, attach an Arize OTLP exporter, and pass the provider to LiveKit before the session starts. LiveKit also lets you attach metadata to every span; use that for stable session or room attributes.

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# instrumentation.py
import os

from livekit.agents.telemetry import set_tracer_provider
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.util.types import AttributeValue

project_name = os.environ.get(
    "ARIZE_PROJECT_NAME",
    "livekit-agents-tracing-example",
)

tracer_provider = TracerProvider(
    resource=Resource.create(
        {
            "service.name": "livekit-agent",
            "openinference.project.name": project_name,
        }
    )
)

tracer_provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://otlp.arize.com/v1/traces",
            headers={
                "space_id": os.environ["ARIZE_SPACE_ID"],
                "api_key": os.environ["ARIZE_API_KEY"],
            },
        )
    )
)

def configure_livekit_tracing(
    metadata: dict[str, AttributeValue] | None = None,
) -> TracerProvider:
    set_tracer_provider(tracer_provider, metadata=metadata)
    return tracer_provider
```

For EU spaces, change the exporter endpoint to:

```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
https://otlp.eu-west-1a.arize.com/v1/traces
```

## Use the tracer provider in your agent

Configure tracing before the agent session starts, then flush spans during shutdown:

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# agent.py
from instrumentation import configure_livekit_tracing

from livekit.agents import Agent, AgentSession, JobContext


class Assistant(Agent):
    def __init__(self) -> None:
        super().__init__(instructions="You are a helpful voice AI assistant.")


async def entrypoint(ctx: JobContext):
    tracer_provider = configure_livekit_tracing(
        metadata={
            "session.id": ctx.room.name,
            "livekit.room.name": ctx.room.name,
        }
    )

    async def flush_trace():
        tracer_provider.force_flush()

    ctx.add_shutdown_callback(flush_trace)

    session = AgentSession()
    await session.start(agent=Assistant(), room=ctx.room)
```

## Verify in Arize

1. Run a LiveKit agent session.
2. Open your Arize AX space and select project **`livekit-agents-tracing-example`**.
3. You should see spans for the agent session and turn activity within \~30 seconds.

### Check from the skill, CLI, or SDK

Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.

<Tabs>
  <Tab title="Arize skill (agent)">
    Install the [Arize Skills](https://github.com/Arize-ai/arize-skills) plugin and let your coding agent check for you:

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    npx skills add Arize-ai/arize-skills
    ```

    Then prompt your agent:

    > Use the `arize-trace` skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.
  </Tab>

  <Tab title="AX CLI">
    Export recent spans for your project — any rows mean traces are landing:

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    ax spans export "$ARIZE_PROJECT_NAME" --space "$ARIZE_SPACE_ID" \
      --limit 5 --stdout | jq 'length'
    ```

    A non-zero count confirms spans reached Arize AX. Run `ax auth login` first if you have not authenticated. See the [`ax spans` reference](/docs/api-clients/cli/spans).
  </Tab>

  <Tab title="SDK">
    Query the project's spans and check that at least one came back.

    <CodeGroup>
      ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      import os
      from arize import ArizeClient

      client = ArizeClient(api_key=os.environ["ARIZE_API_KEY"])
      resp = client.spans.list(
          project=os.environ["ARIZE_PROJECT_NAME"],
          space=os.environ["ARIZE_SPACE_ID"],
          limit=5,
      )
      count = len(resp.spans)
      print(
          f"{count} span(s) found" if count else "No spans yet — recheck setup"
      )
      ```

      ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      // Reads ARIZE_API_KEY from the environment.
      import { listSpans } from "@arizeai/ax-client";

      const { data: spans } = await listSpans({
        project: process.env.ARIZE_PROJECT_NAME!,
        space: process.env.ARIZE_SPACE_ID!,
        limit: 5,
      });
      const count = spans.length;
      console.log(
        count ? `${count} span(s) found` : "No spans yet — recheck setup",
      );
      ```

      ```go Go theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      client, err := arize.NewClient(
          arize.Config{APIKey: os.Getenv("ARIZE_API_KEY")},
      )
      if err != nil {
          log.Fatal(err)
      }
      resp, err := client.Spans.List(ctx, spans.ListRequest{
          Project: os.Getenv("ARIZE_PROJECT_NAME"),
          Space:   os.Getenv("ARIZE_SPACE_ID"),
          Limit:   5,
      })
      if err != nil {
          log.Fatal(err)
      }
      fmt.Printf("%d span(s) found\n", len(resp.Spans))
      ```
    </CodeGroup>

    SDK span references: [Python](/docs/api-clients/python/version-8/client-resources/spans) · [TypeScript](/docs/api-clients/typescript/version-1/client-resources/spans) · [Go](/docs/api-clients/go/version-2/client-resources/spans).
  </Tab>
</Tabs>

## What Arize captures

LiveKit emits OpenTelemetry spans from its own agent runtime. Depending on your LiveKit version and plugins, those spans can include:

* agent session and turn spans
* user and agent speaking spans
* lifecycle spans for agent activity
* model or realtime-model spans and metrics
* custom metadata you attach through LiveKit telemetry setup

## Troubleshooting

* **No spans in Arize.** Confirm tracing is set before `AgentSession.start(...)` and that `force_flush()` runs before the worker exits.
* **Spans are generic.** LiveKit spans are native OpenTelemetry spans. Use OpenInference instrumentors for the LLM SDKs inside your agent if you also need rich LLM prompt, response, token, and tool metadata.
* **Project name is missing.** Make sure the tracer provider resource includes `openinference.project.name`.

## Resources

<CardGroup>
  <Card icon="book-open" href="https://docs.livekit.io/deploy/observability/tracing/" title="LiveKit export traces" horizontal />

  <Card icon="terminal" href="/docs/ax/concepts/otel-openinference/exporter" title="Arize AX OTLP exporter" horizontal />

  <Card icon="book-open" href="/docs/ax/concepts/otel-openinference/resource" title="OpenInference resource attributes" horizontal />
</CardGroup>
