Vercel AI SDK
The ai package with an OpenAI-shaped provider. For the Anthropic and Google providers, see Vercel AI SDK (Anthropic) and Vercel AI SDK (Google).
Connect
Use createOpenAICompatible with supportsStructuredOutputs: true:
const baseURL = process.env.PLUGBOARD_BASE_URL! // ends in /v1
const apiKey = process.env.PLUGBOARD_KEY!
// 1. createOpenAICompatible: Chat Completions. supportsStructuredOutputs sends json_schema for Output.object (structured.ts).
export const compat = createOpenAICompatible({ name: "plugboard", baseURL, apiKey, includeUsage: true, supportsStructuredOutputs: true })
// 2. openai.chat(id): Chat Completions through @ai-sdk/openai.
// 3. openai(id): the default. In @ai-sdk/openai v4 it is the Responses API (POST /v1/responses).
export const openai = createOpenAI({ baseURL, apiKey })The snippets below call client(model), a function from a model id to a model; model is an alias such as "fast" or any allowed provider/model[#variant].
@ai-sdk/openai also works. Its default openai(id) uses the Responses API; openai.chat(id) uses Chat Completions.
Chat
const { text, finishReason, usage } = await generateText({ model: client(model), prompt: "Reply with exactly: pong", maxOutputTokens: 1024 })Tool calls
The SDK runs execute and sends the follow-up request. Plugboard only returns the call.
const get_weather = tool({
description: "Current weather for a city",
inputSchema: z.object({ city: z.string().describe("City name") }),
execute: async ({ city }) => {
cities.push(city)
return weatherResult
},
})
const result = await generateText({ model: client(model), tools: { get_weather }, stopWhen: isStepCount(4), prompt: PROMPT, maxOutputTokens: 1024 })Structured output
const { output } = await generateText({ model: client(model), output: Output.object({ schema: Meal }), prompt: PROMPT, maxOutputTokens: 1024 })Multi-turn on the Responses API
openai(id) sends store: true, so later turns refer to earlier answers by item_reference. Plugboard resolves those while it holds the answer (one hour, the last 1000 per app). For long-lived chats, pass providerOptions: { openai: { store: false } } so the SDK sends earlier turns in full:
const get_weather = tool({
description: "Current weather for a city",
inputSchema: z.object({ city: z.string().describe("City name") }),
execute: async ({ city }) => {
cities.push(city)
return weatherResult
},
})
const result = await generateText({
model: client(model),
tools: { get_weather },
stopWhen: isStepCount(4),
prompt: PROMPT,
maxOutputTokens: 1024,
providerOptions: { openai: { store: false } },
})Limits
- Without
supportsStructuredOutputs: true,createOpenAICompatiblesendsresponse_format: json_objectwith no schema, the model guesses the keys, andOutput.objectthrowsNoObjectGeneratedError. - The SDK has no model-list call. Use
fetchonGET /v1/models. - The schema in structured output is not enforced by the provider. Validate the answer.