traceAI-google-genai-live
Future AGI tracing for Gemini Live sessions that your Python process opens itself with
the official SDK: client.aio.live.connect(...) on the Gemini Developer API.
One Live session is one trace. Inside it you get the setup, each user turn, each model turn
(model, tokens, transcription), each tool call, interruptions, cancellations, goAway, and
a reconnect that resumes the session with the handle this process stored. Audio sessions are
listed as calls in Future AGI's voice views.
Status: alpha. Gemini Live is a preview API.
| Tested | Version |
|---|---|
| google-genai | 2.31.0 (latest, 2026-10-14) and 2.28.0 (floor) |
| Live model | gemini-3.8-live (Gemini Developer API, real sessions on 2026-10-15) |
| Python | 3.10 - 3.13 (fi-instrumentation-otel declares <3.14) |
Install
pip install traceAI-google-genai-live "google-genai>=2.28,<3"
Use
import os
from fi_instrumentation import register
from fi_instrumentation.fi_types import ProjectType
from google import genai
from traceai_google_genai_live import instrument
trace_provider = register(project_type=ProjectType.OBSERVE, project_name="my-voice-agent")
instrument(tracer_provider=trace_provider)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
async with client.aio.live.connect(model="gemini-3.8-live",
config={"response_modalities": ["AUDIO"],
"input_audio_transcription": {},
"output_audio_transcription": {}}) as session:
... # your send_realtime_input / send_client_content / receive / send_tool_response loop
GoogleGenAILiveInstrumentor().instrument(tracer_provider=...) is the same thing.
A complete runnable example with a tool call is in examples/voice_tool.py.
Options:
| Option | Default | Effect |
|---|---|---|
config=TraceConfig(...) or the standard FI_HIDE_* environment variables |
content on | hide_inputs / FI_HIDE_INPUTS drops the input side (system instruction, user text and transcription, tool arguments); hide_outputs / FI_HIDE_OUTPUTS drops the output side (model text and transcription, tool results). *_input_messages / *_input_text (and the output pair) do the same, because all Live content is message text. Both sides off leaves metadata only: model, voice name, timings, tool names, flags, close codes and token counts. The conversation transcript and raw error text need both sides on. |
session_id, user_id |
none | Defaults for every session. fi_instrumentation.using_session(...) / using_user(...) around connect override them per call. |
resume_window_seconds |
30 |
How long a session whose connection ended after goAway, or died, waits for a reconnect with its stored handle before the root span closes. |
What you get
gemini.live.session CONVERSATION (audio) / CHAIN (text-only); parentless when CONVERSATION
├─ gemini.live.setup url.path (no host, no query), system instruction (content)
├─ gemini.live.user_turn transcription or text (content); gemini.turn_start / gemini.turn_boundary
├─ gemini.live.model_turn LLM: model, llm.token_count.*, gemini.usage.*, transcription (content)
│ └─ gemini.live.tool tool name, call id, args and result (content); cancelled / unanswered flags
├─ gemini.live.reconnect gap between the dropped connection and the resumed setup
└─ gemini.live.tool_response a response for a cancelled (ignored) or unknown (unmatched, ERROR) call id
Root attributes: gen_ai.system=google_genai, gen_ai.request.model, session.id
(+ gemini.session_id_source = customer | server | local), user.id only if you set
one, gemini.response_modalities, gemini.voice_name, gemini.tool_names,
gemini.realtime_input_count, gemini.go_away, gemini.time_left, gemini.reconnect_count.
For audio sessions the root also carries the voice-call fields: call.duration,
call.total_turns (omitted, not 0, when no turn closed), call.talk_ratio (model speech
seconds / user speech seconds; omitted unless both were measured: user speech from the
server's voiceActivity offsets, model speech from raw PCM length at the declared rate), and
conversation.transcript / fi.conversation.transcript plus flattened
conversation.transcript.{i}.message.role|content rows when content capture is on.
How server events map:
generationCompletesetsgemini.generation_completeand does not close the model turn.turnCompletecloses it.interruptedcloses it at once (gemini.interrupted=true).send_client_contentduring an open model turn closes that turn withgemini.close_reason=client_content.- A user turn opens on the server's
voiceActivityACTIVITY_START(or youractivity_start, a realtimetext=input, or the first input transcription) and closes onACTIVITY_END(gemini.turn_boundary=activity_end), falling back toturnComplete(gemini.turn_boundary=turn_complete).send_client_contentis its own user turn. toolCallopens a model turn if none is open (real sessions send the call with no model output before it, thenturnComplete+ usage for that generation), and one tool span per function call. The span closes on yoursend_tool_responsewith the same id.toolCallCancellationcloses it withgemini.cancelled=trueand no result.usageMetadatais copied onto the open model turn (latest message wins on that span, and every message is also a span event). Nothing is summed. In realgemini-3.8-livesessions each message covered one generation (its prompt count includes the context so far).- Audio frames sent with
send_realtime_inputare counted, never spanned.
Failures
| Case | Trace |
|---|---|
| Setup rejected (bad model, bad key) | One ERROR root (setup_rejected) with the setup span; the SDK's APIError reaches your code unchanged. No turns, no call.total_turns. |
Socket dies (no goAway) |
Open spans close ERROR socket_closed, gemini.close_code on the root, one flush. No reconnect by this package. |
goAway |
gemini.go_away / gemini.time_left on the root; the root stays open. |
| Reconnect with the stored handle | Same trace, one gemini.live.reconnect span. Failure: root ERROR resume_failed. |
| Reconnect with a handle this process did not store | New trace (gemini.resumed_unknown_handle=true). |
| Task cancelled | Open spans and the root close ERROR task_cancelled. |
Exception from receive() |
Recorded on the root, re-raised unchanged. |
| Export queue full | Spans are dropped by the batch processor; the socket reader is never blocked. |
Privacy
- Default: text on, audio off, as in every traceAI instrumentor. Audio bytes (
realtimeInputandmodelTurninline data) never land on a span. - Metadata only:
FI_HIDE_INPUTS=true FI_HIDE_OUTPUTS=true(orTraceConfig(hide_inputs=True, hide_outputs=True)). There is no package-specific switch. - The API key is never copied. The connection URL is recorded as its path only.
- The session resumption handle stays in memory and is never a span attribute or a log line.
- Raw error text is content: it is recorded only when both content directions are on. Stack traces are never exported.
Not supported
- Vertex AI Live (
vertexai=True): one warning, not traced. - Ephemeral tokens (
auth_tokens/...,BidiGenerateContentConstrained): one warning, not traced. - The deprecated
session.sendandsession.start_streamare not wrapped. Usesend_client_content,send_realtime_input,send_tool_responseandreceive. generate_content/generate_content_stream: usetraceAI-google-genai.- Gemini Live inside LiveKit or Pipecat: use
traceAI-livekit/traceAI-pipecat. - Node
@google/genai. - google-genai 3.x (the version check refuses it).
- No audio recording attachment, no cost in currency (the platform estimates cost from model and tokens where it has a price).
Tests
pip install -e . pytest pytest-asyncio
pytest
The tests run the real google-genai SDK against a scripted socket (tests/conftest.py).
tests/fixtures/real_20261015_*.json are server frames recorded from real
gemini-3.8-live sessions (audio replaced by silence, resumption handles replaced).
tests/_voice_tab.py is a local stand-in for the shared TH-8339 voice-tab assertion helper,
which had not merged; replace it with the shared helper when it lands.
Metadata
Release files for traceAI-google-genai-live 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| traceai_google_genai_live-0.1.0.tar.gz | 21.8 kB | Without provenance | Details for traceai_google_genai_live-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| traceai_google_genai_live-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for traceai_google_genai_live-0.1.0-py3-none-any.whl |
Total release size: 43.6 kB
Release files / traceai_google_genai_live-0.1.0.tar.gz
| Download URL | traceai_google_genai_live-0.1.0.tar.gz |
|---|---|
| Size | 21.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2628df85c76445ea65ce70cd3512f719092be3b08488c7cfd51f320d3fd43dea
|
|
BLAKE2b-256 checksum How to use checksums |
b76a667193b925e91fd8a40f3ee1190f5a56d4af486a56c0ca081b6daa1c4b6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / traceai_google_genai_live-0.1.0-py3-none-any.whl
| Download URL | traceai_google_genai_live-0.1.0-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d44d89f7a2a5ad22d7463432d8579c2879bb29ab21fb5d7724a4ae6a37ab7ce1
|
|
BLAKE2b-256 checksum How to use checksums |
20adccd58dc08da867347a6ab7cd2567589e6cac2716d350ef849a2f9021591c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for traceAI-google-genai-live 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.