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

# OpenAI

> OpenAI model provider configuration and integration guide

If you are a coding agent, prefer the Braintrust [`bt` CLI](/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, such as ad-hoc lookups and exploration from your IDE.

OpenAI provides access to GPT models including GPT-5 and other cutting-edge language models. Braintrust integrates seamlessly with OpenAI through direct API access, `wrapOpenAI` wrapper functions for automatic tracing, and proxy support.

<Note>
  This guide covers manual instrumentation. For quicker setup, use [auto-instrumentation](/instrument/trace-llm-calls).
</Note>

<Note>
  For the GPT-5 family of models, the `temperature` parameter is not configurable. It is handled automatically by the model and is disabled in the Braintrust UI.
</Note>

## Setup

To use OpenAI models in the Braintrust playground, API, and gateway, connect OpenAI as a provider in your organization or project AI providers.

1. Go to **<Icon icon="settings-2" /> Settings** > [**<Icon icon="sparkle" /> AI providers**](https://www.braintrust.dev/app/~/configuration/org/secrets).
2. Click <Icon icon="plus" /> **Organization provider** or <Icon icon="plus" /> **Project provider**, depending on whether you want the provider to be available across every project in the organization or just the current project.
3. Under **Model providers**, click **OpenAI**.
4. Choose your authentication method:
   * **API key**: Visit [OpenAI's API platform](https://platform.openai.com/api-keys), create a new API key, and paste it into the **Secret** field.

     <Note>
       API keys are stored as one-way cryptographic hashes, never in plaintext.
     </Note>
   * **Workload identity federation**: Exchange a Braintrust-signed OIDC token for an OpenAI access token, instead of storing a long-lived OpenAI API key in Braintrust.

     <Note>
       Workload identity federation is available only for organization-level providers on Braintrust-hosted organizations with the Braintrust gateway enabled. Project-level providers and self-hosted deployments must use **API key** authentication.
     </Note>
5. If you chose **Workload identity federation**, use the setup values shown in Braintrust to configure OpenAI:

   1. [Create a workload identity provider](https://developers.openai.com/api/docs/guides/workload-identity-federation) in OpenAI. Use the **Issuer URL** and **Audience** shown in Braintrust, set **JWKS source** to **OIDC discovery**, use the **Subject pattern**, and add the **Required claims** shown in Braintrust.
   2. Map the workload identity provider to the OpenAI service account Braintrust should use.
   3. Paste the OpenAI IDs back into Braintrust:
      * **Identity provider ID**: The workload identity provider ID configured for Braintrust.
      * **Service account ID**: The OpenAI service account ID Braintrust should use.
      * **Subject suffix**: A stable suffix for this OpenAI connection. It must match the final part of the subject pattern used in OpenAI.

   For general OpenAI concepts and dashboard details, see [OpenAI's workload identity federation docs](https://developers.openai.com/api/docs/guides/workload-identity-federation).
6. Click **Save**.

To call OpenAI directly from your application code rather than through the Braintrust gateway, set your OpenAI API key and Braintrust API key as environment variables:

```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
OPENAI_API_KEY=<your-openai-api-key>
BRAINTRUST_API_KEY=<your-braintrust-api-key>

# For organizations on the EU data plane, use https://api-eu.braintrust.dev
# For self-hosted deployments, use your data plane URL
# BRAINTRUST_API_URL=<your-braintrust-api-url>
```

Install the `braintrust` and `openai` packages.

<CodeGroup>
  ```bash Typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # pnpm
  pnpm add braintrust openai
  # npm
  npm install braintrust openai
  ```

  ```bash Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  pip install braintrust openai
  ```

  ```bash Go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  go get github.com/braintrustdata/braintrust-sdk-go
  go get github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai
  go get github.com/openai/openai-go
  ```

  ```bash Ruby theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  gem install braintrust openai
  ```

  ```bash Java theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # add to build.gradle dependencies{} block
  implementation 'dev.braintrust:braintrust-sdk-java:<version-goes-here>'
  implementation 'com.openai:openai-java:<version-goes-here>'
  ```

  ```bash C# theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # add to .csproj file
  dotnet add package Braintrust.Sdk
  dotnet add package OpenAI
  ```
</CodeGroup>

## Trace with OpenAI

[Trace](/instrument/trace-llm-calls) your OpenAI LLM calls for observability and monitoring.

Using the OpenAI Agents SDK? See the [OpenAI Agents SDK](/integrations/agent-frameworks/openai-agents-sdk) framework docs.

### Trace automatically

Braintrust provides automatic tracing for OpenAI API calls, handling streaming, metrics collection, and other details.

* **TypeScript & Python**: Use `wrapOpenAI` / `wrap_openai` wrapper functions
* **Go**: Use the tracing middleware with the OpenAI client
* **Ruby**: Use `Braintrust::Trace::OpenAI.wrap` to wrap the OpenAI client
* **Java**: Use the tracing interceptor with the OpenAI client
* **C#**: Use `BraintrustOpenAI.WrapOpenAI` to wrap the OpenAI client

<Tip>
  For more control over tracing, learn how to [customize traces](/instrument/advanced-tracing).
</Tip>

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import OpenAI from "openai";

  // Initialize the Braintrust logger
  const logger = initLogger({
    projectName: "My Project", // Your project name
    apiKey: process.env.BRAINTRUST_API_KEY,
  });

  // Wrap the OpenAI client with wrapOpenAI
  const client = wrapOpenAI(
    new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    }),
  );

  // All API calls are automatically logged
  const result = await client.chat.completions.create({
    model: "gpt-5-mini",
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: "What is machine learning?" },
    ],
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import os

  from braintrust import init_logger, wrap_openai
  from openai import OpenAI

  logger = init_logger(project="My Project")
  client = wrap_openai(OpenAI(api_key=os.environ["OPENAI_API_KEY"]))

  # All API calls are automatically logged
  result = client.chat.completions.create(
      model="gpt-5-mini",
      messages=[
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "What is machine learning?"},
      ],
  )
  ```

  ```go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  package main

  import (
  	"context"
  	"log"
  	"os"

  	"github.com/openai/openai-go"
  	"github.com/openai/openai-go/option"
  	"go.opentelemetry.io/otel"
  	"go.opentelemetry.io/otel/sdk/trace"

  	"github.com/braintrustdata/braintrust-sdk-go"
  	traceopenai "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai"
  )

  func main() {
  	// Set up OpenTelemetry TracerProvider
  	tp := trace.NewTracerProvider()
  	defer tp.Shutdown(context.Background())
  	otel.SetTracerProvider(tp)

  	// Initialize Braintrust client
  	_, err := braintrust.New(tp,
  		braintrust.WithProject("My Project"),
  		braintrust.WithAPIKey(os.Getenv("BRAINTRUST_API_KEY")),
  	)
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Create OpenAI client with tracing middleware
  	client := openai.NewClient(
  		option.WithMiddleware(traceopenai.NewMiddleware()),
  	)

  	// All API calls are automatically logged
  	result, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
  		Messages: []openai.ChatCompletionMessageParamUnion{
  			openai.SystemMessage("You are a helpful assistant."),
  			openai.UserMessage("What is machine learning?"),
  		},
  		Model: openai.ChatModelGPT4o,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	_ = result
  }
  ```

  ```ruby theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  require 'braintrust'
  require 'openai'

  # Initialize Braintrust
  Braintrust.init(project: 'My Project')

  # Create OpenAI client
  client = OpenAI::Client.new(api_key: ENV.fetch('OPENAI_API_KEY', nil))

  # Wrap the client with Braintrust tracing
  Braintrust::Trace::OpenAI.wrap(client)

  # All API calls are automatically logged
  client.chat.completions.create(
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'What is machine learning?' }
    ]
  )
  ```

  ```java theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import com.openai.client.OpenAIClient;
  import com.openai.client.okhttp.OpenAIOkHttpClient;
  import com.openai.models.ChatModel;
  import com.openai.models.chat.completions.ChatCompletionCreateParams;
  import dev.braintrust.Braintrust;
  import dev.braintrust.instrumentation.openai.BraintrustOpenAI;

  class OpenAITracing {
      public static void main(String[] args) {
          var braintrust = Braintrust.get();
          var openTelemetry = braintrust.openTelemetryCreate();

          // Wrap the OpenAI client with Braintrust instrumentation
          OpenAIClient client = BraintrustOpenAI.wrapOpenAI(openTelemetry, OpenAIOkHttpClient.fromEnv());

          // All API calls are automatically logged
          var request = ChatCompletionCreateParams.builder()
              .model(ChatModel.GPT_4O_MINI)
              .addSystemMessage("You are a helpful assistant.")
              .addUserMessage("What is machine learning?")
              .temperature(0.0)
              .build();

          var result = client.chat().completions().create(request);
      }
  }
  ```

  ```csharp theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  using System;
  using System.Threading.Tasks;
  using Braintrust.Sdk;
  using Braintrust.Sdk.OpenAI;
  using OpenAI;
  using OpenAI.Chat;

  class OpenAITracing
  {
      static async Task Main(string[] args)
      {
          var braintrust = Braintrust.Sdk.Braintrust.Get();
          var activitySource = braintrust.GetActivitySource();

          var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
          if (string.IsNullOrEmpty(apiKey))
          {
              Console.WriteLine("Error: OPENAI_API_KEY environment variable is not set.");
              return;
          }

          // Wrap the OpenAI client with Braintrust instrumentation
          var client = BraintrustOpenAI.WrapOpenAI(
              activitySource,
              apiKey
          );

          // All API calls are automatically logged
          var chatClient = client.GetChatClient("gpt-4o-mini");
          var messages = new ChatMessage[]
          {
              new SystemChatMessage("You are a helpful assistant."),
              new UserChatMessage("What is machine learning?")
          };

          var result = await chatClient.CompleteChatAsync(messages);
      }
  }
  ```
</CodeGroup>

### Stream OpenAI responses

`wrap_openai`/`wrapOpenAI` can automatically log metrics like `prompt_tokens`, `completion_tokens`, and `tokens` for streaming LLM calls if the LLM API returns them. Set `include_usage` to `true` in the `stream_options` parameter to receive these metrics from OpenAI.

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  model: "gpt-5-mini",
    messages: [{ role: "user", content: "Count to 10" }],
    stream: true,
    stream_options: {
      include_usage: true, // Required for token metrics
    },
  });

  for await (const chunk of result) {
    process.stdout.write(chunk.choices[0]?.delta?.content || "");
  }
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  model="gpt-5-mini",
      messages=[{"role": "user", "content": "Count to 10"}],
      stream=True,
      stream_options={"include_usage": True},  # Required for token metrics
  )

  for chunk in result:
      print(chunk.choices[0].delta.content or "", end="")
  ```
</CodeGroup>

## Evaluate with OpenAI

Evaluations help you distill the non-deterministic outputs of OpenAI models into an effective feedback loop that enables you to ship more reliable, higher quality products. Braintrust `Eval` is a simple function composed of a dataset of user inputs, a task, and a set of scorers. To learn more about evaluations, see the [Experiments](/evaluate/run-evaluations) guide.

### Basic OpenAI eval setup

Evaluate the outputs of OpenAI models with Braintrust.

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import { Eval } from "braintrust";
  import { OpenAI } from "openai";

  const client = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
  });

  Eval("OpenAI Evaluation", {
    // An array of user inputs and expected outputs
    data: () => [
      { input: "What is 2+2?", expected: "4" },
      { input: "What is the capital of France?", expected: "Paris" },
    ],
    task: async (input) => {
      // Your OpenAI LLM call
      const response = await client.chat.completions.create({
        model: "gpt-5-mini",
        messages: [{ role: "user", content: input }],
      });
      return response.choices[0].message.content;
    },
    scores: [
      {
        name: "accuracy",
        // A simple scorer that returns 1 if the output matches the expected output, 0 otherwise
        scorer: (args) => (args.output === args.expected ? 1 : 0),
      },
    ],
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import os

  from braintrust import Eval
  from openai import OpenAI

  client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])


  def task(input):
      response = client.chat.completions.create(
          model="gpt-5-mini",
          messages=[{"role": "user", "content": input}],
      )
      return response.choices[0].message.content


  def accuracy_scorer(output, expected, **kwargs):
      return 1 if output == expected else 0


  Eval(
      "OpenAI Evaluation",
      data=[
          {"input": "What is 2+2?", "expected": "4"},
          {"input": "What is the capital of France?", "expected": "Paris"},
      ],
      task=task,
      scores=[accuracy_scorer],
  )
  ```

  ```go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  package main

  import (
  	"context"
  	"log"
  	"os"

  	"github.com/openai/openai-go"
  	"github.com/openai/openai-go/option"
  	"go.opentelemetry.io/otel"
  	"go.opentelemetry.io/otel/sdk/trace"

  	"github.com/braintrustdata/braintrust-sdk-go"
  	"github.com/braintrustdata/braintrust-sdk-go/eval"
  	traceopenai "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai"
  )

  func main() {
  	ctx := context.Background()

  	// Set up OpenTelemetry TracerProvider
  	tp := trace.NewTracerProvider()
  	defer tp.Shutdown(ctx)
  	otel.SetTracerProvider(tp)

  	// Initialize Braintrust
  	bt, err := braintrust.New(tp,
  		braintrust.WithAPIKey(os.Getenv("BRAINTRUST_API_KEY")),
  	)
  	if err != nil {
  		log.Fatal(err)
  	}

  	// Create OpenAI client with tracing
  	client := openai.NewClient(
  		option.WithMiddleware(traceopenai.NewMiddleware()),
  	)

  	// Create evaluator
  	evaluator := braintrust.NewEvaluator[string, string](bt)

  	// Run evaluation
  	_, err = evaluator.Run(ctx, eval.Opts[string, string]{
  		Experiment: "OpenAI Evaluation",
  		// Dataset of user inputs and expected outputs
  		Dataset: eval.NewDataset([]eval.Case[string, string]{
  			{Input: "What is 2+2?", Expected: "4"},
  			{Input: "What is the capital of France?", Expected: "Paris"},
  		}),
  		// Task function with OpenAI LLM call
  		Task: eval.T(func(ctx context.Context, input string) (string, error) {
  			response, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
  				Model: openai.ChatModelGPT4oMini,
  				Messages: []openai.ChatCompletionMessageParamUnion{
  					openai.UserMessage(input),
  				},
  			})
  			if err != nil {
  				return "", err
  			}
  			return response.Choices[0].Message.Content, nil
  		}),
  		// Simple scorer that returns 1 if output matches expected, 0 otherwise
  		Scorers: []eval.Scorer[string, string]{
  			eval.NewScorer("accuracy", func(ctx context.Context, r eval.TaskResult[string, string]) (eval.Scores, error) {
  				score := 0.0
  				if r.Output == r.Expected {
  					score = 1.0
  				}
  				return eval.S(score), nil
  			}),
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  }
  ```

  ```ruby theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  require 'braintrust'
  require 'openai'

  Braintrust.init

  client = OpenAI::Client.new(api_key: ENV.fetch('OPENAI_API_KEY', nil))

  Braintrust::Eval.run(
    project: 'OpenAI Evaluation',
    experiment: 'basic-eval',
    # An array of user inputs and expected outputs
    cases: [
      { input: 'What is 2+2?', expected: '4' },
      { input: 'What is the capital of France?', expected: 'Paris' }
    ],
    # Your OpenAI LLM call
    task: lambda do |input|
      response = client.chat.completions.create(
        model: 'gpt-4o-mini',
        messages: [{ role: 'user', content: input }]
      )
      response.choices[0].message.content
    end,
    # A simple scorer that returns 1 if the output matches the expected output, 0 otherwise
    scorers: [
      Braintrust::Eval.scorer('accuracy') do |_input, expected, output|
        output == expected ? 1.0 : 0.0
      end
    ]
  )
  ```

  ```java theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import com.openai.client.OpenAIClient;
  import com.openai.client.okhttp.OpenAIOkHttpClient;
  import com.openai.models.ChatModel;
  import com.openai.models.chat.completions.ChatCompletionCreateParams;
  import dev.braintrust.Braintrust;
  import dev.braintrust.eval.DatasetCase;
  import dev.braintrust.eval.Scorer;
  import dev.braintrust.instrumentation.openai.BraintrustOpenAI;
  import java.util.function.Function;

  class OpenAIEvaluation {
      public static void main(String[] args) {
          var braintrust = Braintrust.get();
          var openTelemetry = braintrust.openTelemetryCreate();
          OpenAIClient client = BraintrustOpenAI.wrapOpenAI(openTelemetry, OpenAIOkHttpClient.fromEnv());

          Function<String, String> taskFunction = (String input) -> {
              var request = ChatCompletionCreateParams.builder()
                  .model(ChatModel.GPT_4O_MINI)
                  .addUserMessage(input)
                  .temperature(0.0)
                  .build();
              var response = client.chat().completions().create(request);
              return response.choices().get(0).message().content().orElse("");
          };

          var eval = braintrust.<String, String>evalBuilder()
              .name("OpenAI Evaluation")
              .cases(
                  DatasetCase.of("What is 2+2?", "4"),
                  DatasetCase.of("What is the capital of France?", "Paris"))
              .taskFunction(taskFunction)
              .scorers(
                  Scorer.of("contains_answer", (evalCase, output) ->
                      output.contains("4") || output.contains("Paris") ? 1.0 : 0.0))
              .build();

          var result = eval.run();
          System.out.println(result.createReportString());
      }
  }
  ```

  ```csharp theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  using System;
  using System.Threading.Tasks;
  using Braintrust.Sdk;
  using Braintrust.Sdk.Eval;
  using Braintrust.Sdk.OpenAI;
  using OpenAI;
  using OpenAI.Chat;

  class OpenAIEvaluation
  {
      static async Task Main(string[] args)
      {
          var braintrust = Braintrust.Sdk.Braintrust.Get();
          var activitySource = braintrust.GetActivitySource();

          var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
          if (string.IsNullOrEmpty(apiKey))
          {
              Console.WriteLine("Error: OPENAI_API_KEY environment variable is not set.");
              return;
          }

          var client = BraintrustOpenAI.WrapOpenAI(
              activitySource,
              apiKey
          );

          // Define the task function that uses OpenAI
          string TaskFunction(string input)
          {
              var chatClient = client.GetChatClient("gpt-4o-mini");
              var messages = new ChatMessage[]
              {
                  new UserChatMessage(input)
              };
              var options = new ChatCompletionOptions
              {
                  Temperature = 0.0f
              };
              var response = chatClient.CompleteChat(messages, options);
              return response.Value.Content[0].Text;
          }

          // Create and run the evaluation
          var eval = await braintrust
              .EvalBuilder<string, string>()
              .Name("OpenAI Evaluation")
              .Cases(
                  new DatasetCase<string, string>("What is 2+2?", "4"),
                  new DatasetCase<string, string>("What is the capital of France?", "Paris")
              )
              .TaskFunction(TaskFunction)
              .Scorers(
                  new FunctionScorer<string, string>("accuracy", (expected, actual) =>
                      actual.Contains(expected) ? 1.0 : 0.0)
              )
              .BuildAsync();

          var result = await eval.RunAsync();
          Console.WriteLine(result.CreateReportString());
      }
  }
  ```
</CodeGroup>

<Tip>
  Learn more about eval [data](/annotate/datasets) and [scorers](/evaluate/write-scorers).
</Tip>

### Use OpenAI as an LLM judge

You can use OpenAI models to score the outputs of other AI systems. This example uses the `LLMClassifierFromSpec` scorer to score the relevance of the outputs of an AI system.

Install the [`autoevals`](/evaluate/autoevals) package to use the `LLMClassifierFromSpec` scorer.

<CodeGroup>
  ```bash Typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # pnpm
  pnpm add autoevals
  # npm
  npm install autoevals
  ```

  ```bash Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  pip install autoevals
  ```
</CodeGroup>

Create a scorer that uses the `LLMClassifierFromSpec` scorer to score the relevance of the outputs of an AI system. You can then include `relevanceScorer` as a scorer in your `Eval` function (see above).

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import { LLMClassifierFromSpec } from "autoevals";

  const relevanceScorer = LLMClassifierFromSpec("Relevance", {
    choice_scores: { Relevant: 1, Irrelevant: 0 },
    model: "gpt-5-mini",
    use_cot: true,
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  from autoevals import LLMClassifierFromSpec

  relevance_scorer = LLMClassifierFromSpec(
      "Relevance",
      choice_scores={"Relevant": 1, "Irrelevant": 0},
      model="gpt-5-mini",
      use_cot=True,
  )
  ```
</CodeGroup>

## Additional features

### Structured outputs

OpenAI's structured outputs are supported with the wrapper functions.

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import { z } from "zod";

  // Define a Zod schema for the response
  const ResponseSchema = z.object({
    name: z.string(),
    age: z.number(),
  });

  const completion = await client.beta.chat.completions.parse({
    model: "gpt-5-mini",
    messages: [
      { role: "system", content: "Extract the person's name and age." },
      { role: "user", content: "My name is John and I'm 30 years old." },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "person",
        // The Zod schema for the response
        schema: ResponseSchema,
      },
    },
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  from pydantic import BaseModel


  class Person(BaseModel):
      name: str
      age: int


  completion = client.beta.chat.completions.parse(
      model="gpt-5-mini",
      messages=[
          {"role": "system", "content": "Extract the person's name and age."},
          {"role": "user", "content": "My name is John and I'm 30 years old."},
      ],
      response_format=Person,
  )
  ```
</CodeGroup>

### Function calling and tools

Braintrust supports OpenAI function calling for building AI agents with tools.

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  const tools = [
    {
      type: "function" as const,
      function: {
        name: "get_weather",
        description: "Get current weather for a location",
        parameters: {
          type: "object",
          properties: {
            location: { type: "string" },
          },
          required: ["location"],
        },
      },
    },
  ];

  const response = await client.chat.completions.create({
    model: "gpt-5-mini",
    messages: [{ role: "user", content: "What's the weather in San Francisco?" }],
    tools,
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  tools = [
      {
          "type": "function",
          "function": {
              "name": "get_weather",
              "description": "Get current weather for a location",
              "parameters": {
                  "type": "object",
                  "properties": {
                      "location": {"type": "string"},
                  },
                  "required": ["location"],
              },
          },
      }
  ]

  response = client.chat.completions.create(
      model="gpt-5-mini",
      messages=[{"role": "user", "content": "What's the weather in San Francisco?"}],
      tools=tools,
  )
  ```
</CodeGroup>

### Streaming audio transcriptions

Braintrust traces streaming audio transcription calls for sync and async OpenAI clients. Each span captures the audio file as an attachment and the final transcript as the span output.

<CodeGroup dropdown>
  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  with open("audio.m4a", "rb") as f:
      stream = client.audio.transcriptions.create(
          model="gpt-4o-transcribe",
          file=f,
          stream=True,
      )
      for event in stream:
          if event.type == "transcript.text.delta":
              print(event.delta, end="", flush=True)
  ```
</CodeGroup>

### Multimodal content, attachments, errors, and masking sensitive data

To learn more about these topics, check out the [customize traces](/instrument/advanced-tracing) guide.

## Use OpenAI with Braintrust gateway

You can also access OpenAI models through the [Braintrust gateway](/deploy/gateway), which provides a unified interface for multiple providers. Use any [supported provider's SDK](/integrations/ai-providers) to call OpenAI models.

<CodeGroup dropdown>
  ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  const client = new OpenAI({
    baseURL: "https://gateway.braintrust.dev/v1",

    apiKey: process.env.BRAINTRUST_API_KEY,
  });

  const response = await client.chat.completions.create({
    model: "gpt-5-mini",
    messages: [{ role: "user", content: "What is a proxy?" }],
    seed: 1, // A seed activates the proxy's cache
  });
  ```

  ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://gateway.braintrust.dev/v1",
      api_key=os.environ["BRAINTRUST_API_KEY"],
  )

  response = client.chat.completions.create(
      model="gpt-5-mini",
      messages=[{"role": "user", "content": "What is a proxy?"}],
      seed=1,  # A seed activates the proxy's cache
  )
  ```

  ```go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  package main

  import (
  	"context"
  	"log"
  	"os"

  	"github.com/openai/openai-go"
  	"github.com/openai/openai-go/option"
  )

  func main() {
  	ctx := context.Background()

  	client := openai.NewClient(
  		option.WithBaseURL("https://gateway.braintrust.dev/v1"),
  		option.WithAPIKey(os.Getenv("BRAINTRUST_API_KEY")),
  	)

  	response, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
  		Model: openai.ChatModelGPT4oMini,
  		Messages: []openai.ChatCompletionMessageParamUnion{
  			openai.UserMessage("What is a proxy?"),
  		},
  		Seed: openai.Int(1), // A seed activates the proxy's cache
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	_ = response
  }
  ```

  ```ruby theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  require 'openai'

  client = OpenAI::Client.new(
    base_url: 'https://gateway.braintrust.dev/v1',
    api_key: ENV.fetch('BRAINTRUST_API_KEY', nil)
  )

  client.chat.completions.create(
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'What is a proxy?' }],
    seed: 1 # A seed activates the proxy's cache
  )
  ```

  ```java theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import com.openai.client.OpenAIClient;
  import com.openai.client.okhttp.OpenAIOkHttpClient;
  import com.openai.models.ChatModel;
  import com.openai.models.chat.completions.ChatCompletionCreateParams;

  class OpenAIProxy {
      public static void main(String[] args) {
          OpenAIClient client = OpenAIOkHttpClient.builder()
              .apiKey(System.getenv("BRAINTRUST_API_KEY"))
              .baseUrl("https://gateway.braintrust.dev/v1")
              .build();

          var response = client.chat().completions().create(
              ChatCompletionCreateParams.builder()
                  .model(ChatModel.GPT_4O_MINI)
                  .addUserMessage("What is a proxy?")
                  .seed(1L) // A seed activates the proxy's cache
                  .build());
      }
  }
  ```

  ```csharp theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  using System;
  using System.Threading.Tasks;
  using OpenAI;
  using OpenAI.Chat;

  class OpenAIProxy
  {
      static async Task Main(string[] args)
      {
          var apiKey = Environment.GetEnvironmentVariable("BRAINTRUST_API_KEY");
          if (string.IsNullOrEmpty(apiKey))
          {
              Console.WriteLine("Error: BRAINTRUST_API_KEY environment variable is not set.");
              return;
          }

          var client = new OpenAIClient(
              new System.ClientModel.ApiKeyCredential(apiKey),
              new OpenAIClientOptions
              {
                  Endpoint = new Uri("https://gateway.braintrust.dev/v1")
              }
          );

          var chatClient = client.GetChatClient("gpt-4o-mini");
          var messages = new ChatMessage[]
          {
              new UserChatMessage("What is a proxy?")
          };

          var response = await chatClient.CompleteChatAsync(messages);
      }
  }
  ```
</CodeGroup>

### Generate embeddings

The gateway also supports the OpenAI-compatible `/embeddings` endpoint for generating embeddings. See [Generate embeddings](/deploy/gateway#generate-embeddings) for an example.

## Cookbooks

* [Evaluating audio with the OpenAI Realtime API](/cookbook/recipes/Realtime)
* [Using Python functions to extract text from images](/cookbook/recipes/ToolOCR)
* [Using functions to build a RAG agent](/cookbook/recipes/ToolRAG)
