> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fiddler.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code Integration

> Integrate Claude Code with Fiddler for coding agent observability — track LLM calls, tool usage, user prompts, and session behavior via OpenTelemetry traces.

## Overview

[Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) is Anthropic's CLI coding agent. It emits OpenTelemetry traces that Fiddler natively ingests and maps to the Fiddler schema, giving you observability over coding agent sessions — including user prompts, LLM calls, tool invocations, token usage, and permission decisions.

No Fiddler SDK is required. Claude Code's built-in OTel instrumentation sends traces directly to Fiddler's OTLP ingestion endpoint.

<Warning>
  **Beta telemetry.** Claude Code's OpenTelemetry tracing requires the `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` flag and is subject to change between versions. LLM response content is **not available** in trace spans (only via log records). Tool input/output requires `OTEL_LOG_TOOL_CONTENT=1`. See [Known Limitations](#known-claude-code-upstream-limitations) for full details.
</Warning>

| Capability | Support |
| - | - |
| User prompt capture | ✅ Requires `OTEL_LOG_USER_PROMPTS=1` |
| LLM response capture | ❌ Not available in traces |
| Tool name tracking | ✅ Always available |
| Tool input/output | ✅ Requires `OTEL_LOG_TOOL_CONTENT=1` |
| Token counts | ✅ Input, output, cache read, cache creation |
| Session correlation | ✅ Via `session.id` |
| Permission decision tracking | ✅ Accept/deny on tool invocations |
| Cost tracking | ❌ Not emitted by Claude Code |
| Enrichment (Prompt Safety) | ✅ Via Fiddler evaluator rules |

***

## Prerequisites

* **Claude Code** v2.1.138 or later
* A **Fiddler application** with a valid `application.id`

***

## Quick Start

### Step 1 — Enable Claude Code telemetry

Set the following environment variables before launching Claude Code:

```bash theme={null}
# Required — enable OTel tracing (beta)
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_TRACES_EXPORTER=otlp

# Required — point at Fiddler's OTLP ingestion endpoint
export OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-fiddler-url>"
export OTEL_EXPORTER_OTLP_HEADERS="fiddler-application-id=<your-application-id>,Authorization=Bearer <your-api-key>"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"

# Required — tag traces with your Fiddler application
export OTEL_RESOURCE_ATTRIBUTES="application.id=<your-application-id>"

# Recommended — enable content capture
export OTEL_LOG_USER_PROMPTS=1
export OTEL_LOG_TOOL_DETAILS=1
export OTEL_LOG_TOOL_CONTENT=1
```

### Step 2 — Launch Claude Code

```bash theme={null}
claude
```

Use Claude Code normally. Every interaction generates OTel traces that flow to Fiddler.

### Step 3 — Verify traces in Fiddler

Navigate to your application in the Fiddler UI. You should see traces appearing within 30 seconds, with:

* **Agent spans** for each user interaction (prompt → reasoning → tool calls → response)
* **LLM spans** for each model call (Sonnet, Haiku) with token counts and latency
* **Tool spans** for each tool invocation (Bash, Read, Write, MCP tools, WebSearch)

***

## Managed Deployment via Settings File

For enterprise or managed deployments, you can configure telemetry in a Claude Code settings file instead of environment variables. Claude Code accepts telemetry settings from two settings scopes:

| Scope | File | Use it when |
| - | - | - |
| Managed | `managed-settings.json`, installed on each machine by an administrator. See the [Claude Code settings reference](https://docs.claude.com/en/docs/claude-code/settings) for its location on each operating system. | You want the same telemetry configuration on every developer machine, without each developer setting it up. |
| User | `~/.claude/settings.json` | A single developer wants telemetry for all of their own Claude Code sessions. |

<Warning>
  **Project settings files can't turn telemetry on.** Starting with Claude Code v2.1.282, Claude Code ignores telemetry variables that turn on export, set the endpoint, or capture content when they appear in a project's `.claude/settings.json` or `.claude/settings.local.json`, and shows a startup notice listing them in interactive sessions. To send telemetry from one project only, set the environment variables from the [Quick Start](#quick-start) in the shell or launcher script that starts Claude Code in that project, or pass a settings file that contains them with `claude --settings <file>`.
</Warning>

Add the following `env` block to the managed or user settings file:

```json theme={null}
{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
    "OTEL_TRACES_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://<your-fiddler-url>",
    "OTEL_EXPORTER_OTLP_HEADERS": "fiddler-application-id=<your-application-id>,Authorization=Bearer <your-api-key>",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
    "OTEL_RESOURCE_ATTRIBUTES": "application.id=<your-application-id>",
    "OTEL_LOG_USER_PROMPTS": "1",
    "OTEL_LOG_TOOL_DETAILS": "1",
    "OTEL_LOG_TOOL_CONTENT": "1"
  }
}
```

<Warning>
  **Protect your API key.** The `OTEL_EXPORTER_OTLP_HEADERS` value contains your Fiddler API key. Keep any settings file that contains it out of version control, and restrict who can read the managed settings file. For CI/CD or shared environments, prefer setting credentials via environment variables instead of a settings file.
</Warning>

<Info>
  When the same variable is set in more than one place, managed and user settings generally take precedence over shell environment variables. Project settings can override user settings with `none` for `OTEL_LOGS_EXPORTER`, `OTEL_METRICS_EXPORTER`, or `OTEL_TRACES_EXPORTER`, or an off value such as `0` for `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_CONTENT`, or `OTEL_LOG_TOOL_DETAILS`. These project off values do not override values set in the launch environment, a `--settings` file, or managed settings. Other telemetry-enabling variables, including `CLAUDE_CODE_ENABLE_TELEMETRY`, are ignored in project settings even when set to `0`. Run `/status` in a Claude Code session or `claude doctor` in your terminal to see which project telemetry variables were ignored and which turned telemetry off.
</Info>

***

## What Gets Captured

### Span Hierarchy

Each user interaction produces a trace with the following span structure:

```
claude_code.interaction (agent — root span, one per user prompt)
├── claude_code.llm_request (llm — LLM API call, e.g., Sonnet or Haiku)
├── claude_code.llm_request (llm — parallel model call, e.g., Haiku for routing)
├── claude_code.tool (tool — tool invocation wrapper)
│   ├── claude_code.tool.blocked_on_user (chain — permission prompt wait)
│   └── claude_code.tool.execution (chain — actual tool execution)
├── claude_code.tool (tool — second tool invocation)
│   └── claude_code.tool.execution (chain)
└── claude_code.llm_request (llm — follow-up LLM call with tool results)
```

### Span Type Mapping

| Claude Code Span | Fiddler Span Type | Description |
| - | - | - |
| `claude_code.interaction` | `agent` | Root span for a user interaction. Contains the user prompt and interaction-level metadata. |
| `claude_code.llm_request` | `llm` | Individual LLM API call. Contains model name, token counts, latency, and success/error status. |
| `claude_code.tool` | `tool` | Tool invocation wrapper. Contains the tool name and total duration (including permission wait). |
| `claude_code.tool.blocked_on_user` | `chain` | Time spent waiting for the user to accept or deny a tool permission prompt. Contains the user's decision. |
| `claude_code.tool.execution` | `chain` | Actual tool execution after permission is granted. Contains success status and execution duration. |

### Captured Attributes by Span Type

#### Agent Spans (`claude_code.interaction`)

| Attribute | Semantic Name | Requires Env Var | Description |
| - | - | - | - |
| `user_prompt` | `gen_ai.llm.input.user` | `OTEL_LOG_USER_PROMPTS=1` | The user's prompt text. Shows `<REDACTED>` when env var is not set. |
| `user_prompt_length` | `user_prompt_length` | No | Character count of the user prompt (always available, even when content is redacted). |
| `interaction.sequence` | `interaction.sequence` | No | Sequence number within the session (1 for first interaction, 2 for second, etc.). |
| `interaction.duration_ms` | `interaction.duration_ms` | No | Total duration of the interaction in milliseconds. |
| `session.id` | `gen_ai.conversation.id` | No | Claude Code session UUID. Used for session correlation. |

#### LLM Spans (`claude_code.llm_request`)

| Attribute | Semantic Name | Description |
| - | - | - |
| `input_tokens` | `gen_ai.usage.input_tokens` | Number of input tokens (excluding cache). |
| `output_tokens` | `gen_ai.usage.output_tokens` | Number of output tokens. |
| `cache_read_tokens` | `cache_read_tokens` | Tokens read from Anthropic's prompt cache. |
| `cache_creation_tokens` | `cache_creation_tokens` | Tokens written to Anthropic's prompt cache. |
| `model` | Passthrough | Model identifier (e.g., `claude-sonnet-4-5@20250929`). |
| `gen_ai.request.model` | Passthrough | Same as `model`, following OTel GenAI semantic conventions. |
| `gen_ai.system` | Passthrough | LLM provider (always `anthropic` for Claude Code). |
| `ttft_ms` | `ttft_ms` | Time to first token in milliseconds. |
| `stop_reason` | `stop_reason` | Why the LLM stopped: `end_turn`, `tool_use`, `max_tokens`. |
| `success` | `success` | Whether the LLM call succeeded (`true`/`false`). |
| `error` | `error` | Error message when `success` is `false`. |
| `attempt` | `attempt` | Retry attempt number (1 for first try). |
| `llm_request.context` | `llm_request.context` | Call context: `interaction` (top-level) or `tool` (nested in a tool span). |

<Info>
  **LLM response content is not available in traces.** Claude Code emits LLM output via OTel log records, not trace span attributes. This mapper processes trace spans only. See [Known Limitations](#known-claude-code-upstream-limitations).
</Info>

#### Tool Spans (`claude_code.tool`)

| Attribute | Semantic Name | Description |
| - | - | - |
| `tool_name` | `gen_ai.tool.name` | Tool identifier (e.g., `Bash`, `Read`, `Write`, `Edit`, `WebSearch`, `mcp__server__tool`). |
| `duration_ms` | `duration_ms` | Total tool duration including permission wait. |
| Tool output | `gen_ai.tool.output` | Tool output body (up to 60 KB), extracted from the `tool.output` span event. The output attribute key varies by tool (see table below). |
| Tool input | `gen_ai.tool.input` | Tool-specific input arguments (e.g., `file_path` for Read, `bash_command` for Bash), extracted from the `tool.output` span event. Serialized as JSON with native types preserved. |

The output attribute key within the `tool.output` span event varies by tool:

| Tool | Output key | Input key(s) |
| - | - | - |
| Read | `content` | `file_path`, `offset`, `limit` |
| Bash | `output` | `bash_command` |
| Edit | `diff` | `file_path` |
| Write | *(none)* | `content`, `file_path` |
| Unknown/MCP | `content` (fallback) | all other attributes |

<Info>
  **Tool input/output requires `OTEL_LOG_TOOL_CONTENT=1`.** When enabled, Claude Code emits a `tool.output` span event on tool spans. Fiddler looks up the correct output attribute key based on the tool name and extracts it into `gen_ai.tool.output`. All remaining event attributes become `gen_ai.tool.input` (JSON-serialized with native types preserved).
</Info>

#### Permission Decision Spans (`claude_code.tool.blocked_on_user`)

| Attribute | Semantic Name | Description |
| - | - | - |
| `decision` | `decision` | User's permission decision: `accept` or `deny`. |
| `source` | `source` | How the decision was made: `user_temporary`, `user_permanent`, `settings`. |
| `duration_ms` | `duration_ms` | Time spent waiting for the user to respond. |

***

## Session Grouping

Claude Code assigns a `session.id` to each coding session. Fiddler maps this to `gen_ai.conversation.id`, enabling session-level grouping in the UI. All spans within a session share the same `session.id`, allowing you to:

* View the full timeline of a coding session
* Correlate LLM calls with tool invocations
* Track interaction sequences within a session

When `session.id` is absent (rare), Fiddler falls back to using the OTel `trace_id` as the conversation ID.

***

## Enrichment Setup

Fiddler can automatically score Claude Code 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:** `agent`
   * **Text field:** `user_prompt`
   * **Evaluator:** Prompt Safety (or any custom evaluator)
3. New `claude_code.interaction` spans will be scored automatically as they arrive.

<Info>
  Enrichment requires the `user_prompt` attribute to be populated. Set `OTEL_LOG_USER_PROMPTS=1` to enable content capture. When disabled, `user_prompt` contains `<REDACTED>` and enrichment will score the redaction placeholder instead of the actual prompt.
</Info>

***

## Configuration Reference

### Environment Variables

#### Required

| Variable | Description |
| - | - |
| `CLAUDE_CODE_ENABLE_TELEMETRY` | Set to `1` to enable telemetry. |
| `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` | Set to `1` to enable OTel trace export (beta). |
| `OTEL_TRACES_EXPORTER` | Set to `otlp` to enable OTLP trace export. |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Fiddler's OTLP ingestion endpoint base URL (e.g., `https://your-fiddler-instance.com`). The OTel SDK appends `/v1/traces` automatically. |
| `OTEL_EXPORTER_OTLP_HEADERS` | Must include `fiddler-application-id=<uuid>` and `Authorization=Bearer <api-key>`. |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | Set to `http/protobuf`. |
| `OTEL_RESOURCE_ATTRIBUTES` | Must include `application.id=<uuid>` matching the header above. |

#### Content Logging

| Variable | Default | Description |
| - | - | - |
| `OTEL_LOG_USER_PROMPTS` | `0` | Set to `1` to include user prompt text in traces. When disabled, `user_prompt` shows `<REDACTED>`. |
| `OTEL_LOG_TOOL_DETAILS` | `0` | Set to `1` to include additional tool metadata (`file_path` for Read/Edit/Write, `full_command` for Bash). |
| `OTEL_LOG_TOOL_CONTENT` | `0` | Set to `1` to include tool input/output content via `tool.output` span events. |

#### Optional

| Variable | Default | Description |
| - | - | - |
| `OTEL_SERVICE_NAME` | `claude-code` | Override the service name. Must remain `claude-code` for Fiddler to detect and map the traces correctly. |

***

## Troubleshooting

### Traces not appearing in Fiddler

1. Verify telemetry is enabled:
   ```bash theme={null}
   echo $CLAUDE_CODE_ENABLE_TELEMETRY        # should be 1
   echo $CLAUDE_CODE_ENHANCED_TELEMETRY_BETA  # should be 1
   echo $OTEL_TRACES_EXPORTER                 # should be otlp
   ```

2. Verify the OTLP endpoint, protocol, and headers are set:
   ```bash theme={null}
   echo $OTEL_EXPORTER_OTLP_ENDPOINT    # should be the base URL (no /v1/traces)
   echo $OTEL_EXPORTER_OTLP_PROTOCOL    # should be http/protobuf
   echo $OTEL_EXPORTER_OTLP_HEADERS     # should contain fiddler-application-id
   echo $OTEL_RESOURCE_ATTRIBUTES       # should contain application.id
   ```

3. Verify `application.id` in `OTEL_RESOURCE_ATTRIBUTES` is a valid UUID for an existing Fiddler application. Spans with an invalid or missing `application.id` are dropped during ingestion.

4. Verify the endpoint URL is the base URL (the SDK appends `/v1/traces` automatically) and `OTEL_EXPORTER_OTLP_PROTOCOL` is set to `http/protobuf`.

5. If you configured telemetry in a settings file, the `echo` checks above show only your shell's values. Run `/status` in a Claude Code session instead to see which telemetry variables Claude Code ignored.

### Startup notice about telemetry in project settings

If Claude Code starts with the notice "This project's settings set telemetry environment variables", a project's `.claude/settings.json` or `.claude/settings.local.json` contains telemetry variables. Starting with v2.1.282, Claude Code ignores the ones that turn on export, set the endpoint, or capture content, so traces stop reaching Fiddler. Move those variables to your user settings file, a managed settings file, or the shell environment, as described in [Managed Deployment via Settings File](#managed-deployment-via-settings-file).

Non-interactive runs with `claude -p` and Agent SDK sessions don't show this notice. If you run Claude Code in CI or another automated job, check that traces still reach Fiddler after you upgrade, and set the telemetry variables in the job's environment or a `--settings` file.

### User prompts showing as `<REDACTED>`

Set `OTEL_LOG_USER_PROMPTS=1` in the environment before launching Claude Code. This is disabled by default for privacy.

### Tool details missing from spans

Tool spans only include `tool_name` and `duration_ms` by default. Setting `OTEL_LOG_TOOL_DETAILS=1` adds `file_path` (for Read/Edit/Write tools) and `full_command` (for Bash tools) as span attributes. Setting `OTEL_LOG_TOOL_CONTENT=1` enables `tool.output` span events with full tool input/output content.

### Enrichment worker skipping spans

If you see warnings like `Missing gen_ai.agent.name in span.attributes`, the Fiddler mapper automatically sets this to `"claude-code"` on all spans. Ensure you are running the latest version of the external OTel consumer that includes the Claude Code mapper.

### Spans classified as `chain` instead of expected types

Only three span types have specific classifications: `claude_code.interaction` (agent), `claude_code.llm_request` (llm), and `claude_code.tool` (tool). All other spans — including `tool.blocked_on_user` and `tool.execution` — are classified as `chain`. This is expected behavior.

***

## Known Claude Code Upstream Limitations

Claude Code's OpenTelemetry tracing is currently in **beta** and has several limitations that affect what data is available in Fiddler. These are not Fiddler issues — they are limitations of Claude Code's OTel instrumentation. Fiddler captures and maps every attribute that Claude Code emits.

### LLM response content not available in traces

Claude Code does not emit LLM response text as a trace span attribute. Response content is only available via OTel **log records** (controlled by `OTEL_LOGS_EXPORTER` and `OTEL_LOG_RAW_API_BODIES`), not trace spans. OTel log records now include `trace_id` and `span_id` (resolved upstream), enabling log-to-trace correlation.

**Impact:** Session views in Fiddler show user prompts (input) but not Claude's responses (output). Evaluators that require both input and output (e.g., response faithfulness) cannot run on Claude Code traces. Log-to-trace correlation is now possible upstream but not yet implemented in Fiddler's mapper. To capture response content today, use the [Fiddler Claude Code Plugin](/integrations/agentic-ai/fiddler-claude-code-plugin), which records the LLM response on each turn's trace and groups them into the same Fiddler session as these native traces.

### Tool input/output now available via span events

Claude Code emits `tool.output` span events on tool spans when `OTEL_LOG_TOOL_CONTENT=1` is set. The output attribute key varies by tool (`content` for Read, `output` for Bash, `diff` for Edit; Write has no output). Fiddler uses a per-tool lookup to extract the correct attribute into `gen_ai.tool.output`, with remaining event attributes (e.g., `file_path`, `bash_command`) collected into `gen_ai.tool.input`.

<Note>
  This limitation was resolved upstream. Earlier versions of Claude Code did not emit `tool.output` span events despite the env var being set.
</Note>

### Tracing is beta and requires opt-in

Claude Code's OTel tracing requires the `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` flag. The trace schema (span names, attribute names, hierarchy) may change between Claude Code versions without notice.

**Impact:** Fiddler's mapper may need updates when Claude Code's trace schema changes. Pin Claude Code versions in managed deployments to avoid unexpected schema changes.

### No distributed tracing to LLM providers

Claude Code does not send W3C `traceparent` headers when making LLM API calls. If Claude Code is routed through a proxy (e.g., LiteLLM), the proxy creates a new trace root rather than continuing Claude Code's trace. Claude Code traces and proxy traces are separate trace trees.

Claude Code does propagate `TRACEPARENT` to Bash subprocesses (e.g., when running shell commands), enabling trace correlation for subprocess-initiated LLM calls in non-interactive mode.

**Impact:** End-to-end distributed traces (user → coding agent → LLM proxy → LLM provider) require joining on `session.id` or `x-claude-code-session-id` at query time rather than native trace propagation.

### Content redaction is all-or-nothing per category

Content capture is controlled by three separate env vars (`OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_DETAILS`, `OTEL_LOG_TOOL_CONTENT`). Each controls an entire category — there is no per-attribute or per-tool-type granularity. You cannot, for example, capture user prompts while keeping tool content redacted within a single category.

### Thinking and reasoning content not available

There is no env var to export Claude's extended thinking or reasoning steps in OTel telemetry. Only metadata (token counts, model, latency) is available for the reasoning process, not the content.

### ScopeName and ScopeVersion empty in collected traces

Despite using instrumentation scope `com.anthropic.claude_code.tracing 1.0.0`, traces may show empty `ScopeName` and `ScopeVersion` fields. This does not affect span routing or processing — `service.name` and span name prefixes are used for detection.

### Summary

| Limitation | Severity | Description |
| - | - | - |
| No LLM response in traces | High | Output content available only via OTel log records. Log records now include `trace_id`/`span_id` (resolved upstream), but log-to-trace ingestion not yet implemented in Fiddler. |
| ~~No tool input/output~~ | ~~Resolved~~ | `tool.output` span events are now emitted when `OTEL_LOG_TOOL_CONTENT=1` is set. Fiddler extracts tool input and output using per-tool output key dispatch (Read→`content`, Bash→`output`, Edit→`diff`, Write→no output). |
| Beta tracing | Medium | Schema may change between versions. Requires `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA`. |
| No traceparent to LLM providers | Medium | Separate trace trees for agent and proxy. Join on session ID. |
| All-or-nothing redaction | Low | Cannot selectively control content capture per attribute. |
| No thinking content | Medium | Reasoning steps not available in any telemetry signal. |
| Empty ScopeName/ScopeVersion | Low | Does not affect functionality. |

***

## Related Documentation

* [Fiddler Claude Code Plugin](/integrations/agentic-ai/fiddler-claude-code-plugin) — Hook-based plugin that adds LLM response content and per-turn traces; complements native tracing
* [OpenTelemetry Integration](/integrations/agentic-ai/opentelemetry-integration) — Manual OTel instrumentation for custom frameworks
* [LiteLLM Integration](/integrations/agentic-ai/litellm-integration) — Unified LLM gateway with Fiddler observability
* [Strands Agents SDK](/integrations/agentic-ai/strands-sdk) — Native monitoring for Strands agent applications
* [AgentGateway Integration](/integrations/agentic-ai/agentgateway-integration) — Cisco AgentGateway observability
* [Fiddler OTel SDK](/integrations/agentic-ai/fiddler-otel-sdk) — Foundation package for custom OTel instrumentation
