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

# OpenAI observability

> Trace every OpenAI API call in TypeScript and Python: prompts, token usage, cost, and latency, all readable in Tracevell's transcript view.

## Overview

Tracevell automatically instruments the official OpenAI package with a single line of code, allowing you to trace and monitor all your OpenAI API calls without modifying your existing code. This provides complete visibility into your AI application's performance, costs, and behavior.

## Getting Started

> [tab] TypeScript
>
> ### 1. Install Tracevell and OpenAI
>
> ```bash theme={null}
> npm install @lmnr-ai/lmnr@latest openai@latest
> ```
>
> ### 2. Set up your environment variables
>
> Store your API keys in a `.env` file:
>
> ```bash theme={null}
> # .env file
> LMNR_PROJECT_API_KEY=your-tracevell-project-api-key
> OPENAI_API_KEY=your-openai-api-key
> ```
>
> Then load them in your application using a package like [dotenv](https://www.npmjs.com/package/dotenv).
>
> > [!NOTE]
> >
> > Using OpenAI inside Next.js? The [Vercel AI SDK page](https://tracevell.com/docs/integrations/vercel-ai-sdk.md#next-js-setup) covers the Next.js-specific setup (`serverExternalPackages`, `instrumentation.ts`, and `Laminar.patch` for direct SDK clients).
>
> ### 3. Initialize Tracevell
>
> Just add a single line at the start of your application or file to instrument OpenAI with Tracevell.
>
> ```typescript theme={null}
> import { Tracevell } from '@lmnr-ai/lmnr';
> import OpenAI from 'openai';
> import 'dotenv/config'; // Load environment variables
>
> // This single line instruments all OpenAI API calls
> Laminar.initialize({
>   instrumentModules: { OpenAI: OpenAI }
> });
>
> // Initialize OpenAI client
> const openai = new OpenAI.OpenAI();
> ```
>
> > [!NOTE]
> >
> > `import OpenAI from 'openai'` imports the module. Pass it to
> > `instrumentModules`, then create the client with `new OpenAI.OpenAI()`.
>
> ### 4. Use OpenAI as usual
>
> ```typescript theme={null}
> // Make API calls to OpenAI as you normally would
> const response = await openai.chat.completions.create({
>   model: "gpt-5-mini",
>   messages: [
>     { role: "system", content: "You are a helpful assistant." },
>     { role: "user", content: "Hello, how are you?" }
>   ],
> });
>
> console.log(response.choices[0].message.content);
> ```
>
> All OpenAI API calls are now automatically traced in Tracevell.

> [tab] Python
>
> ### 1. Install Tracevell and OpenAI
>
> ```bash theme={null}
> pip install -U 'lmnr[all]' openai python-dotenv
> ```
>
> ### 2. Set up your environment variables
>
> Store your API keys in a `.env` file:
>
> ```bash theme={null}
> # .env file
> LMNR_PROJECT_API_KEY=your-tracevell-project-api-key
> OPENAI_API_KEY=your-openai-api-key
> ```
>
> > [!NOTE]
> >
> > To see an example of how to integrate Tracevell within a FastAPI application, check out our [FastAPI integration guide](https://tracevell.com/docs/guides/fastapi.md).
>
> ### 3. Initialize Tracevell
>
> Just add a single line at the start of your application or file to instrument OpenAI with Tracevell.
>
> ```python theme={null}
> from lmnr import Tracevell
> from openai import OpenAI
> import os
> from dotenv import load_dotenv
>
> # Load environment variables from .env file
> load_dotenv()
>
> # This single line instruments all OpenAI API calls
> Laminar.initialize()
>
> # Initialize OpenAI client as usual
> client = OpenAI()
> ```
>
> ### 4. Use OpenAI as usual
>
> ```python theme={null}
> # Make API calls to OpenAI as you normally would
> response = client.chat.completions.create(
>     model="gpt-5-mini",
>     messages=[
>         {"role": "system", "content": "You are a helpful assistant."},
>         {"role": "user", "content": "Hello, how are you?"}
>     ]
> )
>
> print(response.choices[0].message.content)
> ```
>
> All OpenAI API calls are now automatically traced in Tracevell.

## Monitoring OpenAI usage

After instrumenting your OpenAI calls with Tracevell, you'll be able to:

1. **View detailed traces** of each OpenAI API call, including request and response
2. **Track token usage and cost** across different models
3. **Monitor latency** and performance metrics
4. **Open LLM span in Playground** for prompt engineering
5. **Debug issues** with failed API calls or unexpected model outputs

Visit your Tracevell dashboard to view your OpenAI traces and analytics.

## Enrich your OpenAI traces

* Attach sessions, user IDs, metadata, and tags to OpenAI spans via the [SDK reference](https://tracevell.com/docs/sdk/reference).
* Wrap the functions around your OpenAI calls with `observe` and mark them as [TOOL spans](https://tracevell.com/docs/tracing/structure/span-types.md) so they show up in the transcript.
* Images you send to vision-capable OpenAI models are captured automatically ([Tracing Images](https://tracevell.com/docs/tracing/structure/images.md)).

## Vision inputs (images)

Tracevell automatically traces image inputs (data URLs and external URLs) sent to vision-capable OpenAI models.

> [tab] TypeScript
>
> ```typescript theme={null}
> const response = await openai.chat.completions.create({
>   model: 'gpt-5-mini',
>   messages: [
>     {
>       role: 'user',
>       content: [
>         { type: 'text', text: 'Describe this product and its key features.' },
>         {
>           type: 'image_url',
>           image_url: {
>             url: 'https://example.com/product-image.jpg',
>             detail: 'high',
>           },
>         },
>       ],
>     },
>   ],
> });
>
> console.log(response.choices[0].message.content);
> ```

> [tab] Python
>
> ```python theme={null}
> response = client.chat.completions.create(
>     model="gpt-5-mini",
>     messages=[
>         {
>             "role": "user",
>             "content": [
>                 {"type": "text", "text": "Describe this product and its key features."},
>                 {
>                     "type": "image_url",
>                     "image_url": {
>                         "url": "https://example.com/product-image.jpg",
>                         "detail": "high",
>                     },
>                 },
>             ],
>         }
>     ],
> )
>
> print(response.choices[0].message.content)
> ```

## Decisions API

The [Decisions API](https://developers.openai.com/api/reference/resources/decisions) answers a list of typed questions about a piece of input in one call: predicates (yes or no, with a probability), choices (one value from a fixed list), and scores (a level on a scale). Use it for routing, guardrails, and grading steps in your agent.

In TypeScript, call Decisions through the [Vercel AI SDK](https://tracevell.com/docs/integrations/vercel-ai-sdk.md) v7 `experimental_decide` function. Tracevell traces it through `LaminarAiSdkTelemetry`, which needs `@lmnr-ai/lmnr` 0.8.50 or later. In Python, Tracevell traces every `client.decisions.create` call in the OpenAI SDK, sync and async, with no extra setup. That needs `lmnr` 0.7.65 or later and `openai` 3.26.0 or later.

> [tab] TypeScript
>
> ```bash theme={null}
> npm install @lmnr-ai/lmnr@latest ai@latest @ai-sdk/openai@latest
> ```
>
> ```typescript theme={null}
> import { experimental_decide as decide, registerTelemetry } from 'ai';
> import { openai } from '@ai-sdk/openai';
> import { Tracevell, LaminarAiSdkTelemetry } from '@lmnr-ai/lmnr';
>
> Laminar.initialize();
> registerTelemetry(new LaminarAiSdkTelemetry());
>
> const { answers } = await decide({
>   model: openai.decisionModel('gpt-6-luna'),
>   state: 'I was charged twice for my subscription this month. Please fix it today.',
>   questions: {
>     queue: {
>       type: 'choice',
>       instructions: 'Which support queue should handle this ticket?',
>       criteria: { billing: null, technical: null, account: null },
>     },
>     urgent: {
>       type: 'boolean',
>       instructions: 'Does the customer need a response today?',
>     },
>     frustration: {
>       type: 'score',
>       instructions: 'How frustrated is the customer?',
>       criteria: ['calm', 'annoyed', 'angry'],
>     },
>   },
>   telemetry: {
>     functionId: 'triage-ticket',
>     includeRuntimeContext: { userId: true },
>   },
>   runtimeContext: { userId: 'user-123' },
> });
>
> console.log(answers.queue, answers.urgent, answers.frustration);
> ```

> [tab] Python
>
> ```bash theme={null}
> pip install -U lmnr 'openai>=3.26.0'
> ```
>
> ```python theme={null}
> from lmnr import Tracevell
> from openai import OpenAI
>
> Laminar.initialize()
>
> client = OpenAI()
>
> decision = client.decisions.create(
>     model="gpt-6-luna",
>     input="I was charged twice for my subscription this month. Please fix it today.",
>     questions=[
>         {
>             "type": "choice",
>             "name": "queue",
>             "instructions": "Which support queue should handle this ticket?",
>             "choices": [{"value": "billing"}, {"value": "technical"}, {"value": "account"}],
>         },
>         {
>             "type": "predicate",
>             "name": "urgent",
>             "instructions": "Does the customer need a response today?",
>         },
>         {
>             "type": "score",
>             "name": "frustration",
>             "instructions": "How frustrated is the customer?",
>             "levels": [{"label": "calm"}, {"label": "annoyed"}, {"label": "angry"}],
>         },
>     ],
>     safety_identifier="user-123",
> )
>
> for answer in decision.answers:
>     print(answer)
> ```

Each call becomes an LLM span, named `ai.decide` in TypeScript (`ai.decide triage-ticket` when you set `telemetry.functionId`) and `openai.decision` in Python. The span carries:

* The model, and the input you sent as the span input. A string becomes a user message. Objects, part arrays, and message lists (including image parts) are recorded as you passed them.
* The full question set, with instructions, choices, and levels for every question, in the span's output schema.
* The typed answers as the span output, with probabilities intact.
* Token counts, including cached input tokens.
* The user ID: `runtimeContext.userId` in TypeScript (opted in with `includeRuntimeContext`), `safety_identifier` in Python.

Failed calls, such as an unknown model, are marked as errors with the exception recorded. A Decisions call sits in the transcript next to the LLM calls it routes or guards, so you can see the decision next to the action it triggered. To keep the model and token counts but omit the input, questions, and answers, set `recordInputs: false` and `recordOutputs: false` in the AI SDK `telemetry` options, or `LMNR_TRACE_CONTENT=false` in Python.

## Related integrations

> [card] [Anthropic](https://tracevell.com/docs/integrations/anthropic.md)
>
> Trace the Anthropic SDK directly in TypeScript and Python.

> [card] [Gemini](https://tracevell.com/docs/integrations/gemini.md)
>
> Trace Gemini calls made with the Google Gen AI SDK.

> [card] [OpenRouter](https://tracevell.com/docs/integrations/openrouter.md)
>
> Trace OpenRouter requests with model and cost attribution.

> [card] [OpenAI Agents SDK](https://tracevell.com/docs/integrations/openai-agents-sdk.md)
>
> Trace agent runs, handoffs, and tool calls.

> [card] [Vercel AI SDK](https://tracevell.com/docs/integrations/vercel-ai-sdk.md)
>
> Trace `generateText` and `streamText` in Next.js and Node.js.

> [card] [All integrations](https://tracevell.com/docs/integrations.md)
>
> Browse every provider, framework, coding agent, and browser integration Tracevell supports.


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