vercel-ai
The **AI SDK** by Vercel is a TypeScript toolkit for building AI-powered applications with large language models. It provides a unified interface for text generation, structured output, streaming, too
Vercel AI SDK
The AI SDK by Vercel is a TypeScript toolkit for building AI-powered applications with large language models. It provides a unified interface for text generation, structured output, streaming, tool calling, embeddings, image/speech/video generation, and agentic workflows across 30+ AI providers (OpenAI, Anthropic, Google, AWS Bedrock, etc.) — with framework integrations for React, Next.js, Svelte, Vue, and Angular.
Quick References
| File | Purpose |
|---|---|
packages/ai/src/index.ts | Main ai package entry point — all core exports |
packages/provider/src/index.ts | Provider interface specifications (@ai-sdk/provider) |
packages/openai/src/index.ts | OpenAI provider — representative provider package |
packages/react/src/index.ts | React hooks (useChat, useCompletion, useObject) |
examples/ai-functions/src/ | Hundreds of runnable usage examples |
Packages
Core
| Package | npm name | Description |
|---|---|---|
packages/ai | ai | Core SDK — generateText, streamText, generateObject, streamObject, embed, ToolLoopAgent, and more |
packages/provider | @ai-sdk/provider | Provider interface specifications (e.g. LanguageModelV3) |
packages/provider-utils | @ai-sdk/provider-utils | Shared utilities for building providers (tool, jsonSchema, zodSchema) |
packages/gateway | @ai-sdk/gateway | Vercel AI Gateway — unified model access via gateway('openai/gpt-4o') |
AI Providers
| Package | npm name | Description |
|---|---|---|
packages/openai | @ai-sdk/openai | OpenAI (GPT-4o, GPT-5, o1, DALL-E, Whisper, etc.) |
packages/anthropic | @ai-sdk/anthropic | Anthropic (Claude Sonnet, Haiku, Opus) |
packages/google | @ai-sdk/google | Google Generative AI (Gemini) |
packages/google-vertex | @ai-sdk/google-vertex | Google Vertex AI |
packages/azure | @ai-sdk/azure | Azure OpenAI |
packages/amazon-bedrock | @ai-sdk/amazon-bedrock | Amazon Bedrock |
packages/groq | @ai-sdk/groq | Groq |
packages/mistral | @ai-sdk/mistral | Mistral AI |
packages/xai | @ai-sdk/xai | xAI (Grok) |
packages/cohere | @ai-sdk/cohere | Cohere |
packages/deepseek | @ai-sdk/deepseek | DeepSeek |
packages/fireworks | @ai-sdk/fireworks | Fireworks AI |
packages/perplexity | @ai-sdk/perplexity | Perplexity |
packages/togetherai | @ai-sdk/togetherai | Together AI |
packages/huggingface | @ai-sdk/huggingface | Hugging Face Inference |
packages/openai-compatible | @ai-sdk/openai-compatible | Generic OpenAI-compatible provider adapter |
Framework Integrations
| Package | npm name | Description |
|---|---|---|
packages/react | @ai-sdk/react | React hooks: useChat, useCompletion, useObject |
packages/svelte | @ai-sdk/svelte | Svelte integration |
packages/vue | @ai-sdk/vue | Vue integration |
packages/angular | @ai-sdk/angular | Angular integration |
Utilities
| Package | npm name | Description |
|---|---|---|
packages/mcp | @ai-sdk/mcp | Model Context Protocol (MCP) client integration |
When to Use
- Building chatbots or conversational AI — use
streamTextwithuseChatfor real-time streaming chat UIs - Extracting structured data from text — use
generateObjectwith a Zod schema to get type-safe parsed output - Building AI agents with tool use — use
ToolLoopAgentorgenerateTextwithtoolsfor multi-step reasoning with function calling - Generating embeddings for RAG/search — use
embed/embedManywith any embedding provider - Generating images, speech, or video — use
generateImage,experimental_generateSpeech, orexperimental_generateVideo - Switching between AI providers without code changes — the unified interface lets you swap providers by changing only the model parameter
- Integrating MCP servers as tool sources for agent workflows
Installation
# Core SDK (always required)
npm install ai
# Add one or more providers
npm install @ai-sdk/openai
npm install @ai-sdk/anthropic
npm install @ai-sdk/google
# For React hooks
npm install @ai-sdk/react
# For MCP tool integration
npm install @ai-sdk/mcp
# Zod is a peer dependency (for schemas)
npm install zod
Best Practices
- Use
streamTextfor user-facing responses — streaming provides a much better UX than waiting forgenerateTextto complete. UsesmoothStreamto smooth out chunky output. - Define schemas with Zod for structured output — the SDK deeply integrates Zod schemas, providing full type inference for
generateObject,streamObject, andOutput.object(). Both Zod 3 and Zod 4 are supported. - Use
ToolLoopAgentfor multi-step tool use — rather than manually loopinggenerateText,ToolLoopAgenthandles the tool call → result → next LLM call loop automatically with configurable stop conditions. - Prefer
Output.object()/Output.array()withgenerateText/streamTextwhen you need both text reasoning and structured output — these let you get typed structured data alongside the text stream. - Set
maxOutputTokensto control response length and cost — this parameter is passed through to the provider. - Use
maxRetries(default: 2) for robustness — the SDK automatically retries on transient failures. - Pass
abortSignalfor request cancellation — integrates with standardAbortControllerfor timeouts and user cancellation. - Use the Gateway provider (
gateway()) for unified model access via Vercel's AI Gateway, allowing model routing via string identifiers like'openai/gpt-4o'.
Common Patterns
Generate text:
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const { text, usage, finishReason } = await generateText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant.',
prompt: 'Explain quantum computing in simple terms.',
maxOutputTokens: 500,
});
Stream text:
import { streamText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
const result = streamText({
model: anthropic('claude-sonnet-4-0'),
prompt: 'Write a short poem about AI.',
});
for await (const textPart of result.textStream) {
process.stdout.write(textPart);
}
Generate structured object:
import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const { object } = await generateObject({
model: openai('gpt-4o-mini'),
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 lasagna recipe.',
});
console.log(object.recipe.name); // fully typed
Stream structured object:
import { streamObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = streamObject({
model: openai('gpt-4o-mini'),
schema: z.object({
characters: z.array(z.object({
name: z.string(),
class: z.string(),
description: z.string(),
})),
}),
prompt: 'Generate 3 fantasy RPG characters.',
});
for await (const partialObject of result.partialObjectStream) {
console.dir(partialObject, { depth: Infinity });
}
Tool calling with generateText:
import { generateText, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = await generateText({
model: openai('gpt-4o'),
prompt: 'What is the weather in San Francisco?',
tools: {
weather: tool({
description: 'Get the weather in a location',
inputSchema: z.object({
location: z.string().describe('The location to get the weather for'),
}),
execute: async ({ location }) => ({
location,
temperature: 72,
unit: 'fahrenheit',
}),
}),
},
});
console.log(result.text);
console.log(result.toolCalls);
console.log(result.toolResults);
ToolLoopAgent (agentic loop):
import { ToolLoopAgent, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const agent = new ToolLoopAgent({
model: openai('gpt-4o'),
instructions: 'You are a helpful assistant that answers weather questions.',
tools: {
weather: tool({
description: 'Get the weather in a location',
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => ({
location,
temperature: 72 + Math.floor(Math.random() * 21) - 10,
}),
}),
},
});
// Non-streaming
const result = await agent.generate({
prompt: 'What is the weather in Tokyo?',
});
console.log(result.content);
// Streaming
const streamResult = await agent.stream({
prompt: 'What is the weather in Tokyo?',
});
for await (const textPart of streamResult.textStream) {
process.stdout.write(textPart);
}
Embeddings:
import { embed, embedMany } from 'ai';
import { openai } from '@ai-sdk/openai';
// Single embedding
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: 'sunny day at the beach',
});
// Multiple embeddings
const { embeddings } = await embedMany({
model: openai.embedding('text-embedding-3-small'),
values: ['sunny day at the beach', 'rainy morning in the city'],
});
React useChat hook (Next.js example):
// app/api/chat/route.ts (server)
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
});
return result.toUIMessageStreamResponse();
}
// app/page.tsx (client)
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div>
{messages.map(m => (
<div key={m.id}>{m.role}: {m.parts.map(p => p.type === 'text' ? p.text : '').join('')}</div>
))}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
</form>
</div>
);
}
Using Output.object() with streamText for structured output in a text stream:
import { streamText, Output } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = streamText({
model: openai('gpt-4o'),
prompt: 'List 3 cities with their populations.',
output: Output.object({
schema: z.object({
cities: z.array(z.object({
name: z.string(),
population: z.number(),
})),
}),
}),
});
for await (const partialOutput of result.partialOutputStream) {
console.dir(partialOutput, { depth: Infinity });
}
MCP tool integration:
import { createMCPClient } from '@ai-sdk/mcp';
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const mcpClient = await createMCPClient({
transport: { type: 'sse', url: 'https://my-mcp-server.example/sse' },
});
const result = streamText({
model: openai('gpt-4o'),
prompt: 'Search for the latest AI news',
tools: await mcpClient.tools(),
});
for await (const textPart of result.textStream) {
process.stdout.write(textPart);
}
await mcpClient.close();
Vercel AI Gateway:
import { gateway } from 'ai'; // re-exported from @ai-sdk/gateway
import { generateText } from 'ai';
const result = await generateText({
model: gateway('openai/gpt-4o'),
prompt: 'Hello!',
});
Using smoothStream for smoother streaming output:
import { streamText, smoothStream } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = streamText({
model: openai('gpt-4o'),
prompt: 'Write a short story.',
experimental_transform: smoothStream({ chunking: 'word' }),
});
Custom provider with middleware:
import { wrapLanguageModel, extractReasoningMiddleware } from 'ai';
import { openai } from '@ai-sdk/openai';
const wrappedModel = wrapLanguageModel({
model: openai('gpt-4o'),
middleware: extractReasoningMiddleware({ tagName: 'thinking' }),
});
API Quick Reference
Core Functions (from ai)
| Export | Type | Description |
|---|---|---|
generateText | function | Generate text completion (non-streaming) |
streamText | function | Stream text completion with real-time output |
generateObject | function | Generate typed structured output (non-streaming) |
streamObject | function | Stream structured output with partial objects |
embed | function | Generate a single embedding vector |
embedMany | function | Generate multiple embedding vectors |
generateImage | function | Generate images from a prompt |
experimental_generateSpeech | function | Generate speech audio from text |
experimental_transcribe | function | Transcribe audio to text |
experimental_generateVideo | function | Generate video from a prompt |
rerank | function | Rerank documents by relevance |
tool | function | Define a tool with schema and execute function |
jsonSchema | function | Create a schema from a JSON Schema definition |
zodSchema | function | Create a schema from a Zod schema |
ToolLoopAgent | class | Agent that runs tools in a loop until stop condition |
Output.text() | function | Output spec for plain text |
Output.object() | function | Output spec for typed structured objects |
Output.array() | function | Output spec for typed arrays with element streaming |
Output.choice() | function | Output spec for single choice from options |
Output.json() | function | Output spec for unstructured JSON |
smoothStream | function | Transform stream for smoother text output |
stepCountIs | function | Stop condition: stop after N steps |
hasToolCall | function | Stop condition: stop when a specific tool is called |
generateId | function | Generate a random ID |
createIdGenerator | function | Create a custom ID generator |
gateway | function | Create a Vercel AI Gateway model reference |
createProviderRegistry | function | Create a registry for multiple providers |
customProvider | function | Create a custom provider with model overrides |
pruneMessages | function | Prune messages to fit context window |
Middleware (from ai)
| Export | Type | Description |
|---|---|---|
wrapLanguageModel | function | Wrap a language model with middleware |
wrapEmbeddingModel | function | Wrap an embedding model with middleware |
wrapImageModel | function | Wrap an image model with middleware |
wrapProvider | function | Wrap a provider with middleware |
extractReasoningMiddleware | function | Extract reasoning/thinking from model output |
extractJsonMiddleware | function | Extract JSON from model output |
defaultSettingsMiddleware | function | Apply default settings to model calls |
simulateStreamingMiddleware | function | Simulate streaming for non-streaming models |
UI Integration (from ai)
| Export | Type | Description |
|---|---|---|
UIMessage | type | Standard message type for UI chat interfaces |
convertToModelMessages | function | Convert UI messages to model messages |
createUIMessageStream | function | Create a UI message stream |
createUIMessageStreamResponse | function | Create a Response from a UI message stream |
AbstractChat | class | Framework-agnostic chat state management |
React Hooks (from @ai-sdk/react)
| Export | Type | Description |
|---|---|---|
useChat | hook | Full chat interface with streaming, tool calls, and message management |
useCompletion | hook | Simple text completion with streaming |
useObject | hook | Stream structured objects with partial state |
MCP Client (from @ai-sdk/mcp)
| Export | Type | Description |
|---|---|---|
createMCPClient | function | Create an MCP client for tool discovery |
Key Types (from ai)
| Export | Type | Description |
|---|---|---|
LanguageModel | type | Language model interface |
EmbeddingModel | type | Embedding model interface |
ImageModel | type | Image generation model interface |
ToolSet | type | Record of tool definitions |
ToolChoice | type | Tool choice strategy ('auto', 'required', 'none', or specific tool) |
ModelMessage | type | Model-level message (system, user, assistant, tool) |
LanguageModelUsage | type | Token usage statistics |
FinishReason | type | Why the model stopped generating |
CallWarning | type | Warnings from model calls |
StopCondition | type | Condition function for stopping agent loops |
GenerateTextResult | type | Full result from generateText |
StreamTextResult | type | Full result from streamText |
GenerateObjectResult | type | Full result from generateObject |
StreamObjectResult | type | Full result from streamObject |
StepResult | type | Result of a single step in multi-step generation |
Provider Pattern
Each provider package exports a factory function and a pre-configured instance:
// Pre-configured (uses env vars like OPENAI_API_KEY)
import { openai } from '@ai-sdk/openai';
const model = openai('gpt-4o');
const embedding = openai.embedding('text-embedding-3-small');
// Custom configuration
import { createOpenAI } from '@ai-sdk/openai';
const myOpenAI = createOpenAI({ apiKey: 'sk-...', baseURL: '...' });
const model = myOpenAI('gpt-4o');
// Other providers follow the same pattern:
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
import { groq } from '@ai-sdk/groq';
import { mistral } from '@ai-sdk/mistral';
import { xai } from '@ai-sdk/xai';
Error Classes (from ai)
| Error | Description |
|---|---|
AISDKError | Base error class for all SDK errors |
APICallError | Error during API communication |
NoObjectGeneratedError | Structured output failed to generate or validate |
NoOutputGeneratedError | No output generated (e.g. all steps exhausted) |
NoSuchToolError | Model called a tool that doesn't exist |
InvalidToolInputError | Tool call input didn't match schema |
RetryError | All retries exhausted |
UnsupportedFunctionalityError | Feature not supported by the provider |
LoadAPIKeyError | API key not found in environment |
Configuration
Environment Variables
Each provider reads its API key from a standard environment variable:
| Provider | Environment Variable |
|---|---|
| OpenAI | OPENAI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
GOOGLE_GENERATIVE_AI_API_KEY | |
| Groq | GROQ_API_KEY |
| Mistral | MISTRAL_API_KEY |
| xAI | XAI_API_KEY |
| Cohere | COHERE_API_KEY |
| DeepSeek | DEEPSEEK_API_KEY |
Call Settings
All generation functions accept these common options:
| Option | Type | Default | Description |
|---|---|---|---|
maxOutputTokens | number | — | Maximum tokens to generate |
temperature | number | — | Randomness (provider-dependent range) |
topP | number | — | Nucleus sampling |
topK | number | — | Top-K sampling |
presencePenalty | number | — | Reduce repetition of prompt content |
frequencyPenalty | number | — | Reduce word/phrase repetition |
stopSequences | string[] | — | Stop generation at these sequences |
seed | number | — | Deterministic generation seed |
maxRetries | number | 2 | Retry count (0 to disable) |
abortSignal | AbortSignal | — | Cancellation signal |
timeout | number | object | — | Timeout in milliseconds |
headers | Record<string, string> | — | Additional HTTP headers |
providerOptions | object | — | Provider-specific options |
Documentation
Full documentation is available at ai-sdk.dev/docs.