Follow Discord
Sweep 10 Nov 2026 · 02:18Z Build v2.1.322 539 read Stable v2.1.311 Latest v2.1.322 Next v2.1.322 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Observability with OpenTelemetry changedagent-sdk/observability

Nearest release: v2.1.309, published 6 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 23 Oct 2026 02:37 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 23 Oct 2026 19:07 UTC.

Upstream edited
Recorded here
Lines+19added
Lines−19removed
From line 11 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits15to this page, all time

The whole hunk

from line 11, old and new numbered
/
lines
from line 11
1111 
1212The Agent SDK can export this data as OpenTelemetry traces, metrics, and log events to any backend that accepts the OpenTelemetry Protocol (OTLP), whether a hosted observability platform or a self-hosted collector.
1313 
14This guide explains how the SDK emits telemetry, how to configure the export, and how to tag and filter the data once it reaches your backend. To read token usage and cost directly from the SDK response stream instead of exporting to a backend, see [Track cost and usage](/docs/en/agent-sdk/cost-tracking.md).
14This guide explains how the SDK emits telemetry, how to configure the export, and how to tag and filter the data once it reaches your backend. To read token usage and cost directly from the SDK response stream instead of exporting to a backend, see [Track cost and usage](https://code.claude.com/docs/en/agent-sdk/cost-tracking.md).
1515 
1616> [!NOTE]
1717>
from line 34
3434| Log events | Structured records for each prompt, API request, API error, and tool result | `OTEL_LOGS_EXPORTER` |
3535| Traces | Spans for each interaction, model request, tool call, and hook (beta) | `OTEL_TRACES_EXPORTER` plus `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1` |
3636 
37For the complete list of metric names, event names, and attributes, see the Claude Code [Monitoring](/docs/en/monitoring-usage.md) reference. The Agent SDK emits the same data because it runs the same CLI. Span names are listed in [Read agent traces](#read-agent-traces) below.
37For the complete list of metric names, event names, and attributes, see the Claude Code [Monitoring](https://code.claude.com/docs/en/monitoring-usage.md) reference. The Agent SDK emits the same data because it runs the same CLI. Span names are listed in [Read agent traces](#read-agent-traces) below.
3838 
3939## Enable telemetry export
4040 
from line 101
101101 
102102Because the child process inherits your application's environment by default, you can achieve the same result by exporting these variables in a Dockerfile, Kubernetes manifest, or shell profile and omitting `options.env` entirely.
103103 
104To confirm that export is working, check your collector's logs for incoming spans, metrics, and log events after the task completes. The CLI fails silently on export errors by default: if the endpoint is unreachable or rejects the data, the agent still runs normally and the CLI drops the telemetry without surfacing an error in your application. To surface exporter errors, set [`CLAUDE_CODE_OTEL_DIAG_STDERR=1`](/docs/en/env-vars) alongside the exporter variables and read the diagnostics through the SDK's `stderr` callback (Python) or `stderr` option (TypeScript). Requires Claude Code v2.1.179 or later.
104To confirm that export is working, check your collector's logs for incoming spans, metrics, and log events after the task completes. The CLI fails silently on export errors by default: if the endpoint is unreachable or rejects the data, the agent still runs normally and the CLI drops the telemetry without surfacing an error in your application. To surface exporter errors, set [`CLAUDE_CODE_OTEL_DIAG_STDERR=1`](https://code.claude.com/docs/en/env-vars) alongside the exporter variables and read the diagnostics through the SDK's `stderr` callback (Python) or `stderr` option (TypeScript). Requires Claude Code v2.1.179 or later.
105105 
106106> [!NOTE]
107107>
from line 141
141141* **`claude_code.interaction`:** wraps a single turn of the agent loop, from receiving a prompt to producing a response.
142142* **`claude_code.llm_request`:** wraps each call to the Claude API, with model name, latency, and token counts as attributes.
143143* **`claude_code.tool`:** wraps each tool invocation, with child spans for the permission wait (`claude_code.tool.blocked_on_user`) and the execution itself (`claude_code.tool.execution`).
144* **`claude_code.hook`:** wraps each [hook](/docs/en/agent-sdk/hooks.md) execution. Requires detailed beta tracing (`ENABLE_BETA_TRACING_DETAILED=1` and `BETA_TRACING_ENDPOINT`), a pair that also [changes where your logs and traces go](/docs/en/env-vars.md#variables).
144* **`claude_code.hook`:** wraps each [hook](https://code.claude.com/docs/en/agent-sdk/hooks.md) execution. Requires detailed beta tracing (`ENABLE_BETA_TRACING_DETAILED=1` and `BETA_TRACING_ENDPOINT`), a pair that also [changes where your logs and traces go](https://code.claude.com/docs/en/env-vars.md#variables).
145145 
146146The `llm_request`, `tool`, and `hook` spans are children of the enclosing `claude_code.interaction` span. When the agent spawns a subagent through the Agent tool, the subagent's `llm_request` and `tool` spans nest under the parent agent's `claude_code.tool` span, so the full delegation chain appears as one trace.
147147 
148Spans carry a `session.id` attribute by default. When you make several `query()` calls against the same [session](/docs/en/agent-sdk/sessions.md), filter on `session.id` in your backend to see them as one timeline. Claude Code omits the attribute if you set `OTEL_METRICS_INCLUDE_SESSION_ID` to a falsy value.
148Spans carry a `session.id` attribute by default. When you make several `query()` calls against the same [session](https://code.claude.com/docs/en/agent-sdk/sessions.md), filter on `session.id` in your backend to see them as one timeline. Claude Code omits the attribute if you set `OTEL_METRICS_INCLUDE_SESSION_ID` to a falsy value.
149149 
150150> [!NOTE]
151151>
152152> Tracing is in beta. Span names and attributes may change between releases. See
153> [Traces (beta)](/docs/en/monitoring-usage.md#traces-beta) in the Monitoring reference
153> [Traces (beta)](https://code.claude.com/docs/en/monitoring-usage.md#traces-beta) in the Monitoring reference
154154> for the trace exporter configuration variables.
155155 
156156## Link traces to your application
from line 157
157157 
158158The SDK automatically propagates W3C trace context into the CLI subprocess. When you call `query()` while an OpenTelemetry span is active in your application, the SDK injects `TRACEPARENT` and `TRACESTATE` into the child process environment, and the CLI reads them so its `claude_code.interaction` span becomes a child of your span. The agent run then appears inside your application's trace instead of as a disconnected root.
159159 
160OTLP event log records emitted during the run carry the same trace context: with `TRACEPARENT` set, each record's `trace_id` and `span_id` match your application's trace, so you can join [events](/docs/en/monitoring-usage.md#events) to spans in your backend. Before v2.1.212, event records emitted outside an active span didn't carry `trace_id` or `span_id`.
160OTLP event log records emitted during the run carry the same trace context: with `TRACEPARENT` set, each record's `trace_id` and `span_id` match your application's trace, so you can join [events](https://code.claude.com/docs/en/monitoring-usage.md#events) to spans in your backend. Before v2.1.212, event records emitted outside an active span didn't carry `trace_id` or `span_id`.
161161 
162162When trace-context propagation is enabled, the CLI also forwards `TRACEPARENT` to every Bash and PowerShell command it runs. If a command launched through the Bash tool emits its own OpenTelemetry spans, those spans nest under the `claude_code.tool.execution` span that wraps the command.
163163 
164Auto-injection is skipped when you set `TRACEPARENT` explicitly in `options.env`, so you can pin a specific parent context if needed. Interactive CLI sessions ignore inbound `TRACEPARENT` entirely; only Agent SDK and `claude -p` runs honor it. See [Traces (beta)](/docs/en/monitoring-usage.md#traces-beta) in the Monitoring reference for the full span and attribute reference.
164Auto-injection is skipped when you set `TRACEPARENT` explicitly in `options.env`, so you can pin a specific parent context if needed. Interactive CLI sessions ignore inbound `TRACEPARENT` entirely; only Agent SDK and `claude -p` runs honor it. See [Traces (beta)](https://code.claude.com/docs/en/monitoring-usage.md#traces-beta) in the Monitoring reference for the full span and attribute reference.
165165 
166166## Tag telemetry from your agent
167167 
from line 193
193193 
194194## Attribute actions to your end users
195195 
196The CLI attaches [identity attributes](/docs/en/monitoring-usage.md#standard-attributes) to every event based on the credential it uses to call Anthropic. When you build an application that serves many end users from one deployment, these attributes identify your service's credential, not the end user on whose behalf the agent acted.
196The CLI attaches [identity attributes](https://code.claude.com/docs/en/monitoring-usage.md#standard-attributes) to every event based on the credential it uses to call Anthropic. When you build an application that serves many end users from one deployment, these attributes identify your service's credential, not the end user on whose behalf the agent acted.
197197 
198To make tool calls and MCP activity attributable to your application's end users, inject end-user identity as resource attributes on each `query()` call. Percent-encode values before interpolating them, since `OTEL_RESOURCE_ATTRIBUTES` [reserves commas, spaces, and equals signs](/docs/en/monitoring-usage.md#multi-team-organization-support). The following example attaches the requesting user and tenant to every span and event from one request. It assumes a `request` object from your web framework carrying the user and tenant IDs:
198To make tool calls and MCP activity attributable to your application's end users, inject end-user identity as resource attributes on each `query()` call. Percent-encode values before interpolating them, since `OTEL_RESOURCE_ATTRIBUTES` [reserves commas, spaces, and equals signs](https://code.claude.com/docs/en/monitoring-usage.md#multi-team-organization-support). The following example attaches the requesting user and tenant to every span and event from one request. It assumes a `request` object from your web framework carrying the user and tenant IDs:
199199 
200200```python Python theme={null}
201201from urllib.parse import quote
from line 223
223223After you attach end-user identity, these events become a per-user audit trail you can forward to a Security Information and Event Management (SIEM) platform:
224224 
225225* `tool_decision` and `tool_result`: each tool call, whether it was allowed or denied, and its result
226* `safety_event`: which check refused a tool call or required a permission prompt for it, such as a permission rule or the auto mode classifier. Some calls [have no safety event](/docs/en/monitoring-usage.md#calls-without-a-safety-event). Requires Claude Code v2.1.307 or later
226* `safety_event`: which check refused a tool call or required a permission prompt for it, such as a permission rule or the auto mode classifier. Some calls [have no safety event](https://code.claude.com/docs/en/monitoring-usage.md#calls-without-a-safety-event). Requires Claude Code v2.1.307 or later
227227* `mcp_server_connection`: MCP server connections and connection failures
228228* `permission_mode_changed`: permission mode changes
229229 
230These events export as log records named with a `claude_code.` prefix, such as `claude_code.safety_event`. See [Audit security events](/docs/en/monitoring-usage.md#audit-security-events) in the Monitoring reference for the full list of security-relevant events and the attributes each one carries.
230These events export as log records named with a `claude_code.` prefix, such as `claude_code.safety_event`. See [Audit security events](https://code.claude.com/docs/en/monitoring-usage.md#audit-security-events) in the Monitoring reference for the full list of security-relevant events and the attributes each one carries.
231231 
232232## Control sensitive data in exports
233233 
from line 236
236236| Variable | Adds |
237237| - | - |
238238| `OTEL_LOG_USER_PROMPTS=1` | Prompt text on `claude_code.user_prompt` events and on the `claude_code.interaction` span |
239| `OTEL_LOG_TOOL_DETAILS=1` | Tool input arguments such as file paths, shell commands, and search patterns on `claude_code.tool_result` events, and real agent, skill, plugin, and MCP server names on the [cost and token metrics](/docs/en/monitoring-usage.md#cost-counter). The built-in rule the auto mode classifier named when it blocked a call, as [`classifier_category`](/docs/en/monitoring-usage#tool-decision-event) on `claude_code.tool_decision` and `claude_code.safety_event` events |
240| `OTEL_LOG_TOOL_CONTENT=1` | A [`tool.output` span event](/docs/en/monitoring-usage#tool-output-span-event) on `claude_code.tool` with file contents, Bash output, and what MCP tools, WebFetch, and WebSearch return, truncated at 60 KB by default, configurable via `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH`, which requires Claude Code v2.1.214 or later. Results from MCP tools, WebFetch, and WebSearch require Claude Code v2.1.283 or later. Requires [tracing](#read-agent-traces) to be enabled. Span attributes carry tool content under [their own gates](/docs/en/monitoring-usage.md#new-context-gates) |
239| `OTEL_LOG_TOOL_DETAILS=1` | Tool input arguments such as file paths, shell commands, and search patterns on `claude_code.tool_result` events, and real agent, skill, plugin, and MCP server names on the [cost and token metrics](https://code.claude.com/docs/en/monitoring-usage.md#cost-counter). The built-in rule the auto mode classifier named when it blocked a call, as [`classifier_category`](https://code.claude.com/docs/en/monitoring-usage#tool-decision-event) on `claude_code.tool_decision` and `claude_code.safety_event` events |
240| `OTEL_LOG_TOOL_CONTENT=1` | A [`tool.output` span event](https://code.claude.com/docs/en/monitoring-usage#tool-output-span-event) on `claude_code.tool` with file contents, Bash output, and what MCP tools, WebFetch, and WebSearch return, truncated at 60 KB by default, configurable via `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH`, which requires Claude Code v2.1.214 or later. Results from MCP tools, WebFetch, and WebSearch require Claude Code v2.1.283 or later. Requires [tracing](#read-agent-traces) to be enabled. Span attributes carry tool content under [their own gates](https://code.claude.com/docs/en/monitoring-usage.md#new-context-gates) |
241241| `OTEL_LOG_RAW_API_BODIES` | Full Anthropic Messages API request and response JSON as `claude_code.api_request_body` and `claude_code.api_response_body` log events. Set to `1` for inline bodies truncated at 60 KB by default, or `file:<dir>` for untruncated bodies on disk with a `body_ref` path in the event. `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` configures the inline truncation limit, and requires Claude Code v2.1.214 or later. Bodies include the entire conversation history and have extended-thinking content redacted. Enabling this implies consent to everything the three variables above would reveal |
242242 
243Leave these unset unless your observability pipeline is approved to store the data your agent handles. See [Security and privacy](/docs/en/monitoring-usage.md#security-and-privacy) in the Monitoring reference for the full list of attributes and redaction behavior.
243Leave these unset unless your observability pipeline is approved to store the data your agent handles. See [Security and privacy](https://code.claude.com/docs/en/monitoring-usage.md#security-and-privacy) in the Monitoring reference for the full list of attributes and redaction behavior.
244244 
245245## Related documentation
246246 
247247These guides cover adjacent topics for monitoring and deploying agents:
248248 
249* [Track cost and usage](/docs/en/agent-sdk/cost-tracking.md): read token and cost data from the message stream without an external backend.
250* [Hosting the Agent SDK](/docs/en/agent-sdk/hosting.md): deploy agents in containers where you can set OpenTelemetry variables at the environment level.
251* [Monitoring](/docs/en/monitoring-usage.md): the complete reference for every environment variable, metric, and event the CLI emits.
249* [Track cost and usage](https://code.claude.com/docs/en/agent-sdk/cost-tracking.md): read token and cost data from the message stream without an external backend.
250* [Hosting the Agent SDK](https://code.claude.com/docs/en/agent-sdk/hosting.md): deploy agents in containers where you can set OpenTelemetry variables at the environment level.
251* [Monitoring](https://code.claude.com/docs/en/monitoring-usage.md): the complete reference for every environment variable, metric, and event the CLI emits.
252252 
Feedback