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

# OpenAI

> Auto-trace OpenAI Chat Completions and Responses API calls

### Installation

<Tabs>
  <Tab title="pip">
    ```bash theme={null}
    pip install "pandaprobe[openai]"
    ```
  </Tab>

  <Tab title="uv">
    ```bash theme={null}
    uv add "pandaprobe[openai]"
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    npm install pandaprobe openai
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add pandaprobe openai
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add pandaprobe openai
    ```
  </Tab>
</Tabs>

### Setup

<Tabs>
  <Tab title="Python">
    ```python title="Python" theme={null}
    from pandaprobe.wrappers import wrap_openai
    from openai import OpenAI

    client = wrap_openai(OpenAI())
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts title="TypeScript" theme={null}
    import OpenAI from "openai";
    import { wrapOpenAI } from "pandaprobe/wrappers/openai";

    const client = wrapOpenAI(new OpenAI());
    ```
  </Tab>
</Tabs>

<Note>
  PandaProbe traces both synchronous and asynchronous Python clients, plus the Promise-based TypeScript client.
</Note>

## Chat Completions API

Span name: `"openai-chat"`, SpanKind: `LLM`

```python title="Python" theme={null}
response = client.chat.completions.create(
    model="gpt-5.4",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain quantum computing."},
    ],
    temperature=0.7,
)
```

```ts title="TypeScript" theme={null}
const response = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Explain quantum computing." },
  ],
  temperature: 0.7,
});
```

**What gets traced**

* Input: messages array
* Output: assistant message
* Model name
* Token usage: `prompt_tokens`, `completion_tokens`, `total_tokens`, plus detail fields (for example `reasoning_tokens` from `completion_tokens_details`)
* Model parameters: `temperature`, `top_p`, `max_tokens`, and other safe parameters only

### Streaming

```python title="Python" theme={null}
stream = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
```

```ts title="TypeScript" theme={null}
const stream = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Hello!" }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}
```

Streaming is fully supported. The wrapper records `completion_start_time` on the first chunk for time-to-first-token tracking. Chunks are reduced to a single response for the span output.

## Responses API

Span name: `"openai-response"`, SpanKind: `LLM`

```python title="Python" theme={null}
response = client.responses.create(
    model="gpt-5.4",
    instructions="You are a helpful assistant.",
    input="What is the capital of France?",
)
```

```ts title="TypeScript" theme={null}
const response = await client.responses.create({
  model: "gpt-5.6-terra",
  instructions: "You are a helpful assistant.",
  input: "What is the capital of France?",
});
```

**What gets traced**

* Input: `instructions` plus `input`, normalized to messages format
* Output: response output items
* Token usage: `input_tokens` mapped to prompt tokens, `output_tokens` mapped to completion tokens, plus detail fields
* Reasoning summaries extracted from reasoning output items
* Model parameters: `max_output_tokens`, `temperature`, `top_p`, `reasoning`, and related fields

### Tool calls (Responses API)

Built-in tools such as `web_search`, `file_search`, and `code_interpreter` are automatically traced as child spans with SpanKind `TOOL`:

```python title="Python" theme={null}
response = client.responses.create(
    model="gpt-5.4",
    input="Search the web for PandaProbe",
    tools=[{"type": "web_search"}],
)
```

Each tool invocation produces a child `TOOL` span with the tool type as the span name (for example `"web_search_call"`, `"function_call"`).

Function calls (`function_call` items) are also captured as `TOOL` child spans with arguments as input and results as output.

## Token usage mapping

| OpenAI Field | PandaProbe Field |
| - | - |
| `prompt_tokens` | `prompt_tokens` |
| `completion_tokens` | `completion_tokens` |
| `total_tokens` | `total_tokens` |
| `completion_tokens_details.reasoning_tokens` | `reasoning_tokens` |
| (Responses) `input_tokens` | `prompt_tokens` |
| (Responses) `output_tokens` | `completion_tokens` |
| (Responses) `input_tokens_details.cached_tokens` | `cache_read_tokens` |
| (Responses) `output_tokens_details.reasoning_tokens` | `reasoning_tokens` |

<Warning>
  Chat Completions and Responses return different usage object shapes from the SDK. The wrapper normalizes both into the PandaProbe fields in this table; do not assume raw OpenAI field names are identical across APIs when reading span payloads in custom exporters.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.