> ## Documentation Index
> Fetch the complete documentation index at: https://docs.honeyhive.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Agent SDK

> Add HoneyHive observability to your Claude Agent SDK applications

[Claude Agent SDK](https://docs.anthropic.com/en/docs/claude-agent-sdk) is Anthropic's Python SDK for building AI agents powered by Claude Code. It gives agents access to built-in tools like Bash, Read, Write, and Glob for autonomous task execution.

HoneyHive integrates with the Claude Agent SDK via the OpenInference instrumentor, automatically capturing agent runs, tool calls, and multi-turn conversations.

## Quick Start

<Tip>
  **Add HoneyHive tracing in just 4 lines of code.** Initialize the tracer and instrumentor, and all agent activity is automatically traced.
</Tip>

<Tip>
  To see where to initialize the tracer for your environment, including AWS Lambda and long-running servers, see [Tracer Initialization](/v2/tracing/tracer-initialization).
</Tip>

```bash theme={null}
pip install honeyhive openinference-instrumentation-claude-agent-sdk claude-agent-sdk
```

```python theme={null}
import os
from honeyhive import HoneyHiveTracer
from openinference.instrumentation.claude_agent_sdk import ClaudeAgentSDKInstrumentor

tracer = HoneyHiveTracer.init(
    api_key=os.getenv("HH_API_KEY"),
    project=os.getenv("HH_PROJECT"),
)
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)

# Import claude_agent_sdk AFTER this setup block (see examples below)
# Call tracer.force_flush() before your process exits
```

## Compatibility

| Requirement      | Version |
| ---------------- | ------- |
| Python           | 3.10+   |
| claude-agent-sdk | 0.1.45+ |

## What Gets Traced

The instrumentor automatically captures:

* **Agent runs** - Every agent invocation with inputs and outputs
* **Tool executions** - Built-in tool calls (Bash, Read, Write, Glob) with arguments and results
* **Multi-turn conversations** - Session continuity across turns with `ClaudeSDKClient`
* **Token usage and cost** - Model token counts and cost per request

No manual instrumentation required.

***

## Example: Single Query with Tools

The `query()` function runs a one-off agent session. The agent can use built-in tools to complete tasks autonomously:

```python theme={null}
import asyncio
import os
from openinference.instrumentation.claude_agent_sdk import ClaudeAgentSDKInstrumentor
from honeyhive import HoneyHiveTracer

tracer = HoneyHiveTracer.init(
    api_key=os.getenv("HH_API_KEY"),
    project=os.getenv("HH_PROJECT"),
)
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)

# Import AFTER instrument() so references resolve to the patched versions
from claude_agent_sdk import AssistantMessage, ClaudeAgentOptions, TextBlock, query

async def main():
    async for message in query(
        prompt="Read the file config.json and summarize its contents.",
        options=ClaudeAgentOptions(
            system_prompt="You are a helpful assistant. Complete tasks concisely.",
            allowed_tools=["Read"],
            max_turns=3,
            permission_mode="bypassPermissions",
        ),
    ):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)

    tracer.force_flush()

asyncio.run(main())
```

<Note>
  `permission_mode="bypassPermissions"` allows unrestricted tool use without interactive prompts. Use only in sandboxed or non-interactive environments.
</Note>

***

## Example: Multi-Turn Conversation

`ClaudeSDKClient` maintains session continuity across multiple turns. The agent remembers context from previous interactions:

```python theme={null}
import asyncio
import os
from openinference.instrumentation.claude_agent_sdk import ClaudeAgentSDKInstrumentor
from honeyhive import HoneyHiveTracer

tracer = HoneyHiveTracer.init(
    api_key=os.getenv("HH_API_KEY"),
    project=os.getenv("HH_PROJECT"),
)
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)

# Import AFTER instrument() so references resolve to the patched versions
from claude_agent_sdk import (
    AssistantMessage,
    ClaudeAgentOptions,
    ClaudeSDKClient,
    TextBlock,
)

async def main():
    client = ClaudeSDKClient(
        options=ClaudeAgentOptions(
            system_prompt="You are a customer support agent. Keep responses concise.",
            allowed_tools=["Read"],
            max_turns=3,
            permission_mode="bypassPermissions",
        )
    )

    await client.connect()
    try:
        # Turn 1
        await client.query(prompt="Read orders.json and tell me the status of ORD-1002.")
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(block.text)

        # Turn 2 - agent remembers context from Turn 1
        await client.query(prompt="What about ORD-1003? Is it delayed?")
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(block.text)
    finally:
        await client.disconnect()
        tracer.force_flush()

asyncio.run(main())
```

In HoneyHive, you'll see each turn as a separate agent span with tool calls nested underneath.

***

## Troubleshooting

### Traces not appearing

1. **Check environment variables** - Ensure `HH_API_KEY` and `HH_PROJECT` are set
2. **Pass the tracer provider** - The instrumentor must receive `tracer_provider=tracer.provider`:

```python theme={null}
from honeyhive import HoneyHiveTracer
from openinference.instrumentation.claude_agent_sdk import ClaudeAgentSDKInstrumentor

tracer = HoneyHiveTracer.init(project="your-project")

# Correct - pass tracer_provider
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)

# Wrong - missing tracer_provider
ClaudeAgentSDKInstrumentor().instrument()
```

3. **Import after instrumenting** - Import `claude_agent_sdk` *after* calling `instrument()`. The instrumentor patches module-level functions, so importing before patching captures the original unpatched references:

```python theme={null}
# Correct - import after instrument()
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)
from claude_agent_sdk import query

# Wrong - import before instrument()
from claude_agent_sdk import query
ClaudeAgentSDKInstrumentor().instrument(tracer_provider=tracer.provider)
```

4. **Flush before exit** - Call `tracer.force_flush()` before your process exits. Without this, buffered spans may be silently dropped in short-lived scripts:

```python theme={null}
async def main():
    # ... your agent code ...
    tracer.force_flush()

asyncio.run(main())
```

5. **Check Anthropic credentials** - Ensure `ANTHROPIC_API_KEY` is set

***

## Related

<CardGroup cols={2}>
  <Card title="Enrich Your Traces" icon="sparkles" href="/v2/tutorials/enriching-traces">
    Add user IDs and custom metadata to Claude Agent SDK traces
  </Card>

  <Card title="Custom Spans" icon="code" href="/v2/tracing/custom-spans">
    Create spans for business logic around agent calls
  </Card>

  <Card title="Distributed Tracing" icon="share-nodes" href="/v2/tutorials/distributed-tracing">
    Trace agents across service boundaries
  </Card>
</CardGroup>

***

## Resources

* [Claude Agent SDK Documentation](https://docs.anthropic.com/en/docs/claude-agent-sdk)
* [OpenInference Claude Agent SDK Instrumentor](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-claude-agent-sdk)
