- name
- ai-sdk
- description
- Vercel AI SDK expert guidance. Use when building AI-powered features — chat interfaces, text generation, structured output, tool calling, agents, MCP integration, streaming, embeddings, reranking, image generation, or working with any LLM provider.
- metadata
- {"priority":8,"docs":["https://sdk.vercel.ai/docs","https://sdk.vercel.ai/docs/reference"],"sitemap":"https://sdk.vercel.ai/sitemap.xml","pathPatterns":["app/api/chat/**","app/api/completion/**","src/app/api/chat/**","src/app/api/completion/**","pages/api/chat.*","pages/api/chat/**","pages/api/completion.*","pages/api/completion/**","src/pages/api/chat.*","src/pages/api/chat/**","src/pages/api/completion.*","src/pages/api/completion/**","lib/ai/**","src/lib/ai/**","lib/ai.*","src/lib/ai.*","ai/**","apps/*/app/api/chat/**","apps/*/app/api/completion/**","apps/*/src/app/api/chat/**","apps/*/src/app/api/completion/**","apps/*/lib/ai/**","apps/*/src/lib/ai/**","lib/agent.*","src/lib/agent.*","app/actions/chat.*","src/app/actions/chat.*"],"importPatterns":["ai","@ai-sdk/*"],"bashPatterns":["\\bnpm\\s+(install|i|add)\\s+[^\\n]*\\bai\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*\\bai\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*\\bai\\b","\\byarn\\s+add\\s+[^\\n]*\\bai\\b","\\bnpm\\s+(install|i|add)\\s+[^\\n]*@ai-sdk/","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@ai-sdk/","\\bbun\\s+(install|i|add)\\s+[^\\n]*@ai-sdk/","\\byarn\\s+add\\s+[^\\n]*@ai-sdk/","\\bnpx\\s+@ai-sdk/devtools\\b","\\bnpx\\s+@ai-sdk/codemod\\b","\\bnpx\\s+mcp-to-ai-sdk\\b"],"promptSignals":{"phrases":["ai sdk","vercel ai","generatetext","streamtext"],"allOf":["[Truncated]","[Truncated]"],"anyOf":["usechat","usecompletion","tool calling","embeddings"],"noneOf":["openai api directly"],"minScore":6}}
# Vercel AI SDK (v6)
> **CRITICAL — Your training data is outdated for this library.** AI SDK v6 has breaking changes from v5 and earlier that you will get wrong if you guess. Before writing AI SDK code, **fetch the docs** at https://ai-sdk.dev/docs to find the correct function signatures, return types, and patterns. Key things that have changed: `generateObject()` removal, `streamObject()` removal, `result.files` for image generation, `Output.object()` for structured streaming, `ToolLoopAgent` class (not `Agent`), `useChat` transport API, and provider package versions. Search the docs for working examples that match your exact use case — do not rely on your training data for API shapes.
You are an expert in the Vercel AI SDK v6. The AI SDK is the leading TypeScript toolkit for building AI-powered applications. It provides a unified API across all LLM providers.
## v6 Migration Pitfalls (Read First)
- `ai@^6.0.0` is the umbrella package for AI SDK v6 (latest: 6.0.83).
- `@ai-sdk/react` is `^3.0.x` in v6 projects (NOT `^6.0.0`).
- `@ai-sdk/gateway` is `^3.x` in v6 projects (NOT `^1.x`).
- In `createUIMessageStream`, write with `stream.writer.write(...)` (NOT `stream.write(...)`).
- `useChat` no longer supports `body` or `onResponse`; configure behavior through `transport`.
- UI tool parts are typed as `tool-<toolName>` (for example `tool-weather`), not `tool-invocation`.
- `DynamicToolCall` does not provide typed `.args`; cast via `unknown` first.
- `TypedToolResult` exposes `.output` (NOT `.result`).
- The agent class is `ToolLoopAgent` (NOT `Agent` — `Agent` is just an interface).
- Constructor uses `instructions` (NOT `system`).
- Agent methods are `agent.generate()` and `agent.stream()` (NOT `agent.generateText()` or `agent.streamText()`).
- AI Gateway does not support embeddings; use `@ai-sdk/openai` directly for `openai.embedding(...)`.
- `useChat()` with no transport defaults to `DefaultChatTransport({ api: '/api/chat' })` — explicit transport only needed for custom endpoints or `DirectChatTransport`.
- Default `stopWhen` for ToolLoopAgent is `stepCountIs(20)`, not `stepCountIs(1)` — override if you need fewer steps.
- `strict: true` on tools is opt-in per tool, not global — only set on tools with provider-compatible schemas.
- For agent API routes, use `createAgentUIStreamResponse({ agent, uiMessages })` instead of manual `streamText` + `toUIMessageStreamResponse()`.
- `@ai-sdk/azure` now uses the Responses API by default — use `azure.chat()` for the previous Chat Completions API behavior.
- `@ai-sdk/azure` uses `azure` (not `openai`) as the key for `providerMetadata` and `providerOptions`.
- `@ai-sdk/google-vertex` uses `vertex` (not `google`) as the key for `providerMetadata` and `providerOptions`.
- `@ai-sdk/anthropic` supports native structured outputs via `structuredOutputMode` option (Anthropic Sonnet 4.5+).
## Installation
```bash
npm install ai@^6.0.0 @ai-sdk/react@^3.0.0
npm install @ai-sdk/openai@^3.0.41 # Optional: required for embeddings
npm install @ai-sdk/anthropic@^3.0.58 # Optional: direct Anthropic provider access
npm install @ai-sdk/vercel@^2.0.37 # Optional: v0 model provider (v0-1.0-md)
```
> **`@ai-sdk/react` is a separate package** — it is NOT included in the `ai` package. For v6 projects, install `@ai-sdk/react@^3.0.x` alongside `ai@^6.0.0`.
> **If you install `@ai-sdk/gateway` directly, use `@ai-sdk/gateway@^3.x`** (NOT `^1.x`).
> **Only install a direct provider SDK** (e.g., `@ai-sdk/anthropic`) if you need provider-specific features not exposed through the gateway.
## What AI SDK Can Do
AI SDK is not just text — it handles **text, images, structured data, tool calling, and agents** through one unified API:
| Need | How |
|------|-----|
| Text generation / chat | `generateText()` or `streamText()` with `model: "openai/gpt-5.4"` |
| **Image generation** | `generateText()` with `model: "google/gemini-3.1-flash-image-preview"` — images in `result.files`. **Always use this model, never older gemini-2.x models** |
| Structured JSON output | `generateText()` with `output: Output.object({ schema })` |
| Tool calling / agents | `generateText()` with `tools: { ... }` or `ToolLoopAgent` |
| Embeddings | `embed()` / `embedMany()` with `@ai-sdk/openai` |
**If the product needs generated images** (portraits, posters, cover art, illustrations, comics, diagrams), use `generateText` with an image model — do NOT use placeholder images or skip image generation.
## Setup for AI Projects
For the smoothest experience, link to a Vercel project so AI Gateway credentials are auto-provisioned via OIDC:
```bash
vercel link # Connect to your Vercel project
# Enable AI Gateway at https://vercel.com/{team}/{project}/settings → AI Gateway
vercel env pull .env.local # Provisions VERCEL_OIDC_TOKEN automatically
npm install ai@^6.0.0 # Gateway is built in
npx ai-elements # Required: install AI text rendering components
```
This gives you AI Gateway access with OIDC authentication, cost tracking, failover, and observability — no manual API keys needed.
**OIDC is the default auth**: `vercel env pull` provisions a `VERCEL_OIDC_TOKEN` (short-lived JWT, ~24h). The `@ai-sdk/gateway` reads it automatically via `@vercel/oidc`. On Vercel deployments, tokens auto-refresh. For local dev, re-run `vercel env pull` when the token expires. No `AI_GATEWAY_API_KEY` or provider-specific keys needed.
## Global Provider System (AI Gateway — Default)
In AI SDK 6, pass a `"provider/model"` string to the `model` parameter — it automatically routes through the Vercel AI Gateway:
```ts
import { generateText } from "ai";
const { text } = await generateText({
model: "openai/gpt-5.4", // plain string — routes through AI Gateway automatically
prompt: "Hello!",
});
```
No `gateway()` wrapper needed — plain `"provider/model"` strings are the simplest approach and are what the official Vercel docs recommend. The `gateway()` function is an optional explicit wrapper (useful when you need `providerOptions.gateway` for routing, failover, or tags):
```ts
import { gateway } from "ai";
// Explicit gateway() — only needed for advanced providerOptions
const { text } = await generateText({
model: gateway("openai/gpt-5.4"),
providerOptions: { gateway: { order: ["openai", "azure-openai"] } },
});
```
Both approaches provide failover, cost tracking, and observability on Vercel.
**Model slug rules**: Always use `provider/model` format. Version numbers use **dots**, not hyphens: `anthropic/claude-sonnet-4.6` (not `claude-sonnet-4-6`). Default to `openai/gpt-5.4` or `anthropic/claude-sonnet-4.6`. Never use outdated models like `gpt-4o`.
> AI Gateway does not support embeddings. Use a direct provider SDK such as `@ai-sdk/openai` for embeddings.
> **Direct provider SDKs** (`@ai-sdk/openai`, `@ai-sdk/anthropic`, etc.) are only needed for provider-specific features not exposed through the gateway (e.g., Anthropic computer use, OpenAI fine-tuned model endpoints).
## Core Functions
### Text Generation
```ts
import { generateText, streamText } from "ai";
// Non-streaming
const { text } = await generateText({
model: "openai/gpt-5.4",
prompt: "Explain quantum computing in simple terms.",
});
// Streaming
const result = streamText({
model: "openai/gpt-5.4",
prompt: "Write a poem about coding.",
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
```
### Structured Output
**`generateObject` was removed in AI SDK v6.** Use `generateText` with `output: Output.object()` instead. Do NOT import `generateObject` — it does not exist.
```ts
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(),
ingredients: z.array(
z.object({
name: z.string(),
amount: z.string(),
}),
),
steps: z.array(z.string()),
}),
}),
}),
prompt: "Generate a recipe for chocolate chip cookies.",
});
```
### Tool Calling (MCP-Aligned)
In AI SDK 6, tools use `inputSchema` (not `parameters`) and `output`/`outputSchema` (not `result`), aligned with the MCP specification. Per-tool `strict` mode ensures providers only generate valid tool calls matching your schema.
```ts
import { generateText, tool } from "ai";
import { z } from "zod";
const result = await generateText({
model: "openai/gpt-5.4",
tools: {
weather: tool({
description: "Get the weather for a location",
inputSchema: z.object({
city: z.string().describe("The city name"),
}),
outputSchema: z.object({
temperature: z.number(),
condition: z.string(),
}),
strict: true, // Providers generate only schema-valid tool calls
execute: async ({ city }) => {
const data = await fetchWeather(city);
return { temperature: data.temp, condition: data.condition };
},
}),
},
prompt: "What is the weather in San Francisco?",
});
```
### Dynamic Tools (MCP Integration)
For tools with schemas not known at compile time (e.g., MCP server tools):
```ts
import { dynamicTool } from "ai";
const tools = {
unknownTool: dynamicTool({
description: "A tool discovered at runtime",
execute: async (input) => {
// Handle dynamically
return { result: "done" };
},
}),
};
```
### Agents
The `ToolLoopAgent` class wraps `generateText`/`streamText` with an agentic tool-calling loop.
Default `stopWhen` is `stepCountIs(20)` (up to 20 tool-calling steps).
`Agent` is an interface — `ToolLoopAgent` is the concrete implementation.
```ts
import { ToolLoopAgent, stepCountIs, hasToolCall } from "ai";
const agent = new ToolLoopAgent({
model: "anthropic/claude-sonnet-4.6",
tools: { weather, search, calculator, finalAnswer },
instructions: "You are a helpful assistant.",
// Default: stepCountIs(20). Override to stop on a terminal tool or custom logic:
stopWhen: hasToolCall("finalAnswer"),
prepareStep: (context) => ({
// Customize each step — swap models, compress messages, limit tools
toolChoice: context.steps.length > 5 ? "none" : "auto",
}),
});
const { text } = await agent.generate({
prompt:
"Research the weather in Tokyo and calculate the average temperature this week.",
});
```
### MCP Client
Connect to any MCP server and use its tools:
```ts
import { generateText } from "ai";
import { createMCPClient } from "@ai-sdk/mcp";
const mcpClient = await createMCPClient({
transport: {
type: "sse",
url: "https://my-mcp-server.com/sse",
},
});
const tools = await mcpClient.tools();
const result = await generateText({
model: "openai/gpt-5.4",
tools,
prompt: "Use the available tools to help the user.",
});
await mcpClient.close();
```
MCP OAuth for remote servers is handled automatically by `@ai-sdk/mcp`.
### Tool Approval (Human-in-the-Loop)
Set `needsApproval` on any tool to require user confirmation before execution. The tool pauses in `approval-requested` state until the client responds.
```ts
import { streamText, tool } from "ai";
import { z } from "zod";
const result = streamText({
model: "openai/gpt-5.4",
tools: {
deleteUser: tool({
description: "Delete a user account",
inputSchema: z.object({ userId: z.string() }),
needsApproval: true, // Always require approval
execute: async ({ userId }) => {
await db.users.delete(userId);
return { deleted: true };
},
}),
processPayment: tool({
description: "Process a payment",
inputSchema: z.object({ amount: z.number(), recipient: z.string() }),
// Conditional: only approve large amounts
needsApproval: async ({ amount }) => amount > 1000,
execute: async ({ amount, recipient }) => {
return await processPayment(amount, recipient);
},
}),
},
prompt: "Delete user 123",
});
```
**Client-side approval with `useChat`:**
```tsx
"use client";
import { useChat } from "@ai-sdk/react";
function Chat() {
const { messages, addToolApprovalResponse } = useChat();
return messages.map((m) =>
m.parts?.map((part, i) => {
// Tool parts in approval-requested state need user action
Ver en GitHub