Quick start

This chapter runs AI SDK Core once without a UI, then wires Next.js App Router to useChat. The default model string is Gateway openai/gpt-4.1-mini. The official quickstart currently demos xai/grok-4.6. IDs change—use whatever your account allows.

Finish Installation first: Node 22+, pnpm add ai @ai-sdk/react zod, and AI_GATEWAY_API_KEY in .env.local.


1. No UI: generateText

Use this for scripts, cron jobs, and one-shot server summaries. No React required.

import { generateText } from 'ai';

const { text } = await generateText({
  model: 'openai/gpt-4.1-mini',
  instructions: 'Reply in one short sentence.',
  prompt: 'What is the Vercel AI SDK?',
});

console.log(text);

Direct OpenAI instead:

import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';

const { text } = await generateText({
  model: openai('gpt-5.1'), // docs example; check your console
  prompt: 'What is the Vercel AI SDK?',
});

generateText also returns usage, finishReason, toolCalls, and more—start there when debugging.


2. Streaming chat: route handler

Create app/api/chat/route.ts:

import {
  streamText,
  UIMessage,
  convertToModelMessages,
  createUIMessageStreamResponse,
  toUIMessageStream,
} from 'ai';

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: 'openai/gpt-4.1-mini',
    messages: await convertToModelMessages(messages),
  });

  return createUIMessageStreamResponse({
    stream: toUIMessageStream({ stream: result.stream }),
  });
}

What happens:

  1. The client sends UIMessage[] (UI metadata such as timestamps included).
  2. convertToModelMessages is async; it strips UI fields into ModelMessage[].
  3. streamText starts immediately. You must consume result.stream or generation stalls.
  4. toUIMessageStream + createUIMessageStreamResponse wrap the stream as SSE that useChat understands.

Do not copy toDataStreamResponse() from old blog posts.


3. Page: useChat

app/page.tsx must be a client component (React hooks):

'use client';

import { useChat } from '@ai-sdk/react';
import { useState } from 'react';

export default function Chat() {
  const [input, setInput] = useState('');
  const { messages, sendMessage } = useChat();

  return (
    <div>
      {messages.map((message) => (
        <div key={message.id}>
          {message.role === 'user' ? 'User: ' : 'AI: '}
          {message.parts.map((part, i) =>
            part.type === 'text' ? <span key={i}>{part.text}</span> : null,
          )}
        </div>
      ))}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          sendMessage({ text: input });
          setInput('');
        }}
      >
        <input value={input} onChange={(e) => setInput(e.currentTarget.value)} />
      </form>
    </div>
  );
}

The default POST target is /api/chat. Send with sendMessage({ text }) and keep the input in useState. Render message.parts; do not assume a single content string.

pnpm run dev

Open http://localhost:3000, type a message, and tokens should appear as they stream.


First checklist

  1. pnpm create next-apppnpm add ai @ai-sdk/react zod
  2. Set AI_GATEWAY_API_KEY
  3. Run the generateText snippet (a temporary .mts file is fine)
  4. Add route.ts + page.tsx and confirm streaming chat
  5. Switch model to gateway('anthropic/claude-sonnet-4.5') or openai('gpt-5.1') and confirm it still works

Next, attach a weather tool and status—see useChat and Tools. Timeouts and deploy: Next.js.


Next

评论