# 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
