Skip to main content
The Gemini Live API enables low-latency, bidirectional voice interactions with Gemini models over a persistent WebSocket connection. This guide shows how to trace a Gemini Live voice agent built with the Google Agent Development Kit (ADK) to LangSmith. Gemini Live is a speech-to-speech model: it processes audio natively and exchanges a continuous stream of events with your application over a persistent WebSocket connection, rather than making discrete request/response calls. The following sections show those events and how to turn them into a LangSmith trace. For our high-level principles on getting the most out of your voice agent traces, see Voice tracing fundamentals.

The ADK Live event model

As the conversation runs, ADK streams a series of events to your application. Each event reports something that happened in the conversation: a chunk of audio, a transcript fragment, a tool call, a turn boundary, or an interruption. Every event has the same shape, and most of its fields are optional, so you determine what an event represents from which fields are populated:

How events map to LangSmith runs

To get the most out of your traces, capture each meaningful event and the data it contains in a single conversation trace, with one span per event:

Installation

Install sounddevice and numpy as well if you want to capture local audio and attach the conversation recording.

Set up your environment

The following steps demonstrate how to trace using the LangSmith SDK. You can also trace using OpenTelemetry directly. See Trace with OpenTelemetry.

Quickstart

This guide focuses on the tracing layer. It assumes you already have a working ADK Live app: the LlmAgent, Runner, and LiveRequestQueue that produce the run_live event stream, plus your microphone and speaker I/O. For a complete, runnable implementation of all of that, see the voice demo repository.

Step 1: Build the RunConfig

Transcription is opt-in. You get no transcripts unless you enable input and output transcription in the RunConfig. The finished=True transcription event carries the complete utterance, so there is no need to accumulate fragments client-side.

Step 2: Open the conversation root run

Open one run for the whole conversation and mark it as a voice trace with ls_modality="audio", following the single-trace convention. Keep this run open for the lifetime of the session and finalize it when the session ends.

Step 3: Trace each event

Define a small helper that opens a child run for one event, records its scrubbed payload, and closes it when the block exits. The scrub pass replaces raw audio bytes with a placeholder so the spans stay small:
Then loop over the events from your app’s run_live stream, skipping the audio-only chunks and spanning the rest. runner, adk_session, and queue come from your ADK Live app (see the demo agent); LiveEvent is the wrapper defined in the note below:
Skip audio-only events, the chunks of agent speech. They arrive in the thousands over a short conversation and would bury the trace, so play them to the speaker but do not span them.
A LiveEvent wrapper with helper functions is defined in the demo repository. Adapt the implementation to your own code.

Attach audio

Audio rates differ by direction: ADK Live expects 16 kHz PCM16 input and produces 24 kHz output. If your microphone capture is not 16 kHz, resample it on the send path.
To listen to a conversation alongside its transcript, attach a single combined recording of the whole conversation to the root run. Record both sides into one stereo WAV (the user’s mic on the left channel, the agent’s audio on the right) so interruptions show up as overlap between the channels. Write the user’s mic frames as you send them to ADK, and tap the speaker for the agent’s audio so audio flushed on barge-in never reaches the recording and the file reflects what the user actually heard. For the underlying attachment API, see Upload files with traces. For the cross-provider rationale, see Record a single combined audio file. Finalize the root run when the session ends. Wrap the event loop in a try/finally so the run always closes, even on error:
The demo repository wraps the full recording flow for each framework, including mic resampling, speaker-tap capture, and stereo WAV reconstruction. For Gemini Live, see the ADK agent and the shared recording helpers.

Troubleshooting

  • No transcription configs means empty-looking traces. This is the most common failure mode. Both input_audio_transcription and output_audio_transcription must be set on the RunConfig.
  • Don’t accumulate transcript fragments. Use the finished=True event’s full text; fragments are only for live UI display.
  • Don’t span audio-only events. A few minutes of conversation produces thousands of them.
  • Fields co-occur. Classify by priority, not by assuming one field per event.
  • Tools run inside ADK. Do not synthesize your own tool runs. Doing so double-counts what function_call and function_response already record.
  • Resample the mic if your capture isn’t 16 kHz (ADK input is 16 kHz, output is 24 kHz).
  • Mute ADK’s startup noise for a console UI: logging.getLogger("google_adk").setLevel(logging.ERROR) suppresses the experimental-feature warning for run_live and the MCP-not-installed line.

Next steps

Voice fundamentals

Core conventions for tracing voice agents.

Upload files with traces

Attach the conversation audio recording to your trace.