← Back to tutorials

Vercel AI SDK Hands-On Tutorial: Integrate AI Chat in Next.js in 10 Minutes

Streaming Output, Tool Calling, Multi-Model Switching – Full Feature Breakdown of Vercel AI SDK

Vercel AI SDK Hands-On Tutorial: Next.js AI Chat Integration

Why Vercel AI SDK?

Problems with directly calling the OpenAI API:

  • Streaming output requires manual SSE handling (tedious and error-prone)
  • Switching models requires significant changes
  • Frontend state management (loading, error, message history) must be handled manually
  • Vercel AI SDK solves all of these: a unified interface supports 30+ models, built-in React hooks manage conversation state, and streaming output works out of the box.


    Installation

    bash
    npm install ai @ai-sdk/openai
    

    or Claude: npm install ai @ai-sdk/anthropic

    or Google: npm install ai @ai-sdk/google


    Minimal Streaming Chat (10 Lines of Code)

    API Route

    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'), messages, }); return result.toDataStreamResponse(); }

    Frontend Component

    typescript
    // src/components/chat.tsx
    'use client';
    import { useChat } from 'ai/react';

    export function Chat() { const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat(); return (

    {messages.map((m) => (
    {m.role === 'user' ? 'You' : 'AI'}: {m.content}
    ))}
    ); }


    Tool Calling

    typescript
    import { streamText, tool } from 'ai';
    import { z } from 'zod';

    const result = streamText({ model: openai('gpt-4o'), messages, tools: { getWeather: tool({ description: 'Get the current weather for a specified city', parameters: z.object({ city: z.string() }), execute: async ({ city }) => { const weather = await fetchWeatherAPI(city); return { city, temperature: weather.temp }; }, }), queryOrders: tool({ description: 'Query user order list', parameters: z.object({ userId: z.string(), status: z.enum(['pending', 'completed']).optional(), }), execute: async ({ userId, status }) => { return { orders: await db.orders.findMany({ where: { userId, status } }) }; }, }), }, maxSteps: 5, });


    Multi-Model Switching

    typescript
    import { openai } from '@ai-sdk/openai';
    import { anthropic } from '@ai-sdk/anthropic';
    import { google } from '@ai-sdk/google';

    function selectModel(taskType: string) { const models: Record = { code: anthropic('claude-3-5-sonnet-20241022'), analysis: openai('gpt-4o'), fast: openai('gpt-4o-mini'), multimodal: google('gemini-2.5-pro'), }; return models[taskType] ?? openai('gpt-4o-mini'); }


    Structured JSON Output

    typescript
    import { generateObject } from 'ai';
    import { z } from 'zod';

    const { object } = await generateObject({ model: openai('gpt-4o'), schema: z.object({ name: z.string(), category: z.enum(['electronics', 'clothing', 'food']), price: z.number().positive(), tags: z.array(z.string()).max(5), }), prompt: 'Generate product data based on the following information: ' + productInfo, }); // object has full TypeScript type inference


    Chat History Persistence

    typescript
    const result = streamText({
      model: openai('gpt-4o'),
      messages: [...historicalMessages, ...newMessages],
      onFinish: async ({ text }) => {
        await db.messages.create({
          data: { conversationId, role: 'assistant', content: text },
        });
      },
    });
    


    Production: Rate Limiting + Authentication

    typescript
    import { auth } from '@clerk/nextjs/server';

    export async function POST(req: Request) { const { userId } = await auth(); if (!userId) return new Response('Unauthorized', { status: 401 });

    const { success } = await ratelimit.limit(userId); if (!success) return new Response('Too many requests', { status: 429 });

    const { messages } = await req.json(); const result = streamText({ model: openai('gpt-4o'), messages, maxTokens: 1000, // Control single response length }); return result.toDataStreamResponse(); }


    Further Reading

  • 12 Ways to Optimize LLM API Costs
  • AI Agent Workflow Automation
  • Next.js Best Practices
  • Also available in 中文.

    Vercel AI SDK Hands-On Tutorial: Integrate AI Chat in Next.js in 10 Minutes | AI Skill Navigation | AI Skill Navigation