> ## 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. Several content attributes (LLM responses, tool input/output) are **not available** in trace spans. 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            | ❌ Not emitted in trace spans                |
| 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 via Claude Code's settings file instead of environment variables. This ensures consistent telemetry across all developers without requiring them to set env vars manually.

Create or update `.claude/settings.json` (project-level) or `~/.claude/settings.json` (user-level):

```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>
  **Do not commit API keys to version control.** The `OTEL_EXPORTER_OTLP_HEADERS` value contains your Fiddler API key. If using project-level `.claude/settings.json`, add it to `.gitignore` to prevent accidental exposure. For CI/CD or shared environments, prefer setting credentials via environment variables instead of the settings file.
</Warning>

<Info>
  Settings in `.claude/settings.json` (project-level) take precedence over environment variables. Settings in the user-level `~/.claude/settings.json` apply to all projects unless overridden.
</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                 | Fiddler Mapping                             | Requires Env Var          | Description                                                                           |
| ------------------------- | ------------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------- |
| `user_prompt`             | `fiddler.contents.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`      | `fiddler.span.user.user_prompt_length`      | No                        | Character count of the user prompt (always available, even when content is redacted). |
| `interaction.sequence`    | `fiddler.span.user.interaction.sequence`    | No                        | Sequence number within the session (1 for first interaction, 2 for second, etc.).     |
| `interaction.duration_ms` | `fiddler.span.user.interaction.duration_ms` | No                        | Total duration of the interaction in milliseconds.                                    |
| `session.id`              | `fiddler.metadata.gen_ai.conversation.id`   | No                        | Claude Code session UUID. Used for session correlation.                               |

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

| Attribute               | Fiddler Mapping                                  | Description                                                                |
| ----------------------- | ------------------------------------------------ | -------------------------------------------------------------------------- |
| `input_tokens`          | `fiddler.span.system.gen_ai.usage.input_tokens`  | Number of input tokens (excluding cache).                                  |
| `output_tokens`         | `fiddler.span.system.gen_ai.usage.output_tokens` | Number of output tokens.                                                   |
| `cache_read_tokens`     | `fiddler.span.user.cache_read_tokens`            | Tokens read from Anthropic's prompt cache.                                 |
| `cache_creation_tokens` | `fiddler.span.user.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`               | `fiddler.span.user.ttft_ms`                      | Time to first token in milliseconds.                                       |
| `stop_reason`           | `fiddler.span.user.stop_reason`                  | Why the LLM stopped: `end_turn`, `tool_use`, `max_tokens`.                 |
| `success`               | `fiddler.span.user.success`                      | Whether the LLM call succeeded (`true`/`false`).                           |
| `error`                 | `fiddler.span.user.error`                        | Error message when `success` is `false`.                                   |
| `attempt`               | `fiddler.span.user.attempt`                      | Retry attempt number (1 for first try).                                    |
| `llm_request.context`   | `fiddler.span.user.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     | Fiddler Mapping                        | Description                                                                                |
| ------------- | -------------------------------------- | ------------------------------------------------------------------------------------------ |
| `tool_name`   | `fiddler.span.system.gen_ai.tool.name` | Tool identifier (e.g., `Bash`, `Read`, `Write`, `Edit`, `WebSearch`, `mcp__server__tool`). |
| `duration_ms` | `fiddler.span.user.duration_ms`        | Total tool duration including permission wait.                                             |

<Info>
  **Tool input/output content is not available in traces.** Despite the `OTEL_LOG_TOOL_CONTENT=1` env var, Claude Code does not currently emit `tool.output` span events on tool spans. See [Known Limitations](#known-claude-code-upstream-limitations).
</Info>

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

| Attribute     | Fiddler Mapping                 | Description                                                                |
| ------------- | ------------------------------- | -------------------------------------------------------------------------- |
| `decision`    | `fiddler.span.user.decision`    | User's permission decision: `accept` or `deny`.                            |
| `source`      | `fiddler.span.user.source`      | How the decision was made: `user_temporary`, `user_permanent`, `settings`. |
| `duration_ms` | `fiddler.span.user.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. Currently not functioning as documented — see [Known Limitations](#known-claude-code-upstream-limitations). |

#### 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`.

### 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). However, tool input/output content is not currently available in trace spans — see [Known Limitations](#known-claude-code-upstream-limitations).

### Enrichment worker skipping spans

If you see warnings like `Missing fiddler.span.system.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. Additionally, OTel log records are currently emitted without `trace_id` or `span_id`, making log-to-trace correlation impossible.

**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.

### Tool input/output not emitted in trace spans

Claude Code's documentation states that `OTEL_LOG_TOOL_CONTENT=1` records a `tool.output` span event with tool input and output bodies. In practice, tool spans have empty event arrays — the `tool.output` event is not emitted. Tool spans only carry `tool_name` and `duration_ms`.

**Impact:** Cannot see what arguments were passed to tools or what they returned. This limits visibility into MCP tool interactions and debugging tool failures.

### 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 (with broken trace correlation). |
| No tool input/output            | High     | `OTEL_LOG_TOOL_CONTENT=1` does not emit `tool.output` span events as documented.    |
| 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

* [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
