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

# Azure OpenAI (Beta)

> Automatic tracing for Azure OpenAI applications with Raindrop

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @raindrop-ai/azure-openai openai
  ```

  ```bash pnpm theme={null}
  pnpm add @raindrop-ai/azure-openai openai
  ```

  ```bash pip theme={null}
  pip install raindrop-azure-openai openai
  ```
</CodeGroup>

## Quick Start

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createRaindropAzureOpenAI } from "@raindrop-ai/azure-openai";
  import { AzureOpenAI } from "openai";

  const raindrop = createRaindropAzureOpenAI({
    writeKey: "your-write-key",
    userId: "user-123",
  });

  const client = new AzureOpenAI({
    endpoint: "https://your-resource.openai.azure.com",
    apiKey: "...",
    apiVersion: "2024-10-21",
  });

  const wrapped = raindrop.wrap(client);

  const response = await wrapped.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: "What is the capital of France?" }],
  });

  console.log(response.choices[0].message.content);
  await raindrop.shutdown();
  ```

  ```python Python theme={null}
  from raindrop_azure_openai import RaindropAzureOpenAI
  from openai import AzureOpenAI

  raindrop = RaindropAzureOpenAI(
      api_key="rk_...",
      user_id="user-123",
  )

  client = AzureOpenAI(
      azure_endpoint="https://your-resource.openai.azure.com",
      api_key="...",
      api_version="2024-10-21",
  )
  wrapped = raindrop.wrap(client)

  response = wrapped.chat.completions.create(
      model="gpt-4o-mini",
      messages=[{"role": "user", "content": "What is the capital of France?"}],
  )

  print(response.choices[0].message.content)
  raindrop.shutdown()
  ```
</CodeGroup>

## What Gets Traced

* **Chat completions** — input messages (user text only), output text, model, token usage (prompt/completion)
* **Finish reason** — `azure_openai.finish_reason` (`stop`, `length`, `content_filter`, `tool_calls`)
* **Extended tokens** — `ai.usage.cached_tokens` (prompt cache hits) and `ai.usage.thoughts_tokens` (reasoning tokens for o1/o3 models)
* **Errors** — captured with error status, re-thrown to caller

## Configuration

<CodeGroup>
  ```typescript TypeScript theme={null}
  const raindrop = createRaindropAzureOpenAI({
    writeKey: "your-write-key",       // Optional: your Raindrop write key (omit to disable telemetry)
    endpoint: "...",          // Optional: custom Raindrop API endpoint
    userId: "user-123",      // Optional: associate events with a user
    convoId: "convo-456",    // Optional: conversation/thread ID
    projectId: "support-prod", // Optional: route events to a specific project (slug)
    debug: false,             // Optional: enable verbose logging
  });
  ```

  ```python Python theme={null}
  from raindrop_azure_openai import RaindropAzureOpenAI

  raindrop = RaindropAzureOpenAI(
      api_key="rk_...",                   # Optional: your Raindrop API key (omit to disable telemetry)
      user_id="user-123",                 # Optional: associate events with a user
      convo_id="convo-456",               # Optional: conversation/thread ID
      project_id="support-prod",          # Optional: route events to a specific project (slug)
      tracing_enabled=True,               # Optional: enable OTEL-based tracing
      bypass_otel_for_tools=True,         # Optional: bypass OTEL for tool calls
      debug=False,                        # Optional: enable verbose logging
  )
  ```
</CodeGroup>

## Projects

Route events to a specific [project](/platform/projects) by passing its slug as `projectId` (`project_id` in Python):

<CodeGroup>
  ```typescript TypeScript theme={null}
  const raindrop = createRaindropAzureOpenAI({
    writeKey: "your-write-key",
    projectId: "support-prod",
  });
  ```

  ```python Python theme={null}
  raindrop = RaindropAzureOpenAI(
      api_key="rk_...",
      project_id="support-prod",
  )
  ```
</CodeGroup>

This sets the `X-Raindrop-Project-Id` header on every event. Omit it (or pass `"default"`) to use your org's default **Production** project, which is the existing behavior. Single-project orgs need nothing new.

### Multiple projects in one process

Available in `raindrop-ai>=0.0.56`. When one service wraps several Azure OpenAI
clients that should report to **different** projects, create one
`RaindropAzureOpenAI` wrapper per project. Each wrapper owns its own
`raindrop.Raindrop` client, so the two route independently — there is no shared
module-level state:

```python theme={null}
from raindrop_azure_openai import RaindropAzureOpenAI

# One long-lived wrapper per project, created at startup and reused.
rd_support = RaindropAzureOpenAI(api_key="rk_...", project_id="support-prod")
rd_billing = RaindropAzureOpenAI(api_key="rk_...", project_id="billing-prod")

support_client = rd_support.wrap(support_client)   # -> support-prod
billing_client = rd_billing.wrap(billing_client)   # -> billing-prod

rd_support.flush()
rd_billing.flush()
```

Each wrapper owns its configuration and delivery pipeline, so clients handled by
different wrappers route independently. To share a single client across wrappers
(or with the module-level API), construct a `raindrop.Raindrop` yourself and
pass it via `client=`:

```python theme={null}
from raindrop import Raindrop

client = Raindrop(api_key="rk_...", project_id="support-prod")
raindrop = RaindropAzureOpenAI(client=client)
```

## Flushing and Shutdown

<CodeGroup>
  ```typescript TypeScript theme={null}
  await raindrop.flush();     // flush pending data
  await raindrop.shutdown();  // flush + release resources
  ```

  ```python Python theme={null}
  raindrop.flush()     # flush pending data
  raindrop.shutdown()  # flush + release resources
  ```
</CodeGroup>

## User Identification

<CodeGroup>
  ```typescript TypeScript theme={null}
  raindrop.users.identify({ userId: "user-123", traits: { plan: "pro", name: "Alice" } });
  ```

  ```python Python theme={null}
  raindrop.identify("user-123", traits={"plan": "pro", "name": "Alice"})
  ```
</CodeGroup>

## Tracking Signals

<CodeGroup>
  ```typescript TypeScript theme={null}
  raindrop.signals.track({
    eventId: "evt-abc",
    name: "thumbs_up",
    type: "feedback",
    sentiment: "POSITIVE",
    comment: "Great response!",
  });
  ```

  ```python Python theme={null}
  raindrop.track_signal(
      event_id="evt-abc",
      name="thumbs_up",
      signal_type="feedback",
      sentiment="POSITIVE",
      comment="Great response!",
  )
  ```
</CodeGroup>

## Factory Function (Backwards-Compatible)

```python Python theme={null}
from raindrop_azure_openai import create_raindrop_azure_openai

raindrop = create_raindrop_azure_openai(api_key="rk_...", user_id="user-123")
# Returns a RaindropAzureOpenAI instance
```

<Note>
  Already using the Vercel AI SDK with Azure? The [Vercel AI SDK integration](/integrations/vercel-ai-sdk) automatically traces Azure OpenAI calls when you use the AI SDK's Azure provider. This integration is for users calling the Azure OpenAI SDK directly.
</Note>
