AI/TLDR

What Is the Vercel AI SDK?

Understand what the Vercel AI SDK gives you — a provider-agnostic TypeScript layer for streaming, tool calls, and structured output — and when it's the right starting point.

BEGINNER10 MIN READUPDATED 2026-06-13

In plain English

The Vercel AI SDK is a TypeScript toolkit for talking to AI models from your own code. It gives you a small set of functions — most importantly generateText and streamText — that send a prompt to a model and get the answer back, whether you want the whole reply at once or word-by-word as it's written. It runs on the server (Node.js, Next.js, Bun, Cloudflare Workers) and ships React hooks for building the chat UI in the browser.

Vercel AI SDK — illustration
Vercel AI SDK — aitach.com

Think of it as a universal remote for AI models. Every model provider — OpenAI, Anthropic, Google, and dozens more — has its own SDK, its own request shape, and its own quirks. The Vercel AI SDK puts one consistent set of buttons in front of all of them. You write generateText once; swapping from one model to another is a one-line change to the model argument, not a rewrite.

Why it matters

If you're building an AI feature in a JavaScript or TypeScript app, you face the same boring plumbing every time: format the request for this provider, open a streaming connection, parse the server-sent events, accumulate the tokens, handle tool calls, retry on errors, and pipe it all to the browser without the UI freezing. The Vercel AI SDK does that plumbing so you can focus on the feature.

Three problems it solves stand out:

  • Provider lock-in. Without an abstraction layer, your code is welded to one vendor's SDK. Switching providers — or letting users pick a model — means touching every call site. The AI SDK's provider adapters normalize all of them behind one interface, so the model becomes a swappable argument.
  • Streaming is hard to do by hand. Token-by-token streaming is what makes a chatbot feel alive, but doing it manually means managing SSE parsing, backpressure, and partial JSON. streamText returns a ready-made stream, and the React hooks consume it with no glue code.
  • Structured output and tools are fiddly. Getting a model to return clean, typed JSON — or to call your functions — involves schema wrangling and validation. generateObject and the SDK's tool support handle the schema, the validation, and the loop for you.

Who cares? Anyone shipping a chat interface, an AI agent, a "summarize this" button, or an extraction pipeline in a TypeScript stack. It is, in practice, the default starting point for AI features on Next.js and the broader JS ecosystem — and higher-level frameworks like Mastra are built on top of it.

How it works

The SDK has three layers stacked on top of each other. You usually only touch the top one, but knowing all three explains why model-swapping is so cheap.

The core functions

Everything starts with a model object from a provider adapter and a prompt. generateText waits for the full reply; streamText returns immediately with a stream you can iterate or pipe to the client. Both take the same arguments, so moving from one to the other is trivial.

generateText — the whole reply at oncetypescript
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";

const { text } = await generateText({
  model: anthropic("claude-opus-4-8"),
  prompt: "Explain what a vector database is in two sentences.",
});

console.log(text);

To switch providers, change the import and the model line — nothing else. The rest of your code doesn't know or care which model answered.

streamText — token by tokentypescript
import { streamText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";

const result = streamText({
  model: anthropic("claude-opus-4-8"),
  prompt: "Write a haiku about TypeScript.",
});

for await (const chunk of result.textStream) {
  process.stdout.write(chunk); // prints each piece as it arrives
}

The request-to-render path

In a typical web app, the flow runs from a browser click, through a server route that calls the SDK, and back as a live stream the React hook renders. The diagram below traces one message.

The server route is tiny: it reads the incoming messages, calls streamText, and returns the result as a streaming HTTP response. The useChat hook on the client manages the message list, the input box, the loading state, and the incremental rendering — so the component stays declarative.

A worked example: a streaming chat route

Here is the smallest useful chat feature — a server route plus a client component. The server piece is just a few lines because the SDK formats the stream into a shape the React hook understands automatically.

app/api/chat/route.ts — the servertypescript
import { streamText, convertToModelMessages, type UIMessage } from "ai";
import { anthropic } from "@ai-sdk/anthropic";

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

  const result = streamText({
    model: anthropic("claude-opus-4-8"),
    messages: convertToModelMessages(messages),
  });

  // Formats the stream so the useChat hook can read it directly.
  return result.toUIMessageStreamResponse();
}
the client componenttypescript
"use client";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";

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

  return (
    <div>
      {messages.map((m) => (
        <p key={m.id}><b>{m.role}:</b> {m.parts.map((p) =>
          p.type === "text" ? p.text : null)}</p>
      ))}
      <form onSubmit={(e) => { e.preventDefault(); sendMessage({ text: input }); setInput(""); }}>
        <input value={input} onChange={(e) => setInput(e.target.value)} />
      </form>
    </div>
  );
}

Structured output, tools, and the agent loop

Plain text is only half the job. Two more functions cover the cases that make the SDK useful for real applications.

Typed JSON with generateObject

When you need data, not prose, generateObject constrains the model to a schema (defined with Zod) and gives you back a fully typed object. No parsing, no "please return valid JSON" prompt-begging — see structured outputs explained for the underlying idea.

generateObject — schema-validated outputtypescript
import { generateObject } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";

const { object } = await generateObject({
  model: anthropic("claude-opus-4-8"),
  schema: z.object({
    title: z.string(),
    tags: z.array(z.string()),
    sentiment: z.enum(["positive", "neutral", "negative"]),
  }),
  prompt: "Classify this review: 'Fast shipping, but the box was dented.'",
});

console.log(object.sentiment); // typed as the enum — no casting

Tools and the loop

To make a model do things — fetch data, call an API, run a calculation — you give it tools. Each tool is a function with a Zod input schema and an execute callback. The SDK runs the loop for you: the model picks a tool, the SDK runs it, feeds the result back, and repeats until the model produces a final answer. Set stopWhen with stepCountIs to cap the number of steps. That loop — call a tool, observe the result, decide again — is exactly the agent pattern.

a tool-using calltypescript
import { generateText, tool, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";

const { text } = await generateText({
  model: anthropic("claude-opus-4-8"),
  prompt: "What is the weather in Paris right now?",
  tools: {
    getWeather: tool({
      description: "Get the current weather for a city.",
      inputSchema: z.object({ city: z.string() }),
      execute: async ({ city }) => `It is 18°C and clear in ${city}.`,
    }),
  },
  stopWhen: stepCountIs(5), // safety cap on the agent loop
});

How it compares to the alternatives

The AI SDK sits in a specific spot: a thin, TypeScript-native layer, lower-level than a full agent framework but higher-level than each provider's raw SDK.

ApproachBest forTrade-off
Provider's own SDKDeep use of one vendor's unique featuresCode is locked to that provider; you build streaming and tools yourself
Vercel AI SDKProvider-agnostic chat, streaming, tools, structured output in JS/TSThin layer — you still wire up storage, multi-step orchestration, and memory
Full agent framework (e.g. Mastra)Workflows, agent memory, and orchestration out of the boxMore opinionated and heavier; built on the AI SDK anyway
Python frameworks (LangChain, etc.)Python-centric data and ML pipelinesWrong language for a TypeScript/Next.js front end

The short version: reach for the AI SDK when you want one clean interface over many models inside a TypeScript app, and you're happy to assemble the higher-level pieces yourself. Reach for a framework on top of it when you want those pieces pre-built. Reach for the raw provider SDK only when you need a niche feature the abstraction doesn't expose yet.

Going deeper

The four functions above cover most day-to-day work, but a few areas reward a closer look once the basics click.

The provider registry and model strings. Beyond importing each adapter directly, you can register providers centrally and refer to models by string (like "anthropic:claude-opus-4-8"). This makes "let the user choose a model" a configuration concern instead of a code change — handy when you support many models or want to switch defaults without redeploying logic.

Streaming objects, not just text. streamObject is the structured-output cousin of streamText: it streams a JSON object as the model builds it, so a UI can render fields the moment they're ready instead of waiting for the whole object. Useful for forms, dashboards, and any "fill in the blanks as you go" interface.

Edge and serverless runtimes. Because the core is built on web standards (the Fetch API and ReadableStream), it runs on Cloudflare Workers, Vercel's Edge runtime, Deno, and Bun — not just Node.js. This is a real advantage over SDKs that assume a Node-only environment, and it's why streaming works the same way close to the user.

Telemetry, retries, and middleware. Production features hide one level down: automatic retries on transient errors, an abortSignal to cancel a request, OpenTelemetry tracing for observability, and a language-model middleware layer for wrapping calls with logging, caching, or guardrails. You don't need these on day one, but they're why the SDK scales from a demo to a real service.

The honest limits. The AI SDK is deliberately not an agent framework. It gives you a tool loop, but it does not give you durable workflows, long-term memory, or multi-agent orchestration — you build those, or adopt a framework that provides them. Provider adapters also expose a normalized common surface; a brand-new model capability sometimes lands in the raw provider SDK first and reaches the adapter a little later. Knowing where the abstraction ends tells you when to drop down a layer.

FAQ

What is the Vercel AI SDK used for?

It's a TypeScript toolkit for adding AI features to JavaScript and TypeScript apps. You use it to call language models, stream replies token by token, get typed JSON back, and build chat UIs in React — all through one consistent interface that works across many model providers.

What is the difference between generateText and streamText?

generateText waits for the model to finish and returns the complete reply at once — good for short, non-interactive tasks. streamText returns immediately with a stream you can read piece by piece — good for chat UIs where you want text to appear as it's generated. They take the same arguments, so switching between them is a one-line change.

Is the Vercel AI SDK only for Next.js?

No. The core ai package is framework-agnostic and runs on any TypeScript backend — Node.js, Bun, Deno, Cloudflare Workers, and serverless edge runtimes. The React UI hooks (useChat, useCompletion) are convenient with Next.js but optional; you can use the core with any frontend or none at all.

Does the Vercel AI SDK work with Claude and OpenAI?

Yes. It uses provider adapters — @ai-sdk/anthropic for Claude, @ai-sdk/openai for OpenAI, plus adapters for Google, Mistral, and many others. You import the adapter and pass its model to a core function. Switching providers is usually a one-line change to the model argument.

Can the Vercel AI SDK build AI agents?

It gives you the core agent loop: define tools with schemas, and the SDK calls a tool, feeds the result back to the model, and repeats until done (capped with stopWhen). For richer agents with durable workflows, memory, and orchestration, frameworks like Mastra build on top of the AI SDK rather than replacing it.

How do I get structured JSON from the Vercel AI SDK?

Use generateObject (or streamObject to stream it). You pass a Zod schema describing the shape you want, and the SDK constrains the model's output to it and returns a fully typed object — no manual JSON parsing or validation needed.

Further reading