Claude Agent SDK
Use Confident AI for LLM observability and evals for Claude Agent SDK
Overview
Claude Agent SDK lets you build applications using Claude Code's agent capabilities. confident-trace traces your Python application and configures the SDK's Claude Code subprocess for OpenTelemetry export.
| Runtime | Requirements | Setup |
|---|---|---|
| Python | Python 3.10+, claude-agent-sdk, and Claude authentication | Call init() and wrap the query in span() |
| TypeScript | Not supported by this confident-trace integration | — |
Auto-Instrument
Install Dependencies
Run the following command to install the required packages:
pip install confident-trace claude-agent-sdkSetup Confident AI Key
Get your Confident AI Project API key and set it as an environment variable, or pass it to
init()directly. Configure Claude authentication for your application; this example uses an Anthropic API key.export CONFIDENT_API_KEY="<your-confident-api-key>" export ANTHROPIC_API_KEY="<your-anthropic-key>"from confident_trace import init init(api_key="<your-confident-api-key>")Instrument Claude Agent SDK
Call
init()once at startup and create a span around the query. The adapter respects the explicit telemetry disable switch inClaudeAgentOptions.env; it does not create the outer invocation span automatically.main.py import asyncio from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query from confident_trace import init, shutdown, span async def main(): init() try: options = ClaudeAgentOptions( max_turns=3, env={"CLAUDE_CODE_ENABLE_TELEMETRY": "0"}, ) with span("claude.invocation"): async for message in query( prompt="Explain OpenTelemetry in one sentence.", options=options, ): if isinstance(message, ResultMessage): print(message.result) finally: shutdown() asyncio.run(main())Run your agent
Execute the script to send the invocation span to Confident AI:
python main.pyDone ✅. Open the Observatory in your Confident AI project to inspect the Python invocation span.
What Gets Captured
With the setup above, Confident AI captures the application boundary around your Claude query:
- Invocation lifecycle — the span name, timing, and error status for exceptions that escape the span scope.
- Trace properties — tags, metadata, user IDs, and thread IDs you attach to the Python trace.
- Custom spans — additional application spans created within the invocation scope.
The wrapper does not automatically capture the prompt, response, model calls, tool calls, or token usage inside Claude Code. You can add application input and output with span properties. Disabling child telemetry also disables that child's native metrics and logs; Python tracing remains enabled.
Experimental Native Tracing
To try native Claude tracing, remove the CLAUDE_CODE_ENABLE_TELEMETRY override from the example. Call init() before query() or before connecting a ClaudeSDKClient. The integration configures the default subprocess transport with the resolved OTLP trace endpoint, authentication headers, protocol, and Claude's telemetry switches.
- Active W3C context is propagated when the subprocess connects, but a connected native trace is not guaranteed. A long-lived
ClaudeSDKClientinherits context at connection time, rather than a fresh parent for each query. - Consume
query()through the end of its iterator, even after receivingResultMessage. Pythonflush()andshutdown()do not flush the child process. Fully consuming a query is necessary, but does not guarantee native span delivery. - Explicit exporter settings in
ClaudeAgentOptions.envtake ownership of the child's connection configuration. Supply the destination and authentication together; Confident AI credentials are not injected into that override. Custom transports are left untouched. - Confident trace metadata, thread properties, and content controls are not automatically applied to child-process spans.
See the confident-trace native tracing investigation for the observed limitations. Missing or disconnected native spans cannot be repaired by increasing Python flush timeouts.
Set Trace Span Properties
Use a trace context to add properties before creating the invocation span. The trace context creates no extra span; the Python invocation span inherits its properties.
from confident_trace import span, trace_context
# Inside your async application, after init().
with trace_context(
tags=["support"],
metadata={"release": "2026-09"},
user_id="user-42",
):
with span("claude.invocation"):
async for message in query(prompt="Explain OpenTelemetry.", options=options):
passUse the options from the setup above to keep child telemetry disabled. See trace context for every supported trace property and update behavior.
Instrumenting Multi-Turn
Use turn() to create a Python trace for each conversational turn. Reuse the same thread ID on later turns to group them into one conversation in Confident AI. This groups traces; it does not manage Claude's session history.
from confident_trace import turn
# Inside your async application, after init().
with turn("support-turn", thread_id="chat-42"):
async for message in query(prompt="Explain OpenTelemetry.", options=options):
passSee threads for thread I/O, turn IDs, and user IDs.
Disable Claude Agent SDK Instrumentation
The integration identifier is "claude_agent_sdk". Pass init() a list of identifiers to enable only those integrations; omit this identifier to disable the subprocess adapter. An empty list disables all automatic instrumentation while leaving custom Python spans available:
from confident_trace import init
init(instrumentations=())This stops Confident AI from configuring future subprocess transports. It does not disable telemetry on an already connected child. To explicitly disable Claude's native telemetry, use ClaudeAgentOptions(env={"CLAUDE_CODE_ENABLE_TELEMETRY": "0"}) when creating the child.
Next Steps
Custom Application Spans
Add input, output, and application spans around your Claude queries.
Threads
Group invocation traces from the same conversation into a thread.
Last updated on