---
title: "OpenAI"
description: "Use the OpenAI API for MainSDK AI calls and embeddings - API keys, main.yaml, the model allowlist, data-use rules, local testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/openai"
updated: "2026-10-28"
---

# OpenAI

> Use the OpenAI API for MainSDK AI calls and embeddings - API keys, main.yaml, the model allowlist, data-use rules, local testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/openai · Updated: 2026-10-28

OpenAI makes the GPT models and embedding models, and its API is one of the drivers behind [`ai`](https://mainsdk.dev/docs/interfaces/ai). Your app calls `ai.generate()` and `ai.embed()`; the driver sends the redacted prompt to the OpenAI API. Pick it when your features are tuned for OpenAI models, when you want OpenAI embeddings for search, or as a fallback next to Amazon Bedrock, the default driver.

## Interfaces it serves

### AI calls (`ai`)

- Status: Building for 0.3 · ships as a beta API
- Driver: `openai` (OpenAI)
- Docs: https://mainsdk.dev/docs/interfaces/ai.md

```yaml
ai:
  driver: openai
```

Swap to another provider: `local`, `anthropic`, `gateway`, `bedrock`, `ollama`, `llama-cpp`, `openai-compatible`.

## Before you start

You need an OpenAI platform account with API access.

1. **Create a project and an API key.** In the OpenAI platform settings, create a project for your app and a key scoped to it. Use separate keys per environment so you can revoke one at a time.
2. **Set usage limits on the project.** MainSDK caps spend in your app; a provider-side limit is a second line of defence.
3. **Review the data controls for your organisation.** `ai.data` requires no training and no retention. Check how OpenAI handles API inputs for your organisation, and whether the retention your `main.yaml` asks for needs an arrangement with OpenAI.

Store the key in your secrets manager, never in code or a committed env file.

## Configure

```yaml title="main.yaml"
ai:
  driver: openai
  key: secret:OPENAI_API_KEY         # suggested name; [TBD] key field name for drivers that need one
  models: [openai/gpt-*, openai/text-embedding-*]   # allowlist
  data: { training: never, retention: zero }
  limits: { per-user: $1/day, total: $500/month }
```

The key is always a `secret:` reference; a literal key fails `mainsdk check`. OpenAI's API host comes from the driver's declared hosts, so you don't add it to `network.allow`.

## Use it

Generate text:

```ts title="lib/classify-ticket.ts"
import { ai } from "mainsdk";

export async function classifyTicket(text: string, user: { id: string }) {
  return ai.generate({
    model: "openai/gpt-4o-mini",               // [TBD] model identifiers per driver
    feature: "ticket-triage",
    user,
    prompt: `Reply with one word, billing, bug, account or other, for this ticket:\n${text}`,
  });
}
```

Embed text for search:

```ts title="lib/embed-products.ts"
import { ai } from "mainsdk";

export async function embedProducts(descriptions: string[]) {
  return ai.embed({
    model: "openai/text-embedding-3-small",    // [TBD] model identifiers per driver
    input: descriptions,
    feature: "product-search",
  });                                          // number[][]
}
```

## Local development and testing

- **No key:** set `ai.driver: local` in `main.env.dev.yaml` to use the built-in local fake.
- **Real calls in development:** use a development key with a low cap in the dev overlay, for example `limits: { total: $10/month }`.
- **Tests:** `createTestApp()` from `@mainsdk/testing` runs `ai` on its in-memory fake with redaction, caps and audit enforced. `chaos.on("ai:openai", { outage: true })` simulates an OpenAI outage. The spec's conformance suite runs the OpenAI driver against recorded responses.

```ts title="lib/classify-ticket.test.ts"
import { it } from "node:test";
import { createTestApp, chaos } from "@mainsdk/testing";
import { classifyTicket } from "./classify-ticket";

it("keeps triage working when openai is down", async () => {
  createTestApp({ main: "./main.yaml" });   // with a second driver under fallback.ai
  chaos.on("ai:openai", { outage: true });
  await classifyTicket("I was charged twice", { id: "u_1" });
});
```

## What MainSDK adds on top

- The API key never in your code, only a `secret:` reference.
- Providers, models or account modes that train on or keep prompts are refused; a declaration that doesn't meet `ai.data` fails `mainsdk check` with `MAIN-AI-0001`.
- Personal data redacted before the model sees it, and restored only inside your app.
- Spend limits per user, per feature and in total, checked before the call (`MAIN-AI-0007` at the limit).
- Every call, embeddings included, audited with feature, model, tokens and cost, never the prompt.

See [AI calls](https://mainsdk.dev/docs/interfaces/ai) for the full contract.

## Limits and notes

- The OpenAI driver comes with the `ai` spec (phase 1, milestone 0.3).
- The name of the key field for keyed AI drivers is not final [TBD].
- How "no retention" is proven for a provider is an open question in the spec [TBD].
- If prompts must stay in a MainSDK region (US, EU or India), check where OpenAI processes data for your organisation, or use Bedrock with a region set.
- Embeddings from different models are not interchangeable. If you swap drivers, re-embed stored vectors with the new model.
- `ai.raw()` returns the OpenAI client for features `ai` does not wrap. `mainsdk check` lists every use.

## Swap to or from it

AI calls are stateless, so a swap is instant once `mainsdk swap` has run the contract tests:

```yaml title="main.yaml"
ai:
  driver: openai                     # was bedrock
  key: secret:OPENAI_API_KEY         # [TBD] key field name
```

Update `ai.models` to models the new driver serves. Stored embeddings are the one piece of state: vectors made by one model must be rebuilt with the new one before search uses them.

## FAQ

**Can I use OpenAI for embeddings and another provider for chat?** One `ai` block names one driver. Running two drivers side by side is not in the `ai@1` contract [TBD]; `fallback.ai` covers failover only.

**Where does my OpenAI key go?** In your secrets manager, referenced as `secret:OPENAI_API_KEY`, read on the server only.

**Does streaming work?** Token-by-token streaming is not in the `ai@1` contract yet [TBD].

## Next

- [AI calls](https://mainsdk.dev/docs/interfaces/ai)
- [Amazon Bedrock](https://mainsdk.dev/docs/integrations/amazon-bedrock), [Anthropic](https://mainsdk.dev/docs/integrations/anthropic) and [AI gateway](https://mainsdk.dev/docs/integrations/ai-gateway)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
