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

# Claude SDK | AI Router & Observability

> Route Anthropic SDK calls through the orq.ai AI Router. Access fallbacks, caching, load balancing, and cost tracking for all Claude models.

<CardGroup cols={2}>
  <Card title="Observability" icon="chart-line" href="#observability">
    Instrument your agents with OpenTelemetry using the SDK's hooks system to capture traces for every agent turn and tool use.
  </Card>

  <Card title={<>AI Router &nbsp;<Badge>Beta</Badge></>} icon="arrow-right-arrow-left" href="#ai-router">
    Route your Claude calls through the **AI Router** with a single base URL change. Zero vendor lock-in: always run on the best model at the lowest cost for your use case.
  </Card>
</CardGroup>

## Observability

### Overview

The Claude Agent SDK (`claude-code-sdk`) drives the Claude CLI as a programmable agent supporting multi-turn conversations, tool use, and MCP servers. Use the SDK's built-in `hooks` system to attach OpenTelemetry instrumentation at key execution points. Every tool invocation becomes a span, and the full agent workflow is captured as a trace in **orq.ai** without modifying your agent logic.

### Key Benefits

<CardGroup cols={2}>
  <Card title="Full Agent Visibility" icon="chart-line">
    Track every agent turn, tool use, and LLM call with detailed traces and analytics
  </Card>

  <Card title="Zero Code Changes" icon="wand-magic-sparkles">
    Attach observability through hooks without modifying your agent logic
  </Card>

  <Card title="Cost Tracking" icon="chart-pie">
    Real-time cost and token usage per agent run synced to Orq.ai
  </Card>

  <Card title="Tool Inspection" icon="wrench">
    Inspect every tool input and output with full execution context
  </Card>
</CardGroup>

### Prerequisites

* An Orq.ai account and [API Key](/docs/administer/api-keys)
* Python 3.10 or higher
* [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code/getting-started) installed and authenticated

<Info>
  To set up your API key, see [API keys & Endpoints](/docs/administer/api-keys).
</Info>

### Install Dependencies

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install claude-code-sdk \
            opentelemetry-sdk opentelemetry-exporter-otlp
```

### Configuration

Set up the OTel tracer provider to export spans to Orq.ai:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry import trace

tracer_provider = TracerProvider()
tracer_provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://api.orq.ai/v2/otel/v1/traces",
            headers={"Authorization": f"Bearer {os.environ['ORQ_API_KEY']}"},
        )
    )
)
trace.set_tracer_provider(tracer_provider)
tracer = trace.get_tracer(__name__)
```

### Basic Example

Define a `PostToolUse` hook to create a span for each tool call, then wrap the `query()` call in a root workflow span:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import asyncio
import os
from typing import Any
from claude_code_sdk import (
    query,
    ClaudeCodeOptions,
    HookMatcher,
    HookContext,
    AssistantMessage,
    TextBlock,
    ResultMessage,
)
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry import trace

tracer_provider = TracerProvider()
tracer_provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://api.orq.ai/v2/otel/v1/traces",
            headers={"Authorization": f"Bearer {os.environ['ORQ_API_KEY']}"},
        )
    )
)
trace.set_tracer_provider(tracer_provider)
tracer = trace.get_tracer(__name__)


async def post_tool_use_hook(data: dict[str, Any], tool_name: str | None, _ctx: HookContext):
    with tracer.start_as_current_span(f"tool.{tool_name or 'unknown'}") as span:
        span.set_attribute("tool.name", tool_name or "unknown")
        if "input" in data:
            span.set_attribute("tool.input", str(data["input"])[:500])
        if "output" in data:
            span.set_attribute("tool.output", str(data["output"])[:500])
    return None


async def main():
    options = ClaudeCodeOptions(
        model="sonnet",
        system_prompt="You are a helpful coding assistant.",
        max_turns=3,
        allowed_tools=["Read", "Bash"],
        hooks={
            "PostToolUse": [
                HookMatcher(matcher=None, hooks=[post_tool_use_hook])
            ]
        },
    )

    prompt = "What Python version is installed on this system?"
    print(f"User: {prompt}\n")

    with tracer.start_as_current_span("agent-workflow") as span:
        span.set_attribute("agent.prompt", prompt)

        async for message in query(prompt=prompt, options=options):
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Assistant: {block.text}")
            elif isinstance(message, ResultMessage):
                span.set_attribute("agent.total_cost_usd", message.total_cost_usd or 0)
                span.set_attribute("agent.num_turns", message.num_turns)
                print(f"\nCost: ${message.total_cost_usd or 0:.6f} | Turns: {message.num_turns}")

    tracer_provider.force_flush()
    print("\nTraces exported to orq.ai. View them at https://my.orq.ai")


asyncio.run(main())
```

### View Traces

View your traces in the [AI Studio](/docs/observability/overview) in the **Traces** tab.

<Info>
  Visit your [AI Studio](https://my.orq.ai) to view real-time analytics and traces.
</Info>

## AI Router

<Warning>
  This feature is in Beta. Traces are not supported while using the AI Router with the Claude Agent SDK.
</Warning>

### Overview

The Anthropic SDK is the native client for Claude models. Connect it to **Orq.ai**'s **AI Router** with a single `base_url` change and no modifications to your existing agent logic.

### Install

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install anthropic
```

### Configuration

Set `base_url` to the **AI Router** endpoint and authenticate with your **Orq.ai** API key:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["ORQ_API_KEY"],
    base_url="https://my.orq.ai/v3/router/",
)
```

<Tip>Set `base_url` to `https://my.orq.ai/v3/router/` </Tip>

### Basic Example

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["ORQ_API_KEY"],
    base_url="https://my.orq.ai/v3/router/",
)

message = client.messages.create(
    model="anthropic/claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explain the orq.ai AI Router in one paragraph."}],
)

print(message.content[0].text)
```

### Streaming

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["ORQ_API_KEY"],
    base_url="https://my.orq.ai/v3/router/",
)

with client.messages.stream(
    model="anthropic/claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a haiku about AI routing."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
```

## Other Integrations

<CardGroup cols={2}>
  <Card title="Claude Code" icon="terminal" href="/docs/integrations/code-assistants/claude-code">
    Route Claude Code through the AI Router using environment variables. Integrate Claude Code with our MCP to access 20+ tools and actions on the platform.
  </Card>

  <Card title="Claude Desktop" icon="desktop" href="/docs/integrations/code-assistants/claude-desktop">
    Connect your Orq.ai workspace to Claude Desktop using the MCP integration.
  </Card>
</CardGroup>
