Skip to main content
Send traces from claude-agent-sdk-python to Tessary and tag each query() call with a call site. The SDK emits no OpenTelemetry spans of its own, so you open one by hand around query() and fill in its attributes from the messages the call yields.

Prerequisites

  • A running Tessary instance, with the Endpoint and Bearer Token from its connect gate. See Instrument your agent.
  • ANTHROPIC_API_KEY set in the environment.
  • Python 3.10 or later, with claude-agent-sdk, opentelemetry-sdk, and opentelemetry-exporter-otlp-proto-http installed.

Add the exporter

Tessary receives spans over OTLP (OpenTelemetry Protocol). Point the exporter at your Tessary instance with environment variables:
Replace the host with your Tessary origin and <token> with the Bearer Token value from the connect gate. Then register an exporter that reads those variables. OTLPSpanExporter() with no arguments picks them up:
If your application already configures a TracerProvider, skip this block. Add the Tessary exporter to the existing provider as described in Configure an exporter, and use its tracer. A span opened on a second provider that has no Tessary exporter is never sent.

Tag the query() call

The SDK runs the Claude Code CLI as a subprocess, so each query() call is a CLI agent call site. The call-site tag explains why it follows the same tagging rules as an in-process SDK call. Open a span around query(), set tessary.call_site.id as a literal, and fill in the fields Span requirements marks required. The SDK reports the model on each AssistantMessage and the usage on the final ResultMessage, so read both from the messages instead of setting them up front:
The cache token attributes matter here: the Claude Code CLI sends a large system prompt, and without them Tessary prices cached input as full-price input.
Keep tessary.call_site.id a literal string, never an f-string or a variable. The call-site tag explains why: a computed value cannot be traced back to the code that produced it.

Verify it works

Run the example. It prints each message the SDK yields, including the assistant’s reply and a final ResultMessage with usage and cost. Output is trimmed here, and your model, token counts, and cost will differ:
The connect gate opens once the tagged span arrives, with 1 trace and the support.answer call site. On a project already past the gate, the call site appears in the project instead. If a span arrives without the tag, What done looks like describes the states you see instead.

The call-site tag

What counts as a call site, and the four non-negotiable rules for the id.

Span requirements

Every field Tessary reads off a span, beyond what this page sets.

Configure an exporter

The in-code and collector forms, and how to add Tessary to an exporter setup you already run.