Vercel AI SDK Patterns
Quick Guide: Use Vercel AI SDK (v6) to build AI-powered applications with a unified provider API. UsegenerateText/streamTextfor text generation and streaming,Output.object()/Output.array()for structured data with Zod,tool()for function calling, anduseChat/useCompletionhooks for React chat UIs. Supports OpenAI, Anthropic, Google, and 20+ providers through a single API.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)
(You MUST use the ai package (v6) with Output.object() / Output.array() for structured output -- NOT the deprecated generateObject / streamObject functions)
(You MUST define tool input schemas with z.object() and use .describe() on each property to help the model understand expected inputs)
(You MUST use streamText for user-facing responses to enable progressive rendering -- use generateText only for background/non-interactive tasks)
(You MUST handle streaming errors via onError callback -- streamText errors become part of the stream and are NOT thrown)
(You MUST use inputSchema (not parameters) when defining tools -- parameters was renamed in SDK v5+)
</critical_requirements>
Auto-detection: AI SDK, Vercel AI, generateText, streamText, generateObject, streamObject, Output.object, Output.array, useChat, useCompletion, @ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/google, tool(), toolChoice, embedMany, embed, cosineSimilarity, ToolLoopAgent, smoothStream
When to use:
- Building AI chat interfaces with streaming responses
- Generating structured data (JSON objects, arrays) from LLMs with Zod schema validation
- Implementing tool calling / function calling with LLMs
- Creating multi-provider AI applications (OpenAI, Anthropic, Google, etc.)
- Building RAG pipelines with embeddings and vector similarity
- Adding AI text completion or generation to any TypeScript app
Key patterns covered:
- Provider setup and model configuration (OpenAI, Anthropic, Google, custom)
- Text generation (
generateText) and streaming (streamText) - Structured output with Zod schemas (
Output.object,Output.array,Output.choice) - Tool calling with
tool(), multi-step execution, and approval flows - React hooks:
useChatfor chat UIs,useCompletionfor text completion - Embeddings (
embed,embedMany) and RAG patterns withcosineSimilarity
When NOT to use:
- Simple static content that doesn't need AI generation
- Server-side-only batch jobs where a direct provider SDK (e.g.,
openainpm package) is simpler - Image generation only (AI SDK supports it, but dedicated image SDKs may be more feature-rich)
Detailed Resources:
- For provider setup, text generation, and error handling, see [examples/core.md](examples/core.md)
- For chat UI patterns with useChat, see [examples/chat.md](examples/chat.md)
- For tool definitions and multi-step calling, see [examples/tools.md](examples/tools.md)
- For Zod-based structured output, see [examples/structured-output.md](examples/structured-output.md)
- For embeddings and RAG, see [examples/rag.md](examples/rag.md)
- For quick reference tables, see [reference.md](reference.md)
<philosophy>
Philosophy
The Vercel AI SDK provides a unified TypeScript API for building AI-powered applications across providers. Instead of learning each provider's unique SDK, you write one set of code that works with OpenAI, Anthropic, Google, and 20+ other providers.
Core principles:
- Provider agnostic -- Switch models by changing a string, not rewriting code. The provider abstraction means
generateText({ model: 'openai/gpt-4o' })andgenerateText({ model: 'anthropic/claude-sonnet-4.5' })use the same API. - Streaming first --
streamTextstarts delivering tokens immediately. Use it for all user-facing responses.generateTextblocks until completion and is better for background tasks and agent loops. - Type-safe structured output -- Define Zod schemas and get validated, typed objects back from the model. Use
.describe()on schema properties to guide the model. - Tools as first-class citizens -- Define tools with Zod input schemas and execute functions. The SDK handles the tool call loop, including multi-step execution and human approval.
- Framework-agnostic UI hooks --
useChatanduseCompletionwork with React, Svelte, Vue, and Angular. They manage streaming state, message history, and input handling.
When to use Vercel AI SDK:
- Multi-provider applications where you want to switch models easily
- Streaming chat interfaces with React (or Svelte, Vue, Angular)
- Structured data extraction from natural language
- Agent-style applications with tool calling loops
- RAG systems with embedding and retrieval
When NOT to use:
- Single-provider scripts where the native SDK is simpler and has fewer dependencies
- Extremely high-throughput batch processing (direct API calls avoid SDK overhead)
- Non-TypeScript environments (the SDK is TypeScript-first)
</philosophy>
<patterns>
Core Patterns
Pattern 1: Provider Setup
Configure providers via direct imports (auto-reads env vars), custom instances, or AI Gateway. See [examples/core.md](examples/core.md) for full examples.
import { gateway } from "ai";
import { openai } from "@ai-sdk/openai";
// Gateway: provider/model string routing
const model = gateway("anthropic/claude-sonnet-4.5");
// Direct: auto-reads OPENAI_API_KEY from env
const openaiModel = openai("gpt-4o");
Use customProvider for semantic model aliases (models('fast'), models('smart')). Never hardcode API keys.
Pattern 2: Text Generation with generateText
Use generateText for non-interactive tasks. Returns a promise that resolves when complete. See [examples/core.md](examples/core.md).
import { generateText } from "ai";
const { text, usage } = await generateText({
model: "openai/gpt-4o",
system: "You are a professional technical writer.",
prompt: `Summarize: ${article}`,
});
Use ModelMessage[] for multi-turn conversations. Append response.messages for continued dialogue. Do NOT use generateText for user-facing responses -- use streamText instead.
Pattern 3: Streaming with streamText
Use streamText for all user-facing responses. Errors are part of the stream (not thrown) -- use onError. See [examples/core.md](examples/core.md).
import { streamText, smoothStream } from "ai";
const result = streamText({
model: "anthropic/claude-sonnet-4.5",
prompt: "Explain TypeScript.",
experimental_transform: smoothStream(),
onError({ error }) {
console.error("Stream error:", error);
},
});
for await (const part of result.textStream) {
process.stdout.write(part);
}
Use result.toUIMessageStreamResponse() in route handlers serving useChat, or result.toTextStreamResponse() for plain text streaming. Use result.fullStream for granular event types (text-delta, tool-call, error, finish).
Pattern 4: Structured Output with Zod
Use Output.object() with generateText/streamText for type-safe structured data. See [examples/structured-output.md](examples/structured-output.md).
import { generateText, Output } from "ai";
import { z } from "zod";
const schema = z.object({
name: z.string().describe("Recipe name"),
steps: z.array(z.string()).describe("Cooking instructions"),
});
const { output } = await generateText({
model: "openai/gpt-4o",
output: Output.object({ schema }),
prompt: "Generate a vegetarian lasagna recipe.",
});
Key variants: Output.array({ element }) with elementStream for streaming arrays, Output.choice() for classification, partialOutputStream for streaming partial objects. Do NOT u