# Claude Agent SDK

Claude Agent SDK is Anthropic's open-source framework for building tool-using AI agents, including native support for MCP (Model Context Protocol).

This guide shows how to capture traces from Claude Agent SDK applications and send them to InteractiveAI.

### Prerequisites

* InteractiveAI account with API credentials
* Anthropic API key

***

### Installation

```bash
pip install interactiveai claude-agent-sdk
```

***

### Configuration

Set your API credentials as environment variables:

```python
import os

os.environ["INTERACTIVEAI_PUBLIC_KEY"] = "pk-..."
os.environ["INTERACTIVEAI_SECRET_KEY"] = "sk-..."
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
```

Initialize the client and verify connectivity:

```python
from interactiveai import Interactive
import os

interactiveai = Interactive(
    public_key=os.environ["INTERACTIVEAI_PUBLIC_KEY"],
    secret_key=os.environ["INTERACTIVEAI_SECRET_KEY"],
)

if interactiveai.auth_check():
    print("Connection established")
else:
    print("Authentication failed - verify credentials")
```

***

### Running an Agent with Tracing

Wrap your agent code with `start_as_current_span` to capture the execution:

```python
import os
from interactiveai import Interactive
from claude_agent_sdk import (
    ClaudeAgentOptions,
    ClaudeSDKClient,
    tool,
    create_sdk_mcp_server,
)
from typing import Any

interactiveai = Interactive(
    public_key=os.environ["INTERACTIVEAI_PUBLIC_KEY"],
    secret_key=os.environ["INTERACTIVEAI_SECRET_KEY"],
)


@tool(
    "get_stock_price",
    "Gets the current stock price for a given ticker symbol",
    {"ticker": str},
)
async def get_stock_price(args: dict[str, Any]) -> dict[str, Any]:
    """Simulated stock price lookup tool."""
    ticker = args["ticker"].upper()
    stock_data = {
        "AAPL": 187.50,
        "GOOGL": 141.25,
        "MSFT": 378.90,
        "AMZN": 178.30,
    }
    price = stock_data.get(ticker, None)
    if price:
        return {"content": [{"type": "text", "text": f"{ticker} is currently trading at ${price}"}]}
    return {"content": [{"type": "text", "text": f"Stock data not available for {ticker}"}]}


async def main():
    with interactiveai.start_as_current_span(name="claude-stock-agent") as span:
        
        stock_server = create_sdk_mcp_server(
            name="stocks",
            version="1.0.0",
            tools=[get_stock_price],
        )

        options = ClaudeAgentOptions(
            model="claude-sonnet-4-5-20250929",
            system_prompt="You are a helpful financial assistant.",
            mcp_servers={"stocks": stock_server},
            allowed_tools=["mcp__stocks__get_stock_price"],
        )

        query = "What are the current prices for Apple and Microsoft stock?"
        final_result = ""

        async with ClaudeSDKClient(options=options) as sdk_client:
            await sdk_client.query(query)

            async for message in sdk_client.receive_response():
                if hasattr(message, 'result') and message.result:
                    final_result = message.result

        span.update(
            input={"query": query},
            output={"response": final_result}
        )

    interactiveai.flush()


await main()
```

***

### Enriching Traces with Context

Add user tracking, session IDs, and metadata for filtering and analysis:

<pre class="language-python"><code class="lang-python">import os
from interactiveai import Interactive
from typing import Any
from claude_agent_sdk import (
    ClaudeAgentOptions,
    ClaudeSDKClient,
    tool,
    create_sdk_mcp_server,
)

interactiveai = Interactive(
    public_key=os.environ["INTERACTIVEAI_PUBLIC_KEY"],
    secret_key=os.environ["INTERACTIVEAI_SECRET_KEY"],
)

@tool(
    "compare_stocks",
    "Compares performance of two stocks",
    {"ticker1": str, "ticker2": str},
)
async def compare_stocks(args: dict[str, Any]) -> dict[str, Any]:
    """Compares two stocks by price and market cap."""
    stock_data = {
        "AAPL": {"price": 187.50, "market_cap": "2.9T", "pe_ratio": 29.5},
        "GOOGL": {"price": 141.25, "market_cap": "1.8T", "pe_ratio": 25.2},
        "MSFT": {"price": 378.90, "market_cap": "2.8T", "pe_ratio": 35.1},
        "AMZN": {"price": 178.30, "market_cap": "1.9T", "pe_ratio": 42.3},
    }
    
    t1 = args["ticker1"].upper()
    t2 = args["ticker2"].upper()
    
    if t1 not in stock_data or t2 not in stock_data:
        return {"content": [{"type": "text", "text": "One or both tickers not found."}]}
    
    s1, s2 = stock_data[t1], stock_data[t2]
    comparison = f"""
{t1}: ${s1['price']} | Market Cap: {s1['market_cap']} | P/E: {s1['pe_ratio']}
{t2}: ${s2['price']} | Market Cap: {s2['market_cap']} | P/E: {s2['pe_ratio']}
"""
    return {"content": [{"type": "text", "text": comparison.strip()}]}


async def main():
    with interactiveai.start_as_current_span(name="claude-stock-comparison") as span:
        
<strong>        interactiveai.update_current_trace(
</strong><strong>            user_id="user_claude_agent",
</strong><strong>            session_id="session_claude_agent",
</strong><strong>            tags=["claude-agent-sdk", "stock-analysis"],
</strong><strong>            metadata={"environment": "production"}
</strong><strong>        )
</strong>
        stock_server = create_sdk_mcp_server(
            name="stocks",
            version="1.0.0",
            tools=[compare_stocks],
        )

        options = ClaudeAgentOptions(
            model="claude-sonnet-4-5-20250929",
            system_prompt="You are a financial analyst assistant.",
            mcp_servers={"stocks": stock_server},
            allowed_tools=["mcp__stocks__compare_stocks"],
        )

        query = "Compare Apple and Microsoft stocks for me."
        final_result = ""

        async with ClaudeSDKClient(options=options) as sdk_client:
            await sdk_client.query(query)

            async for message in sdk_client.receive_response():
                if hasattr(message, 'result') and message.result:
                    final_result = message.result

        span.update(
            input={"query": query},
            output={"response": final_result}
        )

    interactiveai.flush()


await main()
</code></pre>

***

### Trace Visibility

After execution, the InteractiveAI dashboard displays:

* Agent execution with custom span name
* Input query and final response
* User and session context for filtering
* Tags and metadata for organization
* Latency metrics


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.interactive.ai/integrations/ai-frameworks/claude-agent-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
