Overview
Gemini CLI is Google’s open-source command-line AI agent. It emits OpenTelemetry traces that follow the GenAI semantic conventions, which Fiddler ingests and maps to the Fiddler schema. This gives you observability over coding agent sessions — including user prompts, LLM calls, tool invocations, token usage, and model output. No Fiddler SDK is required. Because Gemini CLI speaks GenAI semantic conventions natively, most attributes arrive with the names Fiddler expects and pass through with little translation.Gemini CLI 0.65.0 and later export to Fiddler directly.
Version 0.65.0 added the
telemetry.otlpHeaders setting, which lets Gemini CLI send the Authorization and fiddler-application-id headers that Fiddler ingestion requires.
Earlier versions have no settings-file support for OTLP headers, so they use a local OpenTelemetry Collector to inject them.
See OpenTelemetry Collector Proxy if you are pinned to a version before 0.65.0.Prerequisites
- Gemini CLI 0.65.0 or later for direct export (
npm install -g @google/gemini-cli), authenticated with an AI Studio API key, Vertex AI, or a Gemini Code Assist Standard or Enterprise license. Personal Google accounts (free, Google AI Pro, and Google AI Ultra) stopped working with Gemini CLI on June 18, 2026. Earlier Gemini CLI versions are supported through the OpenTelemetry Collector Proxy. - A Fiddler application with a valid
application.idand an API key.
Google reports that Gemini CLI has not been optimized for Gemini 4 Argon and recommends Antigravity for that model.
Gemini CLI remains supported for the models it does target, and Fiddler ingests its traces the same way regardless of the model in use.
How It Works
Gemini CLI’s OTLP exporter sends traces straight to Fiddler’s OTLP ingestion endpoint, with the Fiddler authentication headers attached. Fiddler identifies the traces as Gemini CLI’s by the OpenTelemetry instrumentation scope namegemini-cli, which Gemini CLI sets itself.
Quick Start
Step 1 — Enable Gemini CLI telemetry
Add atelemetry block to ~/.gemini/settings.json (user scope) or .gemini/settings.json (project scope):
<your-fiddler-url> value with your Fiddler instance base URL, including the scheme (for example, https://app.fiddler.ai).
Gemini CLI appends /v1/traces automatically.
Step 2 — Tag traces with your Fiddler application
application.id, and the OTLP headers do not supply one — so this step is required even though fiddler-application-id is already in otlpHeaders.
Step 3 — Run Gemini CLI
Step 4 — Verify traces in Fiddler
Navigate to your application in the Fiddler UI. Traces should appear within seconds. The smoke test above produces LLM spans only — one per model call, with token counts and latency. A prompt that answers directly invokes no tools and starts no sub-agent, so seeing only LLM spans means the integration is working. Expect more span types as you use the CLI on real work:- Tool spans when a turn invokes a tool, such as reading or writing a file
- Agent spans when a turn starts a sub-agent
A single prompt produces more than one LLM span.
Gemini CLI routes each turn through a lightweight classifier model before calling the main model, and both calls are traced — so expect at least two LLM spans per prompt, on different model names.
Gemini CLI also exports logs and metrics.
Alongside traces it sends log records to
<your-fiddler-url>/v1/logs and metrics to <your-fiddler-url>/v1/metrics, and neither can be turned off independently of telemetry as a whole.
Fiddler’s GenAI ingestion consumes traces: it does not ingest OTel metrics, and its /v1/logs path serves a separate opt-in feature that stays disabled unless Fiddler enables it for your organization.
Expect both exports to be rejected, with Gemini CLI recording the failures in its debug output.
Trace ingestion is unaffected.
To avoid the rejected requests, use the OpenTelemetry Collector Proxy, which forwards traces alone.What Gets Captured
Span Hierarchy
Each user interaction produces a trace with the following structure:gemini_cli. for a descriptive span group in the UI, matching the pattern used by the Claude Code integration.
Span Type Mapping
Gemini CLI encodes the operation type in thegen_ai.operation.name attribute (not the span name).
Fiddler maps it to a Fiddler span type:
Captured Attributes by Span Type
Agent Spans
LLM Spans
Gemini CLI sends the request
contents as a JSON array in the form [{"role": "user", "parts": [{"text": "…"}]}], and the response as a single {"role": "model", "parts": […]} object — or, when the response is streamed, as an array with one such object per chunk.
Fiddler extracts the last user message into gen_ai.llm.input.user and the model text into gen_ai.llm.output as clean text.
For a streamed response, the per-chunk objects are rejoined, so gen_ai.llm.output holds the complete reply rather than its final fragment.
See Content capture is incomplete for the cases where this yields nothing.Tool Spans
Gemini CLI serializes the tool-call request into
gen_ai.input.messages, which maps to the input semantic concept — the LLM prompt slot.
Left in place, tool arguments would populate Input while Tool Input stayed empty.
Fiddler relocates the args payload to gen_ai.tool.input, so tool arguments resolve to tool_input and no longer contribute to input.
A request that serializes past Gemini CLI’s 10,000-character telemetry cap arrives cut short and can no longer be parsed.
Because truncation is what large tool calls look like — a write_file carrying file content, a long run_shell_command — Fiddler moves the surviving prefix into gen_ai.tool.input as-is rather than leaving it in the prompt slot.
The stored value keeps Gemini CLI’s ...[TRUNCATED: original length N] marker, so a partial argument blob is recognizable as partial.
A request Fiddler cannot parse for any other reason — or one that is not shaped like a tool-call request — is left on the span untouched rather than discarded.
Evaluator rules scoped to tool spans should use
tool_input.
A rule that resolves the input semantic concept previously scored the tool-request blob on these spans as if it were a user prompt.
Whenever extraction succeeds, tool arguments no longer resolve to input, so such a rule returns nothing on those spans.
Re-scope it to tool_input to keep scoring tool arguments.Extraction failure is the exception, and it fails open rather than silently dropping the request: an unparseable or unexpectedly shaped payload keeps gen_ai.input.messages, which still resolves to input.
Such a span populates neither tool_input nor a clean prompt, so an input-mapped rule still sees the raw request there.
Truncated requests are not in this category — they are relocated to tool_input like any other, so the largest tool calls do not quietly stay behind in input.
Re-scoping to tool_input is what makes the behaviour consistent across both cases.Rules that read the gen_ai.llm.input.user attribute directly are unaffected — that extraction has always run on LLM spans only.Session Grouping
Gemini CLI assigns a session ID to each coding session and emits it asgen_ai.conversation.id.
Fiddler uses this for session-level grouping in the UI, so all spans in a session share the same conversation ID.
This lets you view the full timeline of a session and correlate LLM calls with tool invocations.
When the conversation ID is absent, Fiddler falls back to the OTel trace_id as the conversation ID.
Enrichment Setup
Fiddler can automatically score Gemini CLI user prompts using Prompt Safety (powered by the Centor Model for Safety) or other evaluators. To configure:- Navigate to your application in the Fiddler UI.
- Create an evaluator rule with:
- Span type:
llm - Text field:
gen_ai.llm.input.user - Evaluator: Prompt Safety (or any custom evaluator)
- Span type:
- New spans are scored automatically as they arrive.
gen_ai.llm.input.user, is populated only on llm spans — Fiddler extracts it from gen_ai.input.messages during LLM-span mapping.
Agent spans carry the system prompt but not the user prompt, so scope the rule to llm spans.
Enrichment also requires prompt content to be captured at all, which takes two settings rather than one.
Set both
traces: true and logPrompts: true in the Gemini CLI telemetry settings.With enabled: true alone, Gemini CLI still sends spans, but they carry no conversation: gen_ai.input.messages and gen_ai.output.messages are both absent.
Setting logPrompts: false omits the same two attributes.
In both cases they are absent rather than replaced with a placeholder, so gen_ai.llm.input.user is never populated and enrichment scores nothing.Note that neither setting is a content opt-out — the system prompt and tool definitions are exported either way. See Only enabled: false stops content being exported.
Traces still arrive and still look healthy in the UI, which makes this easy to miss.Configuration Reference
Gemini CLI Telemetry Settings
Set these in~/.gemini/settings.json under telemetry, or via the corresponding environment variables.
Resource Attributes
Fiddler routes Gemini CLI traces primarily by the OpenTelemetry instrumentation scope name
gemini-cli, with service.name=gemini-cli as a fallback.
Gemini CLI sets both itself, so routing works without extra configuration; setting service.name in OTEL_RESOURCE_ATTRIBUTES keeps it correct if another tool in your environment overrides it.Troubleshooting
These steps cover the direct-export path. For the collector path, see Troubleshooting the collector path.No traces in Fiddler
- Verify telemetry is enabled:
cat ~/.gemini/settings.jsonand confirmenabled,traces, andtarget: "local"are all set. - Confirm your Gemini CLI version is 0.65.0 or later:
gemini --version. Earlier versions ignore theotlpHeaderssetting, so the requests reach Fiddler without authentication. - Confirm
otlpEndpointis the base Fiddler URL with a scheme and no path (Gemini CLI appends/v1/traces). - Confirm
OTEL_RESOURCE_ATTRIBUTESincludesapplication.id. Fiddler drops spans that arrive without it. - Start a fresh Gemini CLI session — settings apply only to new sessions.
Authentication errors in the Gemini CLI debug output
- Verify the API key is valid for the application named in
fiddler-application-id. - Confirm the
Authorizationheader value includes theBearerprefix.
Export errors for logs or metrics
Expected. Gemini CLI exports log records and metrics alongside traces, and Fiddler’s GenAI ingestion consumes traces and rejects the other two signals. Trace ingestion is unaffected. To stop the rejected requests, use the OpenTelemetry Collector Proxy.Spans classified as unknown
Only operations in the mapping table above classify as agent, llm, or tool.
Sub-operation spans such as user_prompt, system_prompt, and schedule_tool_calls classify as unknown.
This is expected behavior.
OpenTelemetry Collector Proxy
Use a local OpenTelemetry Collector when you are pinned to Gemini CLI before 0.65.0, which has notelemetry.otlpHeaders setting, or when you want one shared proxy to hold the Fiddler credentials for several developers.
The collector receives Gemini CLI’s traces, adds the Fiddler authentication headers, and forwards traces alone.
Prerequisites for this path
- Docker to run the OpenTelemetry Collector.
Step 1 — Configure the OpenTelemetry Collector
Create a collector configuration file,otel-collector-config.yaml:
<your-fiddler-url> value with your Fiddler instance base URL, including the scheme (for example, https://app.fiddler.ai).
The collector appends /v1/traces automatically.
Setting application.id here rather than relying on each developer’s OTEL_RESOURCE_ATTRIBUTES keeps routing independent of the client environment.
Only the traces pipeline exports to Fiddler.
The logs and metrics pipelines exist so the OTLP receiver accepts those two signals and drops them.
Without those pipelines the receiver registers no handler for either signal, and Gemini CLI’s log and metric exports fail against the collector just as they would against Fiddler.
Step 2 — Start the collector
Create adocker-compose.yaml:
This configuration uses collector ports
4327 (gRPC) and 4328 (HTTP) instead of the OpenTelemetry defaults 4317/4318 to avoid conflicts with other collectors you may be running.
Use any free ports you prefer, as long as Gemini CLI points at the same gRPC port.Step 3 — Point Gemini CLI at the collector
otlpHeaders entry is needed — the collector supplies the authentication headers.
Then run Gemini CLI and verify traces in Fiddler as the Quick Start describes.
Step 2 of the Quick Start is unnecessary on this path, because the collector sets application.id itself.
Troubleshooting the collector path
- Confirm the collector is running:
docker compose ps. - Confirm the gRPC port is reachable:
nc -zv localhost 4327. - Check the collector logs for export errors:
docker compose logs -f. - Verify
FIDDLER_APP_IDandFIDDLER_API_KEYare set and the API key is valid for the application.
Known Limitations
OTLP header support requires Gemini CLI 0.65.0 or later
Thetelemetry.otlpHeaders setting was added in Gemini CLI 0.65.0.
Earlier versions offer no way to configure the Authorization and fiddler-application-id headers that Fiddler ingestion requires, so they need the OpenTelemetry Collector Proxy to inject them.
Content capture is incomplete
Prompt and response text do not always survive the trip from Gemini CLI into Fiddler.
Truncated content is dropped rather than salvaged, deliberately.
Because Gemini CLI keeps the head of the value and discards the tail, a salvaged prompt would be missing its newest turn while still reading as complete — an evaluator would then score clean against text known to be partial.
Leaving the attribute unset makes the gap visible instead.
Span type, token counts, model names, tool names, and session correlation are unaffected — only the prompt and response text.
Evaluator rules that read
gen_ai.llm.input.user score only the spans where capture succeeded.
Only enabled: false stops content being exported
Neither logPrompts nor traces suppresses the system prompt or the tool definitions.
Both are exported whenever telemetry is on at all.
Gemini CLI sets gen_ai.system_instructions and gen_ai.tool_definitions when it creates each LLM span, passing them straight through to the OpenTelemetry tracer.
logPrompts and traces are checked later, when the span ends, and they govern a different set of attributes.
Neither flag is consulted on the path that writes these two, so both survive logPrompts: false and traces: false alike.
So a span emitted with enabled: true carries at least the following, whatever the other two settings are:
Fiddler ingests the system prompt from
gen_ai.system_instructions, so it is stored and visible on the span.
What the two narrower flags do control:
logPrompts: falseomitsgen_ai.input.messagesandgen_ai.output.messages— the conversation, not the system prompt.traces: falsedrops the remaining end-of-span attributes, such as token counts, leaving the creation-time attributes above in place.
Logs and metrics are exported but not ingested
Gemini CLI exports log records and metrics alongside traces and offers no way to disable them individually. Fiddler’s GenAI ingestion consumes traces and rejects the other two signals, which does not affect trace ingestion. The collector proxy path forwards traces alone and avoids the rejected requests.Shared OTEL_RESOURCE_ATTRIBUTES
OTEL_RESOURCE_ATTRIBUTES is a shared OpenTelemetry environment variable.
If you run multiple agents (for example, Gemini CLI and Claude Code) that target different Fiddler applications, set it per session or use project-scoped settings to avoid cross-tagging traces.
Related Documentation
- Claude Code Integration — Native OTel tracing for Anthropic’s CLI coding agent
- OpenTelemetry Integration — Manual OTel instrumentation for custom frameworks
- Strands Agents SDK — Native monitoring for Strands agent applications
- Fiddler OTel SDK — Foundation package for custom OTel instrumentation