> ## 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.

# OpenAI Agents SDK (Beta)

> Automatic tracing for OpenAI Agents with Raindrop

## Installation

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

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

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

## Quick Start

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createRaindropOpenAIAgents } from "@raindrop-ai/openai-agents";
  import { Agent, run, addTraceProcessor } from "@openai/agents";

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

  addTraceProcessor(raindrop.processor);

  const agent = new Agent({
    name: "Assistant",
    model: "gpt-4o",
    instructions: "Be helpful",
  });

  const result = await run(agent, "What is the capital of France?");
  console.log(result.finalOutput);

  await raindrop.flush();
  ```

  ```python Python theme={null}
  from raindrop_openai_agents import create_raindrop_openai_agents
  from agents import Agent, Runner

  raindrop = create_raindrop_openai_agents(
      api_key="your-write-key",
      user_id="user-123",
  )
  # Processor is auto-registered — no extra setup needed

  agent = Agent(name="Assistant", model="gpt-4o", instructions="Be helpful")

  result = Runner.run_sync(agent, "What is the capital of France?")
  print(result.final_output)

  raindrop.flush()
  ```
</CodeGroup>

## What Gets Traced

The integration captures events from the OpenAI Agents SDK's built-in tracing system:

* **Agent runs** — trace-level events with workflow name and metadata
* **LLM generations** — model, input messages, output, token usage (input\_tokens/output\_tokens)
* **Tool/function calls** — function name, input arguments, output, duration, and errors
* **Handoffs** — from/to agent names for multi-agent workflows (TypeScript only)
* **Errors** — captured with error type and message in event properties
* **Finish reason** — extracted from response status or generation output (`ai.finish_reason`)
* **Extended token categories** — cached tokens (`ai.usage.cached_tokens`) and reasoning/thoughts tokens (`ai.usage.thoughts_tokens`) for OpenAI o1/o3 models

In TypeScript, all spans are linked with parent-child relationships for full trace visibility. In Python, tool calls are tracked as individual tool spans via the Interaction API, and LLM generation data is captured per trace.

## Configuration

<CodeGroup>
  ```typescript TypeScript theme={null}
  const raindrop = createRaindropOpenAIAgents({
    writeKey: "your-write-key",       // Optional: your Raindrop write key (omit to disable telemetry)
    endpoint: "...",          // Optional: custom 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_openai_agents import RaindropOpenAIAgents

  raindrop = RaindropOpenAIAgents(
      api_key="your-write-key",           # Optional: 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 (default True)
      bypass_otel_for_tools=True,         # Optional: bypass OTEL for tool calls (default True)
      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 = createRaindropOpenAIAgents({
    writeKey: "your-write-key",
    projectId: "support-prod",
  });
  ```

  ```python Python theme={null}
  raindrop = RaindropOpenAIAgents(
      api_key="your-write-key",
      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 (Python)

Available in `raindrop-ai>=0.0.56`. Each `RaindropOpenAIAgents` wrapper owns
its own `raindrop.Raindrop` client, so its **manual** APIs —
`flush()`, `identify()`, `track_signal()` — route to that wrapper's project
independently:

```python theme={null}
from raindrop_openai_agents import RaindropOpenAIAgents

rd_support = RaindropOpenAIAgents(api_key="your-write-key", project_id="support-prod")
rd_billing = RaindropOpenAIAgents(api_key="your-write-key", project_id="billing-prod")

rd_support.flush()  # -> support-prod
rd_billing.flush()  # -> billing-prod
```

<Warning>
  **Automatic trace capture is process-global and cannot be split by project.**
  The OpenAI Agents SDK exposes a single, process-global trace-processor
  registry (`add_trace_processor`, with no removal API), and auto-captured
  traces carry no project identity. Raindrop therefore registers **one**
  processor per process, and automatic capture follows the **most recently
  constructed** wrapper: building a second wrapper with a different
  `project_id` redirects *all* automatic agent traces — including those from
  agents wired under the first wrapper — to the newer project, and emits a
  runtime warning. Manual APIs (`flush`/`identify`/`track_signal`) still route
  per wrapper.

  For automatic capture, use **one project per process**. If you must stay in
  one process, construct a single `raindrop.Raindrop` and share it via
  `client=` so there is no ambiguity about where traces land:

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

  client = Raindrop(api_key="your-write-key", project_id="support-prod")
  rd = RaindropOpenAIAgents(client=client)
  ```
</Warning>

<Note>
  **Mixed processes — TypeScript (a tracing-enabled `raindrop-ai` js-sdk client alongside this integration).** If the same Node process also constructs a tracing-enabled `raindrop-ai` js-sdk client, its Traceloop pipeline auto-instruments the underlying LLM libraries **process-wide** — so calls made through this integration package additionally produce auto-instrumented spans that route to the js-sdk pipeline owner's project. This is pre-existing behavior, unrelated to per-instance routing. Run mixed setups with a single project, or scope the integration's calls with the js-sdk client's `asCurrent()`.
</Note>

## Identify Users

Associate a user identity with optional traits for analytics:

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

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

## Track Signals

Attach feedback, labels, or other signals to an existing event:

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

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

## Multi-Agent Workflows

The integration automatically captures handoffs between agents:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const triage = new Agent({
    name: "Triage",
    model: "gpt-4o-mini",
    instructions: "Route to the appropriate specialist.",
    handoffs: [specialist],
  });

  const result = await run(triage, "I need help with billing");
  await raindrop.flush();
  ```

  ```python Python theme={null}
  triage = Agent(
      name="Triage",
      model="gpt-4o-mini",
      instructions="Route to the appropriate specialist.",
      handoffs=[specialist],
  )

  result = Runner.run_sync(triage, "I need help with billing")
  raindrop.flush()
  ```
</CodeGroup>

## Flushing and Shutdown

Always call `flush()` before your process exits to ensure all telemetry is shipped:

<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>

## Known Limitations (Python)

* **Handoffs are not individually captured** in the Python SDK. The TypeScript SDK captures full span trees including handoffs.
* **Multi-response traces**: In multi-agent workflows with handoffs, only the last response's data survives per trace.
