Skip to main content

Overview

LiveKit connection enables integration with agents built on LiveKit’s real-time communication platform for audio, video, and data streaming. This connection type supports both LiveKit Cloud and self-hosted LiveKit deployments.

Dispatch Modes

Whether your agent joins a Coval simulation’s room at all depends on how your LiveKit agent worker registers, not on your Coval configuration alone. LiveKit supports two dispatch modes:
  • Automatic dispatch (the default): If your worker calls WorkerOptions without an agent_name, LiveKit auto-joins it to every new room created in your project. Most simple, single-agent setups use this mode, and no extra Coval configuration is needed.
  • Explicit dispatch: If your worker’s code passes an agent_name to WorkerOptions (LiveKit’s Python/Node agents SDK), it opts out of auto-join. It will only join a room when that room’s access token embeds the same name via room_config.agents[].agent_name.
A valid token response—and even a correctly configured Sandbox ID or token endpoint—does not guarantee that an explicitly-dispatched agent will join the room. If your worker uses explicit dispatch, Coval has no way to know that unless you tell it: the simulation will connect, the token will look correct, and the room will simply sit silent until it times out.
To use explicit dispatch with Coval, set the Agent Name field (livekit_agent_name, described below) to the exact same name your worker registered under. Once that field is set, Coval automatically builds the required room_config.agents[].agent_name payload and merges it into the request sent to your generate_token_endpoint—you don’t need to hand-author it in Custom Payload Fields.
Sending room_config to your endpoint is only half the contract: your token endpoint must also read that room_config and embed it into the access token it generates—Coval has no way to do this on your behalf. See Generate Token Endpoint for the exact request shape and an example implementation using LiveKit’s server SDK.
Not sure which mode your agent uses? Check your own worker’s code for how it calls WorkerOptions:
  • If it passes an agent_name argument, your agent uses explicit dispatch—set Coval’s Agent Name field to match.
  • If it doesn’t, your agent uses automatic dispatch and will auto-join Coval’s simulation rooms with no further configuration.
See LiveKit’s docs on agent dispatch and the agent dispatch service for more detail.

Configuration Requirements

Generate Token Endpoint

  • Field: generate_token_endpoint
  • Type: String (required)
  • Purpose: Endpoint for generating LiveKit access tokens
  • Format: Valid HTTPS URL
  • Example: https://your-api.com/livekit/token
Coval sends a POST request to this endpoint with:
If you’ve configured explicit dispatch by setting Agent Name (livekit_agent_name), Coval merges a room_config key into that same request body:
Any Custom Payload Fields you’ve configured are merged in alongside room_config, room_name, and participant_name.
Receiving room_config in the request body does nothing by itself—your token endpoint must read it and embed it into the access token it mints, or the named agent will never be dispatched even though token generation otherwise succeeds. LiveKit’s server SDKs expose this via RoomConfiguration/RoomAgentDispatch constructs passed into AccessToken, e.g. in Python:
Without this step, the token still validates and the room connection still succeeds—only agent dispatch silently fails, which is exactly the “connects but no agent joins” failure mode described in Troubleshooting. See LiveKit’s agent dispatch docs for the equivalent Node.js API (RoomConfiguration, RoomAgentDispatch, and the AccessToken.roomConfig property).
Your endpoint should return:

LiveKit URL

  • Field: livekit_url
  • Type: String (required)
  • Purpose: LiveKit server WebSocket URL
  • Format: Valid WebSocket URL (wss://)
  • Example: wss://your-livekit-server.com
If your token endpoint returns serverUrl or server_url, that value will override this configuration.

Generate Token Headers

  • Field: generate_token_headers
  • Type: String (optional)
  • Purpose: HTTP headers for token generation requests
  • Format: Valid JSON string
  • Example: {"X-Coval-Simulation-Id": "{{simulation_id}}"}
Header values support {{simulation_output_id}} and its {{simulation_id}} alias, plus {{test_case.*}}, {{agent.*}}, and {{run_metadata.*}} placeholders. Coval resolves them separately for each simulation before calling the token endpoint.

Sandbox ID (Development Token Server ID)

  • Field: sandbox_id
  • Type: String (optional, testing only)
  • Purpose: Identifier for LiveKit Cloud’s hosted, dev-only token-minting API—what LiveKit’s own UI now labels the Development Token Server, formerly branded Sandbox
  • When to use: If your generate_token_endpoint points at LiveKit’s hosted Sandbox/Development Token Server API rather than a backend you run yourself
  • When to skip: If you’re already running your own token-minting backend (LiveKit’s recommended production setup), skip this field entirely
“Sandbox” and “Development Token Server” are the same LiveKit mechanism, not two different features. LiveKit deprecated the standalone Sandbox product branding and now exposes the identical hosted token-minting API as a per-project Development Token Server toggle instead. Per LiveKit’s docs, “LiveKit Sandbox is deprecated, but the token server remains available as a standalone project setting”—and their own SDK reference still calls the parameter sandboxId internally, since “API references to ‘Sandbox’ persist in SDKs due to historical naming.” If you already have a working sandbox_id, there’s nothing to migrate: it’s the same ID and the same hosted endpoint, just relabeled in LiveKit’s UI.This hosted API is fully functional today and remains a common way to get a LiveKit agent talking end-to-end during development—it is not an abandoned or removed feature. What’s genuinely deprecated is relying on it for production traffic; LiveKit still recommends it only for development and testing.How it’s actually called: the ID is sent as an X-Sandbox-ID HTTP header on requests to LiveKit’s hosted endpoint (cloud-api.livekit.io/api/v2/sandbox/connection-details)—it is not something you point a token endpoint at via the human-facing https://<id>.sandbox.livekit.io URL. That URL is a browser playground page (it returns 405/404 for direct API calls like POST / or POST /api/token), not a callable token-minting API. When Coval’s generate_token_endpoint is set to LiveKit’s hosted Sandbox/Development Token Server API, set this Sandbox ID field so Coval attaches the required X-Sandbox-ID header for you automatically.For testing and debugging your agent worker’s behavior (dispatch, joins, logs)—as opposed to token minting—LiveKit’s Agent Console remains the right tool, and it’s unrelated to this field. For production, run your own token-minting backend using LiveKit’s server SDK and point generate_token_endpoint at it—this has always been Coval’s recommended production setup, independent of Sandbox/Development Token Server history. See LiveKit’s deployment docs for more.

LiveKit Agent Name

  • Field: livekit_agent_name
  • Type: String (optional)
  • Purpose: Name identifier for the LiveKit agent
  • Format: String identifier
  • Example: "voice-assistant", "video-agent"

Custom Payload Fields

  • Field: token_request_payload
  • Type: String (optional)
  • Purpose: Additional fields to include in the token request
  • Format: Valid JSON string
  • Example: {"agent_variant": "sales", "language": "en"}
These fields are merged with room_name and participant_name when calling your token endpoint. Payload values support the same per-simulation placeholders as token request headers.

Setup Instructions

  1. Set up a token generation endpoint that accepts POST requests
  2. Configure your endpoint to return tokens with the correct room permissions
  3. Enter your LiveKit server WebSocket URL
  4. (Optional) Add authentication headers if your endpoint requires them
  5. Test the connection by launching a simulation

Sending Traces

Set Custom Headers (JSON) to {"X-Coval-Simulation-Id": "{{simulation_id}}"}. Coval replaces the placeholder before calling the token endpoint. Carry the header value into the agent’s dispatch context, then use it as X-Simulation-Id when exporting OpenTelemetry spans to Coval. See OpenTelemetry Traces for the complete tracing setup.

Technical Details

Token Generation Flow

  1. Coval generates a unique room name (UUID) for each simulation
  2. Coval sends a POST request to your token endpoint with the room name
  3. Your endpoint generates a LiveKit JWT token with room access permissions
  4. Your endpoint should also dispatch your agent to join the same room
  5. Coval joins the room using the returned token
  6. Coval waits for your agent to join (on_first_participant_joined event)
  7. Conversation simulation begins

Accepted Response Field Names

Coval accepts multiple field name variations for flexibility:

Troubleshooting

Common Issues

Token Generation Failures
  • Check endpoint accessibility and authentication
  • Verify your endpoint returns valid JSON with a token field
  • Ensure HTTPS is properly configured
WebSocket Connection Errors
  • Verify LiveKit server URL starts with wss://
  • Check that serverUrl is included in your token response
  • Confirm your LiveKit server is running and accessible
Room connects but no agent joins / simulation times out with no audio
  • You’re using explicit dispatch (your worker registered with an agent_name) but Coval’s Agent Name field is unset or doesn’t match. Set livekit_agent_name to the exact name your worker passed to WorkerOptions.
  • If Agent Name is set and matches, confirm your token endpoint actually embeds the incoming room_config into the minted token (e.g. via RoomConfiguration/RoomAgentDispatch)—see Generate Token Endpoint. Receiving room_config in the request isn’t enough; your endpoint must put it into the token itself, or dispatch will silently fail even though token generation succeeds.
  • Confirm the token response’s room name matches the room your worker actually expects to join.
  • Check your worker’s logs for a dispatch request—if it never receives one, double-check the Agent Name value for typos.
Agent Not Joining Room
  • Ensure your agent dispatch system receives the room_name from token requests
  • Verify your agent is running and connected to LiveKit
  • Check that the token grants access to the correct room
Simulation Timeouts
  • Coval waits for your agent to join before starting
  • If your agent doesn’t join, the simulation will timeout
  • Check your agent logs for connection errors
“No token found in response” Error
  • Verify your response includes a recognized token field name
  • Check that the token value is a non-empty string
  • Ensure response Content-Type is application/json

Running Components Locally

Coval’s servers need to reach your token endpoint and LiveKit server to run simulations. Here’s what needs to be publicly accessible: If running your token server locally: Use a tunneling service like ngrok to expose it:
Your agent can run on your local machine without any tunneling—it just connects outbound to the LiveKit server like any other client.