@ai-sdk/openai
The official OpenAI provider for Vercel's AI SDK. It does nothing on its own; it plugs OpenAI's Responses, Chat Completions, embeddings, image, transcription, and speech endpoints into the AI SDK's provider-agnostic functions (generateText, streamText, ToolLoopAgent), so the same call sites can later point at Anthropic or Google by swapping one import. You install it next to the core ai package and pass openai('gpt-5-mini') wherever a model is expected. It lives in the vercel/ai monorepo and versions in lockstep with the core SDK.
If you are on the AI SDK, this is the OpenAI door you walk through and it works well; the trade is Vercel's release cadence plus an ESM and Node 22 floor. If you are not otherwise using the AI SDK, the first-party openai package is the simpler dependency.
Use it if
- You already build on the AI SDK (generateText, streamText, useChat) and need OpenAI models as one of your options
- You want the option to swap OpenAI for Anthropic or Google later by changing an import instead of rewriting call sites
- You need OpenAI-specific surfaces (Responses API, hosted tools like image generation and local shell, transcription, speech) with AI SDK types
- You stream into a React, Svelte, or Vue UI and want the SDK's UI hooks to handle the wire format
- You only ever call OpenAI: the first-party openai package tracks new API features sooner and has no core-plus-provider version pairing to keep compatible
- Your stack cannot move yet: the package is ESM-only and its engines field demands Node 22+, which rules out CommonJS codebases and older LTS runtimes
- You dislike churn: the AI SDK ships a new major roughly yearly (core is on v7, this provider on v4), and every major means codemods and renamed options
- You already route through the Vercel AI Gateway: the core ai package accepts 'openai/gpt-5.4' model strings without this package, so you may not need it at all
Setup reality
npm i ai @ai-sdk/openai, set OPENAI_API_KEY, and generateText works in a few lines. The friction is environmental: the package is ESM-only with a Node 22+ floor, zod rides along as a peer dependency, and the core ai package plus every @ai-sdk/* provider must be on compatible majors, so upgrades arrive as a coordinated bump with a migration guide. The web is littered with snippets from the v3/v4/v5 eras that no longer compile, so always check which major a tutorial targets. Also note the default openai() instance now hits the Responses API; use openai.chat() when you specifically need Chat Completions behavior.
Patterns
Generate text with an OpenAI modelbasic-generation
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
const { text } = await generateText({
model: openai('gpt-5-mini'),
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
});OPENAI_API_KEY is read from the environment automatically. The default openai() instance targets the Responses API, not Chat Completions.
Stream tokens as they arrivestreaming
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
const result = streamText({
model: openai('gpt-5-mini'),
prompt: 'Explain the Node.js event loop briefly.',
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}streamText does not await the request itself; nothing happens until you consume textStream or hand the result to a response helper.
Custom instance with createOpenAIcustom-provider-instance
import { createOpenAI } from '@ai-sdk/openai';
const openai = createOpenAI({
apiKey: process.env.MY_OPENAI_KEY,
baseURL: 'https://my-proxy.internal/v1',
});
const model = openai('gpt-5.4');baseURL lets you point at OpenAI-compatible proxies. For Azure OpenAI use the separate @ai-sdk/azure package instead of overriding the URL here.
Pick Responses vs Chat Completionsresponses-vs-chat
import { openai } from '@ai-sdk/openai';
const responsesModel = openai('gpt-5.4'); // Responses API (default)
const chatModel = openai.chat('gpt-5.4'); // classic Chat CompletionsThe default changed to the Responses API in a past major; if a provider option or a proxy only understands Chat Completions, be explicit with openai.chat().
Structured output with a zod schemastructured-output
import { openai } from '@ai-sdk/openai';
import { generateText, Output } from 'ai';
import { z } from 'zod';
const { output } = await generateText({
model: openai('gpt-5.4'),
output: Output.object({
schema: z.object({
recipe: z.object({
name: z.string(),
steps: z.array(z.string()),
}),
}),
}),
prompt: 'Generate a lasagna recipe.',
});Read output, not text, when an output spec is set. zod is a peer dependency of the provider, so keep its version inside the supported range.
Embeddings via textEmbeddingembeddings
import { openai } from '@ai-sdk/openai';
import { embed } from 'ai';
const { embedding } = await embed({
model: openai.textEmbedding('text-embedding-3-small'),
value: 'sunny day at the beach',
});The factory is textEmbedding; older snippets call openai.embedding(), which no longer exists after the rename.
Agent with a hosted local shell tooltool-loop-agent
import { openai } from '@ai-sdk/openai';
import { ToolLoopAgent } from 'ai';
const agent = new ToolLoopAgent({
model: openai('gpt-5.4'),
system: 'You are an agent with access to a shell environment.',
tools: {
shell: openai.tools.localShell({
execute: async ({ action }) => {
const [cmd, ...args] = action.command;
const out = await runInSandbox(cmd, args); // your sandbox
return { output: out };
},
}),
},
});openai.tools exposes OpenAI-hosted tool types; you still supply the execute implementation, and you are responsible for sandboxing anything shell-like.
Image generation inside an agentimage-generation-tool
import { openai } from '@ai-sdk/openai';
import { ToolLoopAgent, InferAgentUIMessage } from 'ai';
export const imageAgent = new ToolLoopAgent({
model: openai('gpt-5.4'),
tools: {
generateImage: openai.tools.imageGeneration({
partialImages: 3,
}),
},
});
export type ImageAgentMessage = InferAgentUIMessage<typeof imageAgent>;partialImages streams intermediate renders to the UI; the final image arrives base64-encoded in the tool output.
Next.js route streaming agent messagesagent-ui-route
import { imageAgent } from '@/agent/image-agent';
import { createAgentUIStreamResponse } from 'ai';
export async function POST(req: Request) {
const { messages } = await req.json();
return createAgentUIStreamResponse({
agent: imageAgent,
messages,
});
}Pair this with useChat from @ai-sdk/react on the client; the hook and the stream response speak the same UI message protocol.
Skip the provider via AI Gatewaygateway-model-string
import { generateText } from 'ai';
const { text } = await generateText({
model: 'openai/gpt-5.4', // routed through Vercel AI Gateway
prompt: 'Hello!',
});Plain model strings go through Vercel's gateway with no @ai-sdk/openai install. You only need this package when calling OpenAI directly with your own key.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| openai | npm | You talk only to OpenAI and want the first-party SDK that gets new endpoints on day one |
| langchain | npm | You want a full framework with chains, retrieval, and a large agent ecosystem rather than a thin call layer |
| llamaindex | npm | Your app is retrieval-centric and you want data connectors and indexes, not just model calls |