Claude Agent SDK (tracing)

The Claude Agent SDK (claude-agent-sdk) lets you run Claude-powered agent sessions with tool use, multi-turn reasoning, and streamed events. Respan gives you full observability over every SDK run, streamed response, and tool call — and gateway routing for Claude models through the Anthropic-compatible Respan endpoint.

Create an account at platform.respan.ai and grab an API key.

Run npx @respan/cli setup to set up with your coding agent.

See Claude Agent SDK gateway setup to route this integration through the Respan gateway.

Setup

1

Install packages

pip install claude-agent-sdk respan-ai respan-instrumentation-claude-agent-sdk
2

Set environment variables

export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY"
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"

ANTHROPIC_API_KEY is used for Claude requests. RESPAN_API_KEY is used to export traces to Respan.

3

Initialize and run

import asyncio
import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage
from respan import Respan
from respan_instrumentation_claude_agent_sdk import ClaudeAgentSDKInstrumentor
respan = Respan(
instrumentations=[ClaudeAgentSDKInstrumentor(capture_content=True)],
)
async def main():
async for message in claude_agent_sdk.query(
prompt="Explain tracing in one sentence.",
options=ClaudeAgentOptions(model="sonnet", max_turns=1),
):
if isinstance(message, ResultMessage):
print(message.result)
asyncio.run(main())
4

View your trace

Open the Traces page to see your workflow with Claude Agent SDK spans, streamed responses, and tool activity.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate (e.g. ClaudeAgentSDKInstrumentor(capture_content=True)).
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag (e.g. "production").

ClaudeAgentSDKInstrumentor options

ParameterTypeDefaultDescription
agent_namestr | NoneNoneOverride the agent name attached to emitted Claude Agent SDK spans.
capture_contentboolFalseInclude prompt, response, and tool content in telemetry. Set to True when you want full dashboard payload visibility.

Attributes

In Respan()

Set defaults at initialization — these apply to all spans.

from respan import Respan
from respan_instrumentation_claude_agent_sdk import ClaudeAgentSDKInstrumentor
respan = Respan(
instrumentations=[ClaudeAgentSDKInstrumentor(capture_content=True)],
customer_identifier="user_123",
metadata={"service": "claude-agent-api", "version": "1.0.0"},
)

With propagate_attributes

Override per-request using a context scope.

import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage
from respan import Respan, propagate_attributes
from respan_instrumentation_claude_agent_sdk import ClaudeAgentSDKInstrumentor
respan = Respan(
instrumentations=[ClaudeAgentSDKInstrumentor(capture_content=True)],
)
async def handle_request(user_id: str, prompt: str):
with propagate_attributes(
customer_identifier=user_id,
thread_identifier="conv_abc_123",
metadata={"plan": "pro"},
):
async for message in claude_agent_sdk.query(
prompt=prompt,
options=ClaudeAgentOptions(model="sonnet", max_turns=1),
):
if isinstance(message, ResultMessage):
print(message.result)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom key-value pairs. Merged with default metadata.

Decorators (optional)

Decorators are not required. All Claude Agent SDK runs and streamed responses are auto-traced by the instrumentor. Use @workflow and @task (Python) or withWorkflow and withTask (TypeScript) to add structure when you want to group related agent runs into a named workflow with nested tasks.

import asyncio
import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage
from respan import Respan, task, workflow
from respan_instrumentation_claude_agent_sdk import ClaudeAgentSDKInstrumentor
respan = Respan(
instrumentations=[ClaudeAgentSDKInstrumentor(capture_content=True)],
)
@task(name="draft_answer")
async def draft_answer(prompt: str) -> str:
async for message in claude_agent_sdk.query(
prompt=prompt,
options=ClaudeAgentOptions(model="sonnet", max_turns=1),
):
if isinstance(message, ResultMessage):
return message.result
return ""
@workflow(name="customer_support_flow")
async def handle_ticket():
summary = await draft_answer("Summarize a billing issue in one sentence.")
print(summary)
asyncio.run(handle_ticket())

Examples

Basic query

Run a single Claude Agent SDK query and print the final result.

import asyncio
import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage
async def main():
async for message in claude_agent_sdk.query(
prompt="Say hello in three languages.",
options=ClaudeAgentOptions(model="sonnet", max_turns=1),
):
if isinstance(message, ResultMessage):
print(message.result)
asyncio.run(main())

Streaming message flow

The SDK emits multiple message objects during a run. You can inspect the flow while Respan traces the full session.

import asyncio
import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions
async def main():
message_types = []
async for message in claude_agent_sdk.query(
prompt="Explain recursion in one short paragraph.",
options=ClaudeAgentOptions(model="sonnet", max_turns=1),
):
message_types.append(type(message).__name__)
print(" -> ".join(message_types))
asyncio.run(main())