Skip to main content

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.id and 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 name gemini-cli, which Gemini CLI sets itself.

Quick Start

Step 1 — Enable Gemini CLI telemetry

Add a telemetry block to ~/.gemini/settings.json (user scope) or .gemini/settings.json (project scope):
Replace the entire <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.
Do not commit API keys to version control. The otlpHeaders value contains your Fiddler API key. If you use a project-level .gemini/settings.json, add it to .gitignore. For CI/CD or shared environments, set the headers through the GEMINI_TELEMETRY_OTLP_HEADERS environment variable instead of the settings file.

Step 2 — Tag traces with your Fiddler application

Fiddler drops spans that arrive without an 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

Use Gemini CLI normally. Every interaction generates OTel traces that flow to Fiddler. For a quick smoke test, run it headless:

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:
Fiddler prefixes each span name with 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 the gen_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.
Tool spans capture tool arguments. The args object reaches Fiddler as gen_ai.tool.input and appears in the Tool Input column.For file-writing tools those arguments include the file content, and for shell tools they include the command being run. If that is sensitive, set logPrompts: false, which stops Gemini CLI emitting gen_ai.input.messages on tool spans as well as LLM spans — leaving Fiddler nothing to extract. See Only enabled: false stops content being exported for what that does and does not cover.
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 as gen_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:
  1. Navigate to your application in the Fiddler UI.
  2. Create an evaluator rule with:
    • Span type: llm
    • Text field: gen_ai.llm.input.user
    • Evaluator: Prompt Safety (or any custom evaluator)
  3. New spans are scored automatically as they arrive.
The user-prompt field, 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.
gen_ai.llm.input.user is often empty, and enrichment then scores nothing. Gemini CLI truncates telemetry content at 10,000 characters, which leaves the attribute unparseable — and because it sends the whole conversation, including file contents, longer sessions cross that limit routinely. Affected spans are scored silently as if no prompt were present. See Content capture is incomplete.
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.json and confirm enabled, traces, and target: "local" are all set.
  • Confirm your Gemini CLI version is 0.65.0 or later: gemini --version. Earlier versions ignore the otlpHeaders setting, so the requests reach Fiddler without authentication.
  • Confirm otlpEndpoint is the base Fiddler URL with a scheme and no path (Gemini CLI appends /v1/traces).
  • Confirm OTEL_RESOURCE_ATTRIBUTES includes application.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 Authorization header value includes the Bearer prefix.

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 no telemetry.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.
One collector serves one Fiddler application. The configuration below stamps every span it receives with a single application.id and forwards them with that application’s API key. Run a separate collector for each Fiddler application you send traces to.

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:
Replace the entire <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 a docker-compose.yaml:
Provide your Fiddler credentials and start the collector:
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.
Protect your API key. The collector configuration references your Fiddler API key through environment variables. Keep any .env file that contains it out of version control, and restrict who can read it.

Step 3 — Point Gemini CLI at the collector

No 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_ID and FIDDLER_API_KEY are set and the API key is valid for the application.

Known Limitations

OTLP header support requires Gemini CLI 0.65.0 or later

The telemetry.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.
If the system prompt or your tool schemas are sensitive, logPrompts: false and traces: false are not sufficient. Set enabled: false to disable telemetry. That is the only setting that prevents export, because it stops Gemini CLI initializing the OpenTelemetry SDK at all.
What the two narrower flags do control:
  • logPrompts: false omits gen_ai.input.messages and gen_ai.output.messages — the conversation, not the system prompt.
  • traces: false drops 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.