Skip to main content
Claude Managed Agents runs your agent loop on Anthropic’s servers and executes its tools in a sandbox that Anthropic hosts. The Claude Platform can export OpenTelemetry traces of each session, using the OpenTelemetry GenAI semantic conventions. Phoenix converts those spans to OpenInference when they arrive. You can then inspect every agent turn, model request, and tool use in a session, with prompts, responses, and token usage. OpenTelemetry export from the Claude API is now in public beta. Span names and attributes can change during the beta.
This page covers Anthropic’s hosted Claude Managed Agents product. For the Claude Agent SDK, see Claude Agent SDK for Python and Claude Agent SDK for TypeScript.
There are two complementary ways to send spans to Phoenix, and most applications use both:
  • 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
  • A running Phoenix instance with an OTLP/HTTP endpoint that Claude Platform can reach
  • The admin role in a Claude Console organization, to add a destination. With the developer role, you can view destinations
  • An ANTHROPIC_API_KEY from the Claude Console, in a workspace that sends spans to Phoenix

Launch Phoenix

No uv? pip install arize-phoenix && phoenix serve does the same thing. See Terminal setup for customization.
Phoenix serves its UI and OTLP HTTP on port 6006, and OTLP gRPC on port 4317. For a local instance that’s http://localhost:6006. Leave it running while you work.
Claude Platform sends spans from Anthropic’s infrastructure, so a local Phoenix server is not reachable unless you expose it with a public HTTPS tunnel. Plain localhost works for your application’s SDK spans only. For a deployed Phoenix instance or Phoenix Cloud, use its public base URL.
Pointing at a deployment with authentication enabled? Set PHOENIX_COLLECTOR_ENDPOINT to that deployment’s OTLP HTTP traces URL, for example https://your-phoenix.example.com/v1/traces, and PHOENIX_API_KEY to an API key from its Settings page. A local phoenix serve needs no key.

Export spans from the Claude Console

A destination tells the Claude API where to send the spans it creates. Use the Arize Phoenix destination to send Claude Platform spans to a Phoenix project:
Claude Console Add destination modal with Arize Phoenix selected, Phoenix URL, API key, project name, Full content mode, Workspaces setting, and Advanced settings size limit

Claude Console destination configured to export Claude Platform spans to Phoenix

  1. In the Claude Console, open the OpenTelemetry settings page of your organization and click Add destination.
  2. Set Provider to Arize.
  3. Set Product to Arize Phoenix.
  4. Set Phoenix URL to your Phoenix base URL, for example https://phoenix.example.com. Do not include /v1/traces; Claude Platform appends the per-signal path automatically.
  5. Set API key to a Phoenix API key for Phoenix Cloud or an authenticated self-hosted instance.
  6. Set Project name to the Phoenix project name, for example claude-managed-agents-example. The Console sends this as the destination’s x-project-name header.
  7. Set Content mode to Full content, so spans carry the system prompt, messages, and tool arguments as well as token counts. The default, Metadata only, sends only identifiers, timing, status, token counts, and the names and descriptions of your agents, tools, and MCP servers.
  8. Set Workspaces to the workspaces whose spans you want in Phoenix. All, the default, exports from every workspace in your organization. Selected exports from only the workspaces you choose, and All except exports from every workspace except the ones you choose. Then click Add destination.
  9. In the destination’s More actions menu, click Test. The Console shows whether the test span was delivered. In Phoenix, check that an anthropic.test span arrived in the project.
Claude Console destination details panel for Phoenix showing endpoint, Full content mode, Healthy delivery, one workspace, and the More actions menu with Test highlighted

The destination's More actions menu in the Claude Console, with Test highlighted

A destination exports every request made with its workspaces’ API keys, not just Managed Agents sessions. That includes Messages API requests from any other application or tool that uses those keys, with their prompts and responses in Full content mode. To send only your agent’s traffic, give it a workspace and API keys of its own. Workspaces defaults to All, so choose Selected unless you want spans from every workspace in your organization in Phoenix.
Each destination sends to one Phoenix project. To keep workspaces apart, for example production and staging, add one destination per project and select each destination’s workspaces. An organization can have up to 10 destinations, including disabled ones. An admin can also add a destination with Anthropic’s Admin API or CLI. The Admin API has no Arize Phoenix provider, so enter the endpoint and headers yourself: the endpoint is your Phoenix base URL, such as https://phoenix.example.com, and the headers are Authorization: Bearer <your-phoenix-api-key> and x-project-name: <your-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 Phoenix, 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.
Install or upgrade the Claude SDK to a version that emits spans. The SDK emits a span for each request and sends the trace context that joins the API’s spans to yours. With an older SDK, the API’s spans still reach Phoenix from the Console destination, in traces of their own.
Don’t also run the OpenInference Anthropic instrumentor on the same client. Both would trace each request, and every request would appear twice.

Configure credentials

Use the same project name here as the destination’s Project name, so the SDK’s spans and the API’s spans land in the same project. 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

Go and Java keep the tracer setup and the example in one file, with the setup at the top of 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 a fibonacci-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, Phoenix shows a span’s status as unset. Without a span kind, Phoenix shows a span’s kind as unknown.
Agents and environments are persistent and versioned. The example creates them on every run to stay self-contained. In your application, create them once, store their IDs, and pass the IDs to each sessions.create call.

Expected output

Verify in Phoenix

  1. Open Phoenix and select project claude-managed-agents-example.
  2. You should see a new trace within about a minute. The API’s spans can arrive after yours. The trace has a fibonacci-agent 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.
Phoenix trace view of a fibonacci-agent trace with status OK. The trace tree shows the fibonacci-agent root span, Sessions API request spans, an anthropic.session.turn span, anthropic.model_request spans, and an anthropic.tool_use bash span.

A Claude Managed Agents session in Phoenix, with the trace tree expanded

  1. If no traces appear, see Troubleshooting.
The Console’s Delivery column for your destination also shows Healthy once the API delivers its first spans to Phoenix.

What Phoenix captures

The SDK and the API mark their spans with gen_ai.* attributes, and Phoenix converts them to OpenInference attributes on ingestion. See Translating semantic conventions. No span shows a custom tool that your application runs without a tool runner, a multiagent or advisor tool, or a tool use that the permission policy or your application denied. Add your own TOOL span for a custom tool, as in the cookbook. Phoenix 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

  • Some Sessions API spans can show an unknown kind. The anthropic.agents.create, anthropic.environments.create, anthropic.sessions.events.send, and anthropic.sessions.events.stream spans don’t say what kind of operation they are, so Phoenix shows their kind as unknown. Your own spans don’t have this problem as long as they set a span kind.
  • Cache token counts aren’t shown. The spans report cache reads and writes as gen_ai.usage.cache_read.input_tokens and gen_ai.usage.cache_write.input_tokens, which Phoenix doesn’t map yet. Phoenix 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.
  • Session requests appear as LLM spans. The anthropic.sessions.create spans carry the agent’s model, so Phoenix classifies them as LLM spans, with zero tokens. They aren’t model calls. The model calls are the anthropic.model_request spans.
  • Messages API requests count tokens more than once. For a Managed Agents session, only the anthropic.model_request and anthropic.session.outcome_evaluation spans carry token usage, so trace totals are correct. For a Messages API request, the usage is on the SDK’s anthropic.messages.create span, the API’s span of the same name, and the API’s anthropic.model_request children, 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 root span 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.content attribute, which Phoenix doesn’t map to the span output yet. Read it from the span’s attributes. On the SDK’s anthropic.custom_tool_use spans, tool.parameters also 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.truncated to true. Change the destination’s limit under Advanced settings, and the SDK’s with ANTHROPIC_OPEN_TELEMETRY_TRACES_MAX_CONTENT_BYTES. See Anthropic’s Content limits.

Troubleshooting

  • No traces at all. Check that PHOENIX_COLLECTOR_ENDPOINT, PHOENIX_API_KEY, and PHOENIX_PROJECT_NAME are set in the shell that runs the example. Register the tracer provider before the first Claude SDK call, and check that ANTHROPIC_OPEN_TELEMETRY isn’t false. Set OTEL_LOG_LEVEL=debug to see export errors.
  • The destination shows Failing. Hold the pointer over Failing to see the error. A 401 or 403 usually means the API key is missing or wrong. A 404 usually means the destination was pointed at /v1/traces; use the Phoenix base URL because Claude Platform appends the OTLP signal path itself. A rejection that mentions project routing means the destination has no project name. If you change the destination’s Phoenix URL or authentication, 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 matches PHOENIX_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 TypeScript, import your instrumentation.ts before creating the Claude client, and don’t pass global: false to register(). If you also use @opentelemetry/instrumentation-undici, which @opentelemetry/auto-instrumentations-node includes, create the client with openTelemetry: { propagation: false }: that package adds a second traceparent header, which makes the trace context invalid. In Go and Java, register the W3C trace context propagator as the examples do. If your application uses another propagator, such as B3, add the W3C trace context propagator too. In Java, also build the OpenTelemetry SDK with buildAndRegisterGlobal(), and check that no other dependency pins opentelemetry-api below 1.57.0. Requests to Claude Platform on AWS always start traces of their own.
  • Java spans are missing when the program exits. The BatchSpanProcessor exports in the background. Keep the forceFlush and shutdown calls at the end of main, or the JVM can exit before it delivers them.
  • Each request appears twice. Each request has an SDK span and, inside it, an API span with the same name, as listed in What Phoenix 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=content for 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.

Resources

Export OpenTelemetry traces from the Claude API

Claude Managed Agents documentation

Trace and Evaluate Claude Managed Agents

Translating semantic conventions