Skip to main content
Anthropic provides the Claude family of large language models. Arize AX captures every Anthropic SDK call — prompts, responses, tool calls (including server tools and the MCP connector), thinking, and token usage — via the OpenInference instrumentors for Python, JavaScript / TypeScript, and Go, so you can debug, evaluate, and monitor Claude-powered applications.
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-anthropic 3.1.0 or later (Python, with anthropic 1.8.0 or later), or @arizeai/openinference-instrumentation-anthropic 1.0.0 or later (TypeScript)
  • An Arize AX account (sign up)
  • An ANTHROPIC_API_KEY from the Anthropic Console

Launch Arize AX

  1. Sign in to your Arize AX account.
  2. From Space Settings, copy your Space ID and API Key. You will set them as ARIZE_SPACE_ID and ARIZE_API_KEY below.

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

  1. Open your Arize AX space and select project anthropic-tracing-example.
  2. You should see a new trace within ~30 seconds containing an LLM span — messages.create for the Python SDK, Anthropic Messages for the Node.js SDK, or anthropic.messages.create for the Go SDK — with the prompt, response, and token usage attached. Other Python methods get spans named after the method, such as messages.stream, messages.parse, messages.count_tokens, and beta.messages.create. In Node.js, every messages.create and messages.stream call is an Anthropic Messages span, stable or beta, and token counting is an Anthropic Count Tokens span.
  3. 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.
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 as message.tool_calls on the output message. The tools available to the request, including tools added inline with tool_addition, are recorded in llm.tools.
  • Token usage. Prompt, completion, and total tokens, cache reads and writes, and thinking tokens as llm.token_count.completion_details.reasoning.
  • Provider. llm.provider is anthropic, 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 each messages.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 a beta.messages.tool_runner CHAIN 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_runner gets LLM spans but not the chain and tool spans, so wrap it the same way.

Expected output

The trace tree in Arize AX is a chain span with two LLM spans and one 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 the TraceConfig 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:
  • citations is 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_text is left out.
  • The explanation in stop_details is left out when outputs, output messages, or output text are hidden.
Request parameters are recorded in llm.invocation_parameters, which the hide settings don’t mask. If you use the MCP connector, each server’s authorization_token in mcp_servers is recorded there. In Python, so are any extra_headers, which are also part of input.value. Keep credentials out of these parameters, or remove them with a span processor before export.

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.value is 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_calls too, so a client tool call can have a higher index than before.

Troubleshooting

  • No traces in Arize AX. Confirm ARIZE_SPACE_ID and ARIZE_API_KEY are set in the same shell that runs the example. Enable OpenTelemetry debug logs with export OTEL_LOG_LEVEL=debug and re-run.
  • Anthropic spans missing but other spans present (Python). AnthropicInstrumentor().instrument(...) must run before any import anthropic in the application. Make sure instrumentation.py is the first import in your entry point.
  • Each Claude call appears twice, with an anthropic.messages.create span under the LLM span. Recent Anthropic SDK versions emit their own spans. Set ANTHROPIC_OPEN_TELEMETRY=false before you create the client, as the setup above does, or pass open_telemetry=False (Python) or openTelemetry: false (TypeScript) to the client.
  • 401 from Anthropic. Verify ANTHROPIC_API_KEY is set and has access to the model in the example. Swap claude-sonnet-5-5 for a model your key can call.
  • Go process exits before spans flush. arize-otel-go uses a batched span processor by default. The defer tp.Shutdown(...) block in main.go is what flushes the batch — without it, short-lived programs lose their last spans. Pass SimpleProcessor: true to arizeotel.Register if you want synchronous export instead.

Resources

Anthropic Documentation

OpenInference Anthropic Instrumentor (Python)

OpenInference Anthropic Instrumentor (JavaScript / TypeScript)

Anthropic Tracing Example (messages.create)

Anthropic Tracing Example (tool calling)

Anthropic Go SDK

OpenInference Anthropic Instrumentor (Go)