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

# Python SDK Quickstart

> Start here for the whyops Python package: install the package, initialize the agent, make your first proxied call, and then move into runtime tracing.

The `whyops` package gives Python services one integration surface for agent registration, OpenAI or Anthropic proxying, and direct runtime event emission. This page is the basic setup path.

<CardGroup cols={3}>
  <Card title="Proxy Helpers" icon="plug" href="/integrations/python-sdk-proxy">
    Read this next if you want the exact API-key flow and what `sdk.openai()` or `sdk.anthropic()` changes.
  </Card>

  <Card title="Runtime Events" icon="diagram-project" href="/integrations/python-sdk-runtime">
    Add sync or async trace events for tools, thinking blocks, embeddings, and errors.
  </Card>

  <Card title="Advanced Patterns" icon="sliders" href="/integrations/python-sdk-advanced">
    Hybrid tracing, self-hosted overrides, prompt caching, and common mistakes.
  </Card>
</CardGroup>

## Before you start

| You need                                  | Why                                                                                       |
| ----------------------------------------- | ----------------------------------------------------------------------------------------- |
| `WHYOPS_API_KEY`                          | Authenticates agent init, manual events, and proxied model traffic to WhyOps              |
| A stable `agent_name`                     | Keeps proxy traffic and runtime events attached to the same agent identity                |
| `systemPrompt` and tool metadata          | Lets WhyOps version the agent and show the correct configuration in the UI                |
| Your provider key in the WhyOps dashboard | Lets WhyOps authenticate upstream when it forwards OpenAI or Anthropic traffic            |
| A stable session or trace ID              | Best for explicit continuity between proxied model calls and later tool or runtime events |

<Callout type="info" title="Recommended order">
  In Python, the cleanest flow is: create the WhyOps client, call `init_agent_sync()` or `await init_agent()` during startup, then patch OpenAI or Anthropic, and only after that add manual runtime events.
</Callout>

## 1. Install the package

<Tabs>
  <Tab title="pip">
    ```bash theme={null}
    pip install whyops
    ```
  </Tab>

  <Tab title="uv">
    ```bash theme={null}
    uv add whyops
    ```
  </Tab>

  <Tab title="poetry">
    ```bash theme={null}
    poetry add whyops
    ```
  </Tab>
</Tabs>

## 2. Create the WhyOps client once

```python theme={null}
from whyops import WhyOps

sdk = WhyOps(
    api_key="YOUR_WHYOPS_API_KEY",
    agent_name="customer-support-agent",
    agent_metadata={
        "systemPrompt": "You are a precise customer support assistant.",
        "description": "Handles support, billing, and order status flows.",
        "tools": [
            {
                "name": "search_orders",
                "description": "Look up order state by ID",
                "inputSchema": "{\"type\":\"object\",\"properties\":{\"orderId\":{\"type\":\"string\"}},\"required\":[\"orderId\"]}",
                "outputSchema": "{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}}",
            }
        ],
    },
)
```

<Callout type="warning" title="Tool schemas are strings">
  If you include `inputSchema` or `outputSchema`, pass JSON strings. If the agent has no tools, set `tools: []` explicitly so the registered definition stays clear.
</Callout>

## 3. Initialize the agent during startup

<Tabs>
  <Tab title="Sync">
    ```python theme={null}
    sdk.init_agent_sync()
    ```
  </Tab>

  <Tab title="Async">
    ```python theme={null}
    await sdk.init_agent()
    ```
  </Tab>
</Tabs>

You do not have to call this manually because trace methods auto-initialize, but early registration is the better default because configuration problems fail before live traffic.

## 4. Make your first proxied model call

<Tabs>
  <Tab title="OpenAI">
    ```python theme={null}
    from openai import OpenAI

    trace_id = "session-123"
    client = sdk.openai(OpenAI(api_key="YOUR_WHYOPS_API_KEY"))
    client.default_headers = {
        **(client.default_headers or {}),
        "X-Trace-ID": trace_id,
        "X-Thread-ID": trace_id,
    }

    completion = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Where is order 123?"}],
    )
    ```
  </Tab>

  <Tab title="Anthropic">
    ```python theme={null}
    from anthropic import Anthropic

    trace_id = "session-123"
    client = sdk.anthropic(Anthropic(api_key="YOUR_WHYOPS_API_KEY"))
    client.default_headers = {
        **(client.default_headers or {}),
        "X-Trace-ID": trace_id,
        "X-Thread-ID": trace_id,
    }

    message = client.messages.create(
      model="claude-3-5-sonnet-20241022",
        max_tokens=800,
        messages=[{"role": "user", "content": "Summarize this incident."}],
    )
    ```
  </Tab>
</Tabs>

<Callout type="tip" title="Read the proxy page next">
  The helper mutates the provider client in place. Go to [Python SDK Proxy Helpers](/integrations/python-sdk-proxy) for the exact key flow, header behavior, and sync versus async details.
</Callout>

<Callout type="warning" title="Use explicit trace headers when you care about follow-up tool continuity">
  The proxy can generate a trace automatically, but the backend checks `X-Trace-ID` and `X-Thread-ID` first. If your app later emits tool or runtime events, reusing the same explicit trace ID is the cleaner and more reliable setup.
</Callout>

## 5. Add runtime traces only where you need more visibility

Start with proxy-only instrumentation first. Add `trace()` events when you need:

* tool execution latency and outputs
* retries inside your framework
* runtime failures after the model returns
* prompt caching-aware usage on manual `llm_response()` calls
* exposed thinking blocks or orchestration milestones

## Next pages

<CardGroup cols={3}>
  <Card title="Proxy Helpers" icon="plug" href="/integrations/python-sdk-proxy">
    Understand which API key goes where and what the helper changes on the provider client.
  </Card>

  <Card title="Runtime Events" icon="terminal" href="/integrations/python-sdk-runtime">
    Add manual event coverage for tools, thinking blocks, embeddings, and errors.
  </Card>

  <Card title="Advanced Patterns" icon="sliders" href="/integrations/python-sdk-advanced">
    Finish with hybrid tracing, self-hosting, prompt caching, and event IDs.
  </Card>
</CardGroup>
