- From the Claude Console. The Claude API exports the spans it creates on Anthropic’s servers: the Sessions API requests, agent turns, model requests, and tool uses inside the sandbox. You configure this once for your organization, with no code changes.
- From your application. The Claude SDK emits a span for each request it sends and links it to the API’s spans with W3C trace context, so a session appears inside your application’s own trace.
Prerequisites
- Python 3.10+, Node.js 18.19+, Go 1.26+, or Java 11+ and Gradle for the application-side example
- An Arize AX account (sign up)
- The admin role in a Claude Console organization, to add a destination. With the developer role, you can view destinations
- An
ANTHROPIC_API_KEYfrom the Claude Console, in a workspace that sends spans to Arize AX
Launch Arize AX
Sign in
Copy your Space ID and API key
ARIZE_SPACE_ID and ARIZE_API_KEY below.Export spans from the Claude Console
A destination tells the Claude API where to send the spans it creates. The Claude Console has an Arize provider that fills in the endpoint and headers for you when you select the Arize AX product:Open the OpenTelemetry settings
Choose Arize AX
Enter your Arize AX details
claude-managed-agents-example.Set the content mode
Choose the workspaces
Send a test span
anthropic.test span arrived in the project.
The destination's More actions menu in the Claude Console, with Test highlighted
https://otlp.arize.com for US spaces, and the headers arize-space-id, arize-api-key, and x-project-name. The Claude API sets the resource attributes of its spans itself, so Arize AX routes them to a project by the x-project-name header.

The Claude Console's Add destination form with the Arize provider and the Arize AX product
https://otlp.arize.com, or https://otlp.eu-west-1a.arize.com for EU spaces, and the headers arize-space-id, arize-api-key, and x-project-name.
Install
The rest of this page traces a Managed Agents session from your application. You register an OpenTelemetry tracer provider that exports to Arize AX, then run the session inside one of your own spans. The Claude SDK sends the trace context of that span with each request. The API’s spans then nest under it, and the whole session appears as one trace.Configure credentials
ARIZE_COLLECTOR_ENDPOINT to that region’s endpoint, for example https://otlp.eu-west-1a.arize.com/v1 for EU spaces, and select the same Region on the destination. ANTHROPIC_OPEN_TELEMETRY_TRACES_CONTENT_MODE=content makes the SDK spans carry prompts and responses. Without it, they carry only metadata and token counts. The Java client reads it when you build it with AnthropicOkHttpClient.fromEnv().
Setup tracing
main. Neither registers the W3C trace context propagator by default, so both examples register it. Without it, the SDK can’t link its spans to the API’s spans. The Java example also registers the OpenTelemetry SDK globally, because the Claude SDK for Java uses the global instance.
Run Claude Managed Agents
The example creates an environment and an agent, starts a session inside afibonacci-agent span, and asks the agent to compute Fibonacci numbers with bash. It prints the agent’s reply. Run the Python example with python example.py and the TypeScript example with npx tsx example.ts.
The fibonacci-agent span is a CHAIN span, with the request as its input and the agent’s reply as its output. Python uses OpenInference’s @tracer.chain decorator and TypeScript its traceChain wrapper, which set the span kind, record the input and output, and set the span’s status for you. Go and Java set the openinference.span.kind, input.value, and output.value attributes themselves, and set the status to OK when the session finishes. Without a status, Arize AX shows a span’s status as unset. Without a span kind, Arize AX shows a span’s kind as unknown.
sessions.create call.Expected output
Verify in Arize AX
Open the project
claude-managed-agents-example.Open the new trace
fibonacci-agent CHAIN root span, the SDK’s client spans for each Sessions API request, and the API’s spans under them: an anthropic.session.turn span with anthropic.model_request and tool spans inside it.If no traces appear, see Troubleshooting.
A Claude Managed Agents session in Arize AX, with the agent's turn selected
Check from the skill, CLI, or SDK
Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.- Arize skill (agent)
- AX CLI
- SDK
Use the arize-trace skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.
Add tracing to your application
To trace your own Managed Agents application, follow the same steps as the example:Add a Console destination
Install the packages
Register the tracer provider
Run each session inside a CHAIN span
CHAIN span for each session. Wrap the function that creates the session, sends the user’s message, and reads the event stream, with the message as the input and the agent’s reply as the output. In Python, use the @tracer.chain decorator, and in TypeScript, the traceChain wrapper. In Go and Java, set openinference.span.kind, input.value, output.value, and the span’s status yourself.Run each custom tool inside a TOOL span
TOOL span for each custom tool that your application runs. A custom tool runs in your application, so the Claude API can’t see inside it. In Python, use @tracer.tool, and in TypeScript, traceTool. In Go and Java, also set tool.name, tool.description, and tool.parameters. The API already traces the tools that run in its sandbox, such as bash and MCP tools, so don’t add spans for those. In a self-hosted sandbox, the SDK’s environment worker traces those tools instead, under an anthropic.environment.work span for each work item. If you run your custom tools with the Claude SDK’s session tool runner, client.beta.sessions.events.tool_runner in Python, client.beta.sessions.events.toolRunner in TypeScript, or client.Beta.Sessions.Events.NewToolRunner in Go, the SDK already creates a TOOL span for each call, anthropic.custom_tool_use <tool>, so don’t add your own. The cookbook shows a custom tool in all four languages.Shut down the tracer provider
session.id: Arize AX groups each thread’s spans into a session by gen_ai.conversation.id, as described in What Arize AX captures. Some of the Claude SDK’s and the API’s spans show an unknown kind or unset status, as listed in Known limitations. They don’t mean your instrumentation is wrong.
What Arize AX captures
The SDK and the API mark their spans withgen_ai.* attributes, and Arize AX converts them to OpenInference attributes on ingestion. See How Arize AX ingests GenAI spans.
TOOL span for a custom tool, as in Add tracing to your application.
Arize AX groups a session’s spans into a session by gen_ai.conversation.id, which holds the session thread ID, so each Managed Agents thread is one session in the Sessions tab. Select it to read the thread as a conversation. If you set the SDK’s conversation_id option, the SDK’s spans carry your ID in gen_ai.conversation.id, so they form a session of their own, apart from the API’s spans. To find every span of a multiagent session across all its threads, filter on anthropic.session.id. A turn that starts because an agent on another thread replied or finished has no parent, so it’s the root of a trace of its own.
Known limitations
- Cache token counts aren’t shown. The spans report cache reads and writes as
gen_ai.usage.cache_read.input_tokensandgen_ai.usage.cache_write.input_tokens, which Arize AX doesn’t map yet. Arize AX counts all of a request’s input tokens as regular prompt tokens, so cost estimates for requests that read from the prompt cache can be higher than what you were billed. The raw attributes stay on the span. For a session’s actual token usage and list cost, read the session’susagefield or thesession.usageevent, as described in Anthropic’s Inspect sessions and track usage. - Session requests appear as LLM spans. The
anthropic.sessions.createspans carry the agent’s model, so Arize AX classifies them asLLMspans, with zero tokens. They aren’t model calls. The model calls are theanthropic.model_requestspans. - Some Sessions API requests have no span kind. The
anthropic.agents.create,anthropic.environments.create,anthropic.sessions.events.send, andanthropic.sessions.events.streamspans don’t say what kind of operation they are, so Arize AX shows their kind as unknown. Your own spans don’t have this problem as long as they set a span kind. - The SDK’s stream spans have no status. The SDK’s
anthropic.sessions.events.streamspan ends without a status when your application stops reading the stream, so Arize AX shows it as unset. The API’s span of the same name inside it has a status. - Messages API requests count tokens more than once. For a Managed Agents session, only the
anthropic.model_requestandanthropic.session.outcome_evaluationspans carry token usage, so trace totals are correct. For a Messages API request, the usage is on the SDK’santhropic.messages.createspan, the API’s span of the same name, and the API’santhropic.model_requestchildren, so trace totals are higher than the request used. See Anthropic’s guidance on counting tokens. - The Sessions list doesn’t summarize these sessions. The session ID is on the SDK’s and the API’s spans, not on the
CHAINspan at the root of each trace, so the Sessions list shows no first message, last message, duration, or tokens, and a session shows zero traces. Select the session to read its conversation. - Tool spans don’t show an output. Tool results are in the
anthropic.tool_result.contentattribute, which Arize AX doesn’t map to the span output yet. Read it from the span’s attributes. On the SDK’santhropic.custom_tool_usespans,tool.parametersalso holds the call’s arguments rather than the tool’s JSON schema. - Images and documents aren’t included. Spans record only the type of an image or document in a prompt or response, not its data.
- Long content is shortened. Each span holds a limited amount of content, by default 0.75 MB. When content is over the limit, the SDK or the API shortens it and sets
anthropic.content.truncatedtotrue. Change the destination’s limit under Advanced settings, and the SDK’s withANTHROPIC_OPEN_TELEMETRY_TRACES_MAX_CONTENT_BYTES. See Anthropic’s Content limits.
Troubleshooting
- No traces at all. Check that
ARIZE_SPACE_ID,ARIZE_API_KEY, andARIZE_PROJECT_NAMEare set in the shell that runs the example. WithoutARIZE_PROJECT_NAME, your spans go to a project nameddefault. Register the tracer provider before the first Claude SDK call, and check thatANTHROPIC_OPEN_TELEMETRYisn’tfalse. SetOTEL_LOG_LEVEL=debugto see export errors. - The destination shows Failing. Hold the pointer over Failing to see the error. A
401or403means a wrong API key or Space ID, or a key that doesn’t belong to that space. A rejection that mentions project routing means the destination has no Project name. Check that the Region matches your space: EU spaces usehttps://otlp.eu-west-1a.arize.com. If your own spans don’t arrive either, check thatARIZE_COLLECTOR_ENDPOINTpoints to the same region. If you change the Region of a destination, enter the API key again. - The destination shows Disabled. Hold the pointer over Disabled to see why. The API disables a destination after 24 hours of failed deliveries, or when the endpoint redirects or resolves to an IP address that isn’t public. Fix the cause, then click Enable in the destination’s More actions menu, with the Workspace filter set to All.
- Only your own spans appear, with no API spans. Check that the destination’s Workspaces include the workspace of your
ANTHROPIC_API_KEY, and that the destination’s Project name matchesARIZE_PROJECT_NAME. The API’s spans can take about a minute to arrive. - The API’s spans are in a separate trace. The SDK didn’t send the trace context. Check that you installed or upgraded the Claude SDK to a version that emits spans. In Go and Java, register the W3C trace context propagator as the examples do, and in TypeScript call
provider.register(). If your application uses another propagator, such as B3, add the W3C trace context propagator too. In Java, also build the OpenTelemetry SDK withbuildAndRegisterGlobal(), and check that no other dependency pinsopentelemetry-apibelow 1.57.0. In TypeScript, if you use@opentelemetry/instrumentation-undici, which@opentelemetry/auto-instrumentations-nodeincludes, create the client withopenTelemetry: { propagation: false }: that package adds a secondtraceparentheader, which makes the trace context invalid. Requests to Claude Platform on AWS always start traces of their own. - Your spans are missing when the program exits. The batch span processor exports in the background. Shut down the tracer provider before the process exits, as the examples do:
shutdown()in Python and TypeScript, the deferredShutdownin Go, andforceFlushandshutdownin Java. In Go, return errors from a function instead of callinglog.Fatalwhile a span is open, becauselog.Fatalexits without running deferred calls. - Each request appears twice. Each request has an SDK span and, inside it, an API span with the same name, as listed in What Arize AX captures. That’s expected. If a request has three spans of that name, another library also traces the Claude SDK, for example the OpenInference Anthropic instrumentor. Remove one of the two, or turn the SDK’s spans off with
ANTHROPIC_OPEN_TELEMETRY=false. - Spans have no prompts or responses. Set the destination’s content mode to Full content and
ANTHROPIC_OPEN_TELEMETRY_TRACES_CONTENT_MODE=contentfor the SDK. If your organization has a HIPAA, FERPA, or K-12 data-handling restriction with Anthropic, destinations export only metadata, whatever their content mode. The SDK’s spans still carry content.