# Claude Now Sends OpenTelemetry Traces: What You Can See

> Source: <https://www.digitalapplied.com/blog/claude-opentelemetry-traces-agents>
> Published: 2026-10-14 00:00:00+00:00

On October 14, 2026, the Claude Platform release notes added a line that observability teams have been asking for since agents went into production: OpenTelemetry export, in beta, for Messages API requests and Claude Managed Agents sessions. The Claude SDK emits spans in Python, TypeScript, C#, Go, Java, PHP and Ruby, and the API itself emits spans once an admin adds an OpenTelemetry destination in the Claude Console. The traces land in whatever platform you already use, from an open-source collector to a commercial observability suite.

That last part is the point. Until now, seeing inside a Claude request meant wrapping the SDK yourself or trusting a third-party integration. Now the API will tell you, in a vendor-neutral format, what happened on its side: each model run inside a request, each server tool it executed, each turn of an agent session, with token counts and timing attached. OpenTelemetry is the standard most monitoring tools already understand, so the spans arrive with no custom parsing.

This post reads the two documentation pages behind the release note so you do not have to. It covers what a trace contains, the difference between metadata and full content, the setup steps, how to count tokens without double counting, and the limits the docs state plainly. Our broader [agent observability stack guide](https://www.digitalapplied.com/blog/ai-agent-observability-2026-tracing-monitoring-stack-guide) covers the discipline this plugs into.

1. 01Two sources, one trace.The SDK emits client-side spans for every request it sends and every client tool it runs. The API emits server-side spans for each model run, each server tool and each agent turn. Set up both and they nest into one trace per request.
2. 02API tracing needs no code, but it needs an admin.An organization admin adds a destination in the Claude Console with an OTLP/HTTP endpoint and a credential header. Every API client in the covered workspaces is traced from then on, whatever language or tool sent the request.
3. 03Metadata only is the default; full content is opt-in.Metadata spans carry identifiers, timing, status and token counts. Full content adds the system prompt, messages and responses, up to 0.75 MB per span by default. Your observability platform then stores that content under its own retention rules.
4. 04Token usage repeats across span levels. Sum one source.The docs are specific: for a Messages request, sum either the API's messages spans or its model-request spans, not both, and never add SDK and API spans together. Spans can also arrive twice, so de-duplicate by trace and span ID.
5. 05It is beta, best effort and not a billing record.Delivery is at least once with retries, but a span can be lost and never resent. Anthropic points you to the Usage API for anything that must be complete, such as spotting a leaked key.

## 01 — The ReleaseWhat shipped on *October 14*.

The release note is one paragraph. OpenTelemetry export is launched in beta so that Messages API requests and Managed Agents sessions can be traced in your observability backend; the SDK emits spans in seven languages; and to get spans from the API you add a destination in the Console. Everything else lives in the [OpenTelemetry documentation](https://platform.claude.com/docs/en/manage-claude/opentelemetry), which carries a beta notice pointing at the Beta Services section of Anthropic's service terms.

Two scope notes before anything else. First, this is the Claude API and Managed Agents. Claude Code, the Agent SDK and Cowork have their own OpenTelemetry support, documented separately, and the overview page sends you there rather than covering them. Second, the spans use the OpenTelemetry GenAI semantic conventions, the shared attribute names for AI workloads, so a platform that supports those conventions recognises a Claude span without any mapping. Anthropic adds its own attributes under an `anthropic.` prefix for things the conventions do not cover, such as session IDs and compaction tokens.

The docs also list twelve partner platforms with ready-made setup guides, from open-source tracing tools to the large commercial monitoring suites, and any other platform that accepts OTLP over HTTPS works through the Custom option. We are not linking the partners; if yours is in the list, the Console will ask for its API key instead of an endpoint URL.

## 02 — SourcesTwo sources of *spans*.

The thing to understand first is that there are two independent emitters, and they see different things. The SDK in your application emits client spans: one for each request it sends, one for each client-side tool the tool runner executes, one for file uploads and other API calls. The API emits server spans: one for the request as the server saw it, one for each model run inside it, one for each server tool or MCP connector tool the API ran, and for Managed Agents one per turn and one per outcome evaluation.

Why both? Because each is blind to half the picture. The SDK cannot see that a single request triggered two model runs with a web search in between. The API cannot see your custom tool executing on your own server, or the application span that called Claude in the first place. Set up only SDK tracing and you get coverage of clients that use the SDK, with no admin permission required. Set up only API tracing and you get every client, including ones you did not write, but nothing about what happens on your side. Set up both, in the same observability platform, and the API span nests under the SDK span which nests under your own.

| Condensed from the coverage table on Anthropic's OpenTelemetry overview page, read October 15, 2026. Using both gives every row. |  |  | 
|---|---|---|
| What you get | SDK tracing | API tracing | 
|---|---|---|
| Messages and Sessions API requests | Yes | Yes | 
| Token usage | Yes | Yes | 
| Each model run within a request | No | Yes | 
| Managed Agents turns | No | Yes | 
| Server tools run by the API | No | Yes | 
| Client tools run by the tool runner | Yes | No | 
| Tools in a self-hosted sandbox | Yes | No | 
| Other API requests, such as file uploads | Yes | No | 
| Setup · permission · coverage | Code · none · SDK clients | Console · admin · any client | 

## 03 — AnatomyWhat a trace *looks like*.

The overview page walks through two example traces, and they are worth reading closely because the shape is not what a plain HTTP trace would suggest. Take a Messages API request that uses the SDK's tool runner, the helper that executes your tools and feeds results back. Your application opens a span, say `answer_question`, and calls the tool runner inside it. The runner sends a first request, which appears as a client span from the SDK with a server span from the API underneath. Inside that server span the API ran a web search between two model runs. The second model run asked for your custom `get_weather` tool, so the request ended. The runner executed `get_weather`, visible as its own span, then sent a second request with the result, and the model answered.

Six steps, a dozen spans, one trace. Every model run has its own timing and token usage. Every server tool is a span with its arguments and, in full-content mode, its result. That is the level of detail that turns "the agent was slow" into "the second model run was waiting on the web search." For an engineer used to tracing microservices, it is the same picture with model runs in place of downstream services.

Managed Agents sessions add a layer. A session has a span for each Sessions API request and a turn span for each agent turn; a turn contains its model runs, each tool the API ran, and each outcome evaluation. The docs' example follows a chat request: your application's `POST /chat` span, the SDK's event-stream spans, the request that sends the user's message, a turn with a bash tool use and a turn on another thread, your custom tool running, and a second turn that finishes with the result. The failure case to plan for is that a session's spans can land in several traces, because a later request can start from a new root. The fix is to group by ID rather than by trace: one thread by `gen_ai.conversation.id`, a whole session across all its threads by `anthropic.session.id`.

`gen_ai.system_instructions` on a thread's first turn span, the inputs in `gen_ai.input.messages`, the agent's output in `gen_ai.output.messages`, and a tool's arguments and result in `gen_ai.tool.call.arguments` and `anthropic.tool_result.content`. Group the turn spans by conversation ID, sort by start time, and you have the conversation in order.
## 04 — Content ModesMetadata or *full content*.

Every destination and every SDK client has a content mode. The default, metadata only, sends identifiers, timing, status, token counts, and text you choose to expose such as the names and descriptions of your agents, tools and MCP servers. Full content adds the prompts and responses themselves. The docs describe what that buys you in one sentence: you can see why a run failed or was slow, read whole conversations, and build evaluations from real traces.

The trade is where that content ends up. Once delivered, it is stored by your observability platform under that platform's access and retention settings, not Anthropic's, and the docs say so twice. A team that has negotiated zero data retention with Anthropic and then switches on full content has, in effect, moved its retention question to a different vendor. For Messages API requests under zero data retention, the API holds exported content only in memory until it is delivered. Managed Agents is not eligible for zero data retention at all, and OpenTelemetry does not change that.

Two more rules. Organisations with a HIPAA, FERPA or K-12 data restriction with Anthropic get metadata only from API destinations whatever mode is set, though SDK spans are unaffected. And content is capped: 0.75 MB per span by default, which the docs say fits a 200K-token window of English text and stays under the 1 MB request limit common to observability platforms and proxies. Over the cap, the span is shortened and flagged with `anthropic.content.truncated`. Request spans drop the system prompt and earliest messages first; tool spans drop from the end of the result. A full 1M-token window needs about 4 MB, so a team tracing long-context agents should raise the limit if its platform accepts it.

##### Metadata only

Enough for latency, cost and failure-rate dashboards and for grouping sessions by ID. No prompts or responses leave Anthropic. The mode forced on HIPAA, FERPA and K-12 restricted organisations.

##### Full content

Read a failed run, replay a conversation, build evals from live traffic. Content is stored by your observability vendor under its rules. Capped at 0.75 MB per span unless you raise it.

## 05 — SetupSetting it *up*.

API tracing is a Console task, documented on the [API setup page](https://platform.claude.com/docs/en/manage-claude/opentelemetry/api). You need the admin role in your Claude Console organisation, an OTLP/HTTP endpoint that accepts protobuf over HTTPS on port 443, and a credential for it. That port requirement catches people running their own OpenTelemetry Collector, whose OTLP/HTTP receiver listens on 4318 by default; the docs say to reconfigure it for HTTPS on 443 or put a load balancer or reverse proxy in front.

In the Console you open the organisation's OpenTelemetry settings, add a destination, and fill in a provider, the base endpoint URL, request headers for authentication, a content mode, and which workspaces it covers. The URL detail that will save someone an hour: enter the base OTLP URL and do not append `/v1/traces`, because the API adds it. If your platform uses a non-standard traces path, there is a separate advanced field for the full traces URL, which must share a host with the base URL. Header values are credentials and the Console never shows them again after saving.

Then you test. The destination's menu has a Test action that sends an `anthropic.test` span and reports whether it was delivered. After a real request, the Delivery column should show Healthy within about a minute, and in your platform you filter on `service.name` equal to `claude-platform` to find the spans. The same destination can be created through the Admin API or the CLI, which matters for teams that manage infrastructure as code; the API route needs the `telemetry-destinations-2026-08-11` beta header.

Workspaces are the scoping unit. A destination can cover all workspaces, a selected set, or all except some, and the API sends spans to every enabled destination that covers the workspace a request ran in. A sensible first rollout is one destination covering a staging workspace in full-content mode, then a second covering production in metadata mode, rather than one destination for everything.

##### Endpoint and credential

An OTLP/HTTP endpoint on HTTPS port 443 that accepts protobuf, plus an API key or bearer token for its headers. A self-run Collector needs a proxy or a port change first.

##### Add the destination as an admin

Base URL without /v1/traces, headers with the credential, content mode, and the workspaces it covers. Click Test and look for the anthropic.test span in your platform.

##### Add SDK tracing in the app

Register a tracer provider so the SDK emits client spans, and call Claude from inside your own spans. The API reads the W3C traceparent header and nests its spans under yours.

##### Verify and de-duplicate

Confirm Delivery shows Healthy, filter on service.name = claude-platform, and make sure your platform drops repeated spans by trace ID and span ID, because delivery is at least once.

## 06 — Token MathCounting tokens *once*.

The most useful page section for anyone building a cost dashboard is also the easiest to get wrong. Token usage appears on several spans of the same request, so a naive sum over all spans counts the same tokens two or three times. The docs give an explicit rule: sum the spans of only one source per request, and within that source sum only one level.

For a request traced by both the SDK and the API, sum the API spans and ignore the SDK's. Both are named `anthropic.messages.create`; the SDK's is kind CLIENT and the API's, its child, is kind SERVER. Within the API spans, sum either the `anthropic.messages.create` spans or the `anthropic.model_request` spans beneath them, never both. If a request compacted its context, add the `anthropic.compaction` spans too, but do not also add the compaction attributes on the parent span, because they hold the same tokens. For a Managed Agents session, sum the model-request spans and the outcome-evaluation spans.

Two further traps. The `gen_ai.usage.input_tokens` attribute already includes tokens read from and written to the prompt cache, so adding the cache attributes on top double counts them. And because delivery is at least once, a retried delivery can land the same span twice; if your platform does not de-duplicate, do it yourself on trace ID plus span ID. Teams that attribute model spend to features or customers will recognise all of this from our [cost attribution guide](https://www.digitalapplied.com/blog/llm-agent-cost-attribution-guide-production-2026); the new part is that the vendor's own spans now carry the numbers.

## 07 — GapsWhat is *missing*.

The docs are unusually direct about limits, and they deserve the same directness here. Delivery is best effort. A span can be lost before delivery and the API cannot resend it. Retries happen a limited number of times after timeouts, connection failures and 408, 429 or 5xx responses, and not after other failures. Each delivery must complete within ten seconds, with a five-second TLS handshake and a five-second wait for response headers. The consequence, stated on the overview page, is that exported spans are not a complete record of API usage. For anything that must be complete, such as noticing that a key has leaked, the Usage API is the tool, because it counts requests that produced no span.

The API also disables a destination on its own under conditions the setup page lists, a 3xx redirect from the endpoint being the first. A destination that silently flips to Disabled is a monitoring gap in your monitoring, so alert on the Delivery column or poll the Admin API for destination state.

Trace nesting has a platform gap. The API reads the W3C `traceparent` header to attach its spans to yours, and if the header's sampled flag is off it emits nothing for that request. Claude Platform on AWS does not support the header yet, so spans from requests sent there always start their own traces, even when the flag is off. Teams on AWS get the API spans but not the nesting, for now.

Finally, retention. Managed Agents is not eligible for zero data retention and OpenTelemetry leaves that unchanged. Covered Models, the ones with their own retention requirements, are excluded from the feature's zero-data-retention eligibility. And once content reaches your platform, its retention is that platform's problem. None of these is hidden; all of them belong in the review before a regulated team switches full content on. The patterns in our [trace-quality anti-patterns post](https://www.digitalapplied.com/blog/agent-observability-anti-patterns-trace-quality-mistakes-2026) apply unchanged.

## 08 — DecisionWho should turn it *on*.

Anyone running Claude in production with an observability platform already in place should add an API destination in metadata mode this week. The cost is an admin's ten minutes, the risk is low because no content leaves Anthropic, and the return is a per-model-run view of latency and tokens for every client, including the ones built by a contractor two years ago. That alone answers the "why did the bill double" question without a code change.

Teams building agents, whether on Managed Agents or their own loop with the tool runner, should add SDK tracing too, because the interesting failures happen at the seams: a tool that took far longer than the model run, a turn that ended on a tool request nobody handled, a session whose spans scattered across three traces until someone grouped them by session ID. Full content belongs in staging and in any environment where building evaluations from real traffic is a goal, after the retention review above.

Who should wait: organisations on Claude Platform on AWS that need nested traces, teams whose platform cannot accept HTTPS on port 443 without new infrastructure, and anyone who would treat the spans as a billing or audit record. It is a beta, and the docs say the spans can be incomplete. Our [AI transformation team](https://www.digitalapplied.com/services/ai-transformation) sets this up as part of taking an agent from pilot to production, including the retention review that decides which mode each workspace gets.

## 09 — ConclusionThe vendor's side of the trace is now *visible*.

### Add a metadata-only destination for production now, trace staging in full content, and sum tokens from one span source before you trust a dashboard.

As of Anthropic's October 14, 2026 release note, the Claude API and Managed Agents emit OpenTelemetry spans in beta to any OTLP endpoint, and the SDK emits matching client spans in seven languages. A trace now shows every model run, every server tool and every agent turn with timing and token usage, in the standard format your observability platform already reads.

The design choices are sensible and documented: metadata by default with content opt-in, a per-span content cap with explicit truncation rules, workspace scoping, and an at-least-once delivery model that the docs refuse to oversell. The limits are equally clear. Spans can be lost, AWS does not nest traces yet, Managed Agents keeps its retention terms, and the Usage API remains the record of truth for consumption.

For most production teams the first step is small and reversible: one destination, metadata only, production workspaces, Delivery column showing Healthy. Everything after that, from full-content staging traces to evaluation sets built from live sessions, is a decision about where your prompts are allowed to live, and that decision should be made deliberately rather than inherited from a default.
