Building on Claude Managed Agents? The Claude Platform and the Claude SDK export OpenTelemetry spans for sessions natively, so you don’t need this instrumentor. Don’t run both on the same client, or each request appears twice.
Prerequisites
- Python 3.10+, Node.js 18+, or Go 1.25+
- For the current Messages API features on this page:
openinference-instrumentation-anthropic3.1.0 or later (Python, withanthropic1.8.0 or later), or@arizeai/openinference-instrumentation-anthropic1.0.0 or later (TypeScript) - An Arize AX account (sign up)
- An
ANTHROPIC_API_KEYfrom the Anthropic Console
Launch Arize AX
- Sign in to your Arize AX account.
- From Space Settings, copy your Space ID and API Key. You will set them as
ARIZE_SPACE_IDandARIZE_API_KEYbelow.
Install
Configure credentials
Setup tracing
Anthropic SDK spans. Starting with
anthropic 1.14.0 (Python) and @anthropic-ai/sdk 0.134.0 (TypeScript), the Anthropic SDK emits its own OpenTelemetry spans whenever a tracer provider is registered. With the OpenInference instrumentor also running, each request would appear twice, and its tokens and cost would be counted twice. The setup above sets ANTHROPIC_OPEN_TELEMETRY=false so that only the OpenInference spans are exported. A client created with an explicit open_telemetry (Python) or openTelemetry (TypeScript) option ignores the variable, so pass False / false there instead.Go SDK Only
/v1/messages is instrumented today. Streaming responses pass through unchanged, but output.value and token counts are not populated for streaming spans yet. tool_use content blocks in messages are not yet captured as message.tool_calls attributes — wrap your tool execution in manual TOOL spans, see Manual instrumentation.Run Anthropic
Expected output
Verify in Arize AX
- Open your Arize AX space and select project
anthropic-tracing-example. - You should see a new trace within ~30 seconds containing an LLM span —
messages.createfor the Python SDK,Anthropic Messagesfor the Node.js SDK, oranthropic.messages.createfor the Go SDK — with the prompt, response, and token usage attached. Other Python methods get spans named after the method, such asmessages.stream,messages.parse,messages.count_tokens, andbeta.messages.create. In Node.js, everymessages.createandmessages.streamcall is anAnthropic Messagesspan, stable or beta, and token counting is anAnthropic Count Tokensspan. - If no traces appear, see Troubleshooting.
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
Install the Arize Skills plugin and let your coding agent check for you:Then prompt your agent:
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.
What gets captured
The Python and TypeScript instrumentors cover the stable and beta Messages API (client.messages and client.beta.messages), streaming and non-streaming. Each LLM span records:
- Messages. The system prompt as input message 0, then each message and content block in order: text, images, thinking, tool calls and tool results, documents, and compaction summaries. Other content block types are recorded as their type and JSON, with base64 data replaced by a placeholder.
- Tool calls. Client tools (
tool_use), server tools such as web search, web fetch, and code execution (server_tool_use), and MCP connector tools (mcp_tool_use) are all recorded asmessage.tool_callson the output message. The tools available to the request, including tools added inline withtool_addition, are recorded inllm.tools. - Token usage. Prompt, completion, and total tokens, cache reads and writes, and thinking tokens as
llm.token_count.completion_details.reasoning. - Provider.
llm.providerisanthropic, or the cloud that hosts the model. See Trace Claude on Amazon Bedrock, Google Vertex AI, and Microsoft Foundry. - Response details in metadata. Details with no OpenInference attribute go to span metadata, alongside any metadata you set yourself:
messages.count_tokens (Python) and messages.countTokens (TypeScript), stable and beta, get a lightweight span with the token count response as its output.
Compaction calls report 0 for the top-level token counts, as the API does, so these spans show no cost. The tokens the compaction used are in the
usage_iterations metadata.Trace tool usage
The instrumentor traces eachmessages.create call automatically, including every tool call Claude requests. Server tools and MCP connector tools run on Anthropic’s side, so their calls appear on the LLM span with no extra code.
Client tools run in your code, and how you trace them depends on how you run the tool loop:
- TypeScript. Use
client.beta.messages.toolRunner()to run the loop. The instrumentor wraps each run in abeta.messages.tool_runnerCHAIN span, with an LLM span for each request and a TOOL span for each tool run, so you need no manual spans. - Python, or a loop you write yourself. Wrap the loop in a manual chain span and each tool execution in a manual tool span with the OpenTelemetry API. The auto LLM spans nest under your chain span automatically. See Combine auto and manual instrumentation for the pattern. The Python
tool_runnergets LLM spans but not the chain and tool spans, so wrap it the same way.
Expected output
get_weather tool span under it. In Python and Go the chain span is your weather-agent span. In TypeScript it is the tool runner’s beta.messages.tool_runner span.
Go SDK The auto middleware still emits an LLM span for each
Messages.New call, but it does not populate tool_use blocks as attributes on that span. The chain and tool spans are created manually with the OpenTelemetry API — threading the chain span’s ctx into each Messages.New call is what nests the auto LLM spans underneath it.Trace Claude on Amazon Bedrock, Google Vertex AI, and Microsoft Foundry
The Python and TypeScript instrumentors also trace the Anthropic SDK’s own clients for the clouds that host Claude, with the same setup as above.llm.provider records where the model ran:
The async versions of each Python client are traced too. If you call Claude on Bedrock through
boto3 instead, use the Amazon Bedrock instrumentor.
Mask sensitive data
The Python and TypeScript instrumentors respect theTraceConfig settings in Mask and redact data. Because span metadata isn’t masked by TraceConfig, the instrumentors apply the hide settings to the response details they put there:
citationsis left out when inputs, outputs, input messages, or output messages are hidden, because citation URLs and titles name the sources.- With input text or output text hidden, only each citation’s
cited_textis left out. - The
explanationinstop_detailsis left out when outputs, output messages, or output text are hidden.
Upgrading from earlier instrumentor versions
These changes affect dashboards, monitors, and evaluators built on spans from earlier versions:- TypeScript. The system prompt is now input message 0, so the other input messages move up one index when a system prompt is set. The system prompt is no longer part of
llm.invocation_parameters. - TypeScript. A streamed response’s
output.valueis now the rebuilt message as JSON (application/json), the same as a non-streaming response, instead of the concatenated text. - Python. Prompt, completion, and total token counts of 0 are now recorded instead of left out.
- Python and TypeScript. In an assistant message that mixes server and client tools, the server tool calls are now in
message.tool_callstoo, so a client tool call can have a higher index than before.
Troubleshooting
- No traces in Arize AX. Confirm
ARIZE_SPACE_IDandARIZE_API_KEYare set in the same shell that runs the example. Enable OpenTelemetry debug logs withexport OTEL_LOG_LEVEL=debugand re-run. - Anthropic spans missing but other spans present (Python).
AnthropicInstrumentor().instrument(...)must run before anyimport anthropicin the application. Make sureinstrumentation.pyis the first import in your entry point. - Each Claude call appears twice, with an
anthropic.messages.createspan under the LLM span. Recent Anthropic SDK versions emit their own spans. SetANTHROPIC_OPEN_TELEMETRY=falsebefore you create the client, as the setup above does, or passopen_telemetry=False(Python) oropenTelemetry: false(TypeScript) to the client. 401from Anthropic. VerifyANTHROPIC_API_KEYis set and has access to the model in the example. Swapclaude-sonnet-5-5for a model your key can call.- Go process exits before spans flush.
arize-otel-gouses a batched span processor by default. Thedefer tp.Shutdown(...)block inmain.gois what flushes the batch — without it, short-lived programs lose their last spans. PassSimpleProcessor: truetoarizeotel.Registerif you want synchronous export instead.