TypeScript AI SDK Guide 2026: Vercel AI SDK for Next.js Applications
Build streaming AI chat interfaces, structured outputs, and agent workflows in Next.js using the Vercel AI SDK with TypeScript
TypeScript AI SDK Guide 2026: Vercel AI SDK for Next.js Applications
The Vercel AI SDK has become the standard library for building AI applications in TypeScript/Next.js. It provides a unified interface across OpenAI, Claude, Gemini, and other models, with built-in streaming, React hooks, and Server Actions support. This guide covers everything you need to build production AI features.
Why Vercel AI SDK?
useChat, useCompletion, useObject for UISetup
bash
npm install ai @ai-sdk/openai @ai-sdk/anthropic zod
or
bun add ai @ai-sdk/openai @ai-sdk/anthropic zod
Basic Text Generation
typescript
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';// Server-side generation
const { text } = await generateText({
model: openai('gpt-4o'),
prompt: 'Explain the difference between RSC and RSC streaming in Next.js',
});
console.log(text);
// With system prompt
const { text: review } = await generateText({
model: openai('gpt-4o'),
system: 'You are a senior TypeScript engineer who reviews code for best practices.',
prompt: Review this code: ${code},
});
Streaming Chat with useChat Hook
typescript
// src/app/chat/page.tsx
'use client';import { useChat } from '@ai-sdk/react';
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
});
return (
{messages.map((message) => (
{message.content}
))}
);
}
typescript
// src/app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant.',
messages,
});
return result.toDataStreamResponse();
}
Structured Output with Zod
typescript
import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';// Define schema
const ProductSchema = z.object({
name: z.string().describe('Product name'),
price: z.number().describe('Price in USD'),
category: z.enum(['electronics', 'clothing', 'food', 'other']),
features: z.array(z.string()).describe('Key features list'),
inStock: z.boolean(),
rating: z.number().min(1).max(5).optional(),
});
// Extract structured data from unstructured text
const { object: product } = await generateObject({
model: openai('gpt-4o'),
schema: ProductSchema,
prompt: `Extract product info from: "The Pro X Wireless Headphones feature 30-hour battery,
active noise cancellation, and premium sound at $299. Currently in stock. User rating 4.7/5."
Category: electronics`,
});
console.log(product);
// { name: 'Pro X Wireless Headphones', price: 299, category: 'electronics', ... }
Tool Calling in Next.js
typescript
// src/app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful shopping assistant.',
messages,
tools: {
searchProducts: tool({
description: 'Search the product catalog',
parameters: z.object({
query: z.string().describe('Search query'),
category: z.enum(['electronics', 'clothing', 'all']).optional(),
maxPrice: z.number().optional(),
}),
execute: async ({ query, category, maxPrice }) => {
// Call your actual product search API
const results = await searchProductCatalog({ query, category, maxPrice });
return results.slice(0, 5);
},
}),
getOrderStatus: tool({
description: 'Get order status by order ID',
parameters: z.object({
orderId: z.string(),
}),
execute: async ({ orderId }) => {
return await fetchOrderStatus(orderId);
},
}),
},
maxSteps: 5, // Allow up to 5 tool call rounds
});
return result.toDataStreamResponse();
}
Streaming Object Generation
typescript
// Generate streaming structured data - great for forms and reports
import { streamObject } from 'ai';
import { openai } from '@ai-sdk/openai';const ReportSchema = z.object({
title: z.string(),
sections: z.array(z.object({
heading: z.string(),
content: z.string(),
})),
recommendations: z.array(z.string()),
});
// API route
export async function POST(req: Request) {
const { topic } = await req.json();
const result = streamObject({
model: openai('gpt-4o'),
schema: ReportSchema,
prompt: Generate a business report about: ${topic},
});
return result.toTextStreamResponse();
}
// Client hook
'use client';
import { experimental_useObject as useObject } from '@ai-sdk/react';
export function ReportGenerator() {
const { object: report, submit, isLoading } = useObject({
api: '/api/generate-report',
schema: ReportSchema,
});
return (
{report && (
{report.title}
{report.sections?.map((section, i) => (
{section?.heading}
{section?.content}
))}
)}
);
}
Multi-Step Agent in Next.js
typescript
import { openai } from '@ai-sdk/openai';
import { generateText, tool } from 'ai';
import { z } from 'zod';export async function runResearchAgent(topic: string): Promise {
const { text, steps } = await generateText({
model: openai('gpt-4o'),
system: `You are a research assistant. Use available tools to thoroughly research topics.
Always search for information before answering.
Synthesize multiple sources into a comprehensive response.`,
prompt: Research and summarize: ${topic},
tools: {
webSearch: tool({
description: 'Search the web for information',
parameters: z.object({
query: z.string().describe('Search query'),
}),
execute: async ({ query }) => {
// Integrate with Tavily, Serper, or another search API
const results = await searchWeb(query);
return results.map((r) => ({ title: r.title, snippet: r.snippet, url: r.url }));
},
}),
},
maxSteps: 10, // Allow multiple research iterations
});
// Log what the agent did
for (const step of steps) {
if (step.toolCalls) {
for (const call of step.toolCalls) {
console.log(Tool: ${call.toolName}, call.args);
}
}
}
return text;
}
Switching Models
typescript
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';// One unified API, swap the model easily
const model = process.env.AI_PROVIDER === 'anthropic'
? anthropic('claude-3-5-sonnet-20241022')
: process.env.AI_PROVIDER === 'google'
? google('gemini-2.0-flash-exp')
: openai('gpt-4o'); // Default
const { text } = await generateText({
model, // Works identically regardless of provider
prompt: 'Your prompt here',
});
Production Patterns
typescript
// Error handling and fallback
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';async function generateWithFallback(prompt: string): Promise {
const models = [
openai('gpt-4o'),
anthropic('claude-3-5-sonnet-20241022'),
openai('gpt-4o-mini'), // Cheaper fallback
];
for (const model of models) {
try {
const { text } = await generateText({ model, prompt });
return text;
} catch (error) {
console.warn(Model failed, trying next:, error);
}
}
throw new Error('All models failed');
}
Conclusion
The Vercel AI SDK dramatically reduces the boilerplate for AI applications in TypeScript. The unified API means you're not locked into a single provider, and the React hooks handle streaming complexity automatically. Start with useChat for conversational interfaces and generateObject for structured data extraction—these two patterns cover 80% of AI features teams want to build.
Also available in 中文.