Introduction
The Vercel AI SDK has become the reference tool for integrating language models into web applications. In 2026, its advanced features enable handling complex streams, dynamic tool calls, and custom providers. This tutorial guides you step by step to build a robust AI application with Next.js. You will learn to optimize streaming performance, secure API calls, and extend the SDK. Each step includes ready-to-use code. This advanced level assumes solid proficiency in TypeScript and REST APIs.
Prerequisites
- Node.js 20+ and Next.js 15
- OpenAI or Anthropic account
- Strong knowledge of TypeScript and React Server Components
- Vercel CLI installed
Project Initialization
npx create-next-app@latest ai-sdk-app --yes
cd ai-sdk-app
npm install ai @ai-sdk/openai zodThis command creates a Next.js 15 project and installs the Vercel AI SDK with the OpenAI provider and Zod for validation. The ai package handles streaming and React hooks.
API Route with Advanced Streaming
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: {
getWeather: {
description: 'Obtenir la météo',
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => ({ temp: 18, city }),
},
},
maxSteps: 5,
});
return result.toDataStreamResponse();
}This API route uses streamText to handle streaming and tool calling. maxSteps limits tool iterations. The code is complete and ready to use with Zod validation.
React Component with useChat
'use client';
import { useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div>
{messages.map(m => <div key={m.id}>{m.role}: {m.content}</div>)}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Envoyer</button>
</form>
</div>
);
}The useChat hook automatically manages streaming and message state. It connects to the API route without additional configuration.
Advanced Custom Provider
import { createOpenAI } from '@ai-sdk/openai';
export const customOpenAI = createOpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1',
headers: { 'X-Custom-Header': 'advanced' },
fetch: async (url, options) => {
const res = await fetch(url, options);
if (!res.ok) throw new Error('Provider error');
return res;
},
});Creating a custom provider allows adding headers, handling errors, and routing requests. This approach is essential for production.
Complex Tool Management
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: {
searchDatabase: {
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => ({ results: ['item1'] }),
},
},
});
return result.toDataStreamResponse();
}Complex tools with asynchronous execution allow integrating databases or external APIs while maintaining smooth streaming.
Best Practices
- Always validate inputs with Zod before calling models
- Limit maxSteps to prevent infinite tool loops
- Use environment variables for API keys
- Implement server-side rate limiting
- Log provider errors for monitoring
Common Errors to Avoid
- Forgetting to return toDataStreamResponse() which blocks streaming
- Not handling async errors in tool execute functions
- Using unsupported models without a custom provider
- Ignoring token limits which causes response cutoffs
Going Further
Explore multi-model features and autonomous agents in our Learni training courses.