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

# OpenAI

> Automatic tracing for the full OpenAI SDK — chat, embeddings, images, audio, and more

# OpenAI

The `@mutagent/openai` package provides `observeOpenAI()`, a wrapper that adds automatic tracing to **any OpenAI client instance**. Using JavaScript Proxy, it intercepts all method calls without replacing the client — chat completions, embeddings, images, audio, moderations, and every other SDK method work exactly as before, with full tracing.

## Installation

<CodeGroup>
  ```bash bun theme={null}
  bun add @mutagent/openai @mutagent/sdk
  ```

  ```bash npm theme={null}
  npm install @mutagent/openai @mutagent/sdk
  ```

  ```bash yarn theme={null}
  yarn add @mutagent/openai @mutagent/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @mutagent/openai @mutagent/sdk
  ```
</CodeGroup>

**Peer dependencies:** `@mutagent/sdk >=0.1.0`, `openai >=4.0.0`

## Quick Start

<Steps>
  <Step title="Initialize tracing">
    Call `initTracing()` once at application startup.

    ```typescript theme={null}
    import { initTracing } from '@mutagent/sdk/tracing';

    initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
    ```
  </Step>

  <Step title="Wrap your OpenAI client">
    Call `observeOpenAI()` to wrap your existing client. All methods are preserved.

    ```typescript theme={null}
    import OpenAI from 'openai';
    import { observeOpenAI } from '@mutagent/openai';

    const openai = observeOpenAI(new OpenAI());
    ```
  </Step>

  <Step title="Use as normal">
    Every API call is automatically traced — no code changes needed.

    ```typescript theme={null}
    const completion = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages: [{ role: 'user', content: 'Hello!' }],
    });

    console.log(completion.choices[0].message.content);
    ```
  </Step>
</Steps>

## Full Example

```typescript theme={null}
import { initTracing } from '@mutagent/sdk/tracing';
import OpenAI from 'openai';
import { observeOpenAI } from '@mutagent/openai';

// 1. Initialize SDK tracing (once at app startup)
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });

// 2. Wrap the OpenAI client
const openai = observeOpenAI(new OpenAI());

// 3. All methods are traced automatically
const completion = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'Explain observability in 3 sentences.' },
  ],
});

// Embeddings — also traced
const embedding = await openai.embeddings.create({
  model: 'text-embedding-3-small',
  input: 'The quick brown fox',
});

// Images — also traced
const image = await openai.images.generate({
  model: 'dall-e-3',
  prompt: 'A sunset over mountains',
});
```

## Streaming

Streaming is fully supported. The wrapper intercepts the async iterator to accumulate response text and closes the span when the stream completes.

```typescript theme={null}
const stream = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: 'Tell me a story' }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content || '');
}
// Span is automatically closed when the stream ends
```

<Note>
  The stream wrapper preserves the original async iterator interface. Your existing streaming code works without changes.
</Note>

## Options

Pass options to `observeOpenAI()` for session tracking and custom span naming:

```typescript theme={null}
const openai = observeOpenAI(new OpenAI(), {
  generationName: 'my-app',     // Custom span name prefix
  sessionId: 'chat-session-123', // Group traces by session
  userId: 'user-456',           // Attribute traces to a user
  tags: ['production', 'v2'],   // Filter traces by tag
});
```

| Option           | Type       | Description                                                                                      |
| ---------------- | ---------- | ------------------------------------------------------------------------------------------------ |
| `generationName` | `string`   | Custom span name prefix. Defaults to auto-detected method path (e.g., `chat.completions.create`) |
| `sessionId`      | `string`   | Group related traces into a session                                                              |
| `userId`         | `string`   | Attribute traces to a specific user                                                              |
| `tags`           | `string[]` | Tags for filtering in the dashboard                                                              |

## What Gets Traced

The Proxy wrapper intercepts all method calls on the OpenAI client. Known methods get structured tracing:

| Method                    | Span Kind        | Data Captured                                        |
| ------------------------- | ---------------- | ---------------------------------------------------- |
| `chat.completions.create` | `llm.chat`       | Input messages, output messages, model, token usage  |
| `completions.create`      | `llm.completion` | Input text, output text, model, token usage          |
| `embeddings.create`       | `llm.embedding`  | Input text, embedding dimensions, model, token usage |
| All other methods         | `llm.chat`       | Raw request/response data                            |
| Streaming calls           | Same as above    | Accumulated text, model                              |
| Errors                    | Any              | Error message, status set to `error`                 |

## Token Usage Tracking

For non-streaming calls, token metrics are automatically extracted from the OpenAI response:

* `inputTokens` — `usage.prompt_tokens`
* `outputTokens` — `usage.completion_tokens`
* `totalTokens` — `usage.total_tokens`

The `model` and `provider` (always `"openai"`) are recorded in span metrics.

<Note>
  For streaming calls, token usage is available when you set `stream_options: { include_usage: true }` in the request parameters.
</Note>

## How It Works

`observeOpenAI()` uses a JavaScript `Proxy` that:

1. **Intercepts property access** on the OpenAI client via the `get` trap
2. **Recursively wraps nested objects** — accessing `client.chat` returns a new Proxy, so `client.chat.completions.create()` is intercepted
3. **Wraps function calls** with `startSpan()` / `endSpan()` from `@mutagent/sdk/tracing`
4. **Handles streaming** by wrapping `AsyncIterable` responses to accumulate text before closing the span

This means every method on the OpenAI SDK is automatically traced — including methods added in future SDK versions.

## Migration from `MutagentOpenAI`

<Warning>
  `MutagentOpenAI` is **deprecated**. It only traced `chat.completions.create()` — all other SDK methods were missing. Use `observeOpenAI()` instead.
</Warning>

**Before (deprecated):**

```typescript theme={null}
import { MutagentOpenAI } from '@mutagent/openai';
const client = new MutagentOpenAI({ apiKey: '...' });
client.chat.completions.create(...)  // ✅ traced
client.embeddings.create(...)         // ❌ not available
```

**After (recommended):**

```typescript theme={null}
import OpenAI from 'openai';
import { observeOpenAI } from '@mutagent/openai';
const client = observeOpenAI(new OpenAI());
client.chat.completions.create(...)    // ✅ traced
client.embeddings.create(...)           // ✅ traced
client.images.generate(...)             // ✅ traced
```

## CLI Shortcut

```bash theme={null}
mutagent integrate openai
```

This auto-detects the `openai` package in your `package.json` and generates ready-to-use configuration code.

## Python

Looking for the Python OpenAI integration? See the [Python OpenAI guide](/integrations/python/openai).
