AISDK docs are already really good, so this guide is not trying to replace them. I wrote it because I wanted something I could share with friends and coworkers who already know Next.js, but feel a bit lost when they first see generateText, streamText, tools, and all the different examples. My goal was to make a very visual walkthrough of the core primitives, so that you can open this page next to the official docs, click through the demos, glance at the code, and feel comfortable building with AISDK without spending days getting your hands dirty just to understand the basics.
AISDK takes care of the boring parts of working with LLMs so you can focus on behavior and UI instead of HTTP plumbing. It gives you a small set of primitives that repeat everywhere: generate a thing once, stream it, turn it into structured data, or let the model call tools and build agents on top.
This guide walks through those primitives in the order you are likely to use them in a real project. The visual blocks on this page sit on top of the same few calls from the SDK.
I will be using v5 v6 version of AISDK for this guide.
How I recommend you follow this guide
I will say keep the AISDK website open alongside this guide, and refer to the codeblocks Vercel providers for better updated understanding.
They way this guide is set up, helps not only you but also me to refer back to points which I noted. Ive been working on lots projects involving AISDK and there has been a ton on times, that ive been stuck on concepts and wanted someone to guide me through. I will say the AISDK cookbook is really good, and ill link each page I thought should exist and did exist, but I found way to late! There are many great concepts and fun projects we will go through!
So lets first start with the basics.
The Generate Text Function
generateText is the minimal unit of work in the SDK. It takes a prompt (or messages) and gives you back a string. The core docs describe it as ideal for non interactive use, such as drafting copy or summarizing text, and as a building block for agents that will call tools later. Here is an example of using the generateText function, and how it feels, try running it!
Start a conversation
Messages will appear when you press the button above.
Its instant right? If you’re coming from other AI chat applications, you might have felt this was not that beautiful, thats where our next topic comes.
Before going forward I would like to show you how you can implement this function too!
The first time I saw the use of this function was from viewing and understanding the code from https://x.com/pontusab ai-sdk-tools example web page. He used it to generate chat titles of each AI conversation. I found it really useful and try to add this in every production ready AI app. Here is the simple function.
1/**
2 * Generates a minimal chat title from a text
3 */
4export async function generateChatTitleFromText(
5 text: string,
6): Promise<string> {
7 try {
8 const response = await fetch("/api/ai/chat-title", {
9 method: "POST",
10 headers: {
11 "Content-Type": "application/json",
12 },
13 body: JSON.stringify({ text }),
14 })
15
16 if (!response.ok) {
17 throw new Error("Failed to generate title")
18 }
19
20 const { title } = await response.json()
21 return title || text.trim().slice(0, 30) || "New Chat"
22 } catch (error) {
23 console.error("Error generating chat title:", error)
24 const fallback = text.trim().slice(0, 30)
25 return fallback || "New Chat"
26 }
27}and for the route file:
1import { openai } from "@ai-sdk/openai"
2import { generateText } from "ai"
3import { type NextRequest, NextResponse } from "next/server"
4import { CHAT_TITLE_INSTRUCTIONS } from "@/components/ui/support/utils/instructions"
5
6export async function POST(req: NextRequest) {
7 let text: string | undefined
8
9 try {
10 const body = await req.json()
11 text = body.text
12
13 if (!text) {
14 return NextResponse.json(
15 { error: "Text is required" },
16 { status: 400 },
17 )
18 }
19
20 const prompt = `${CHAT_TITLE_INSTRUCTIONS}\n\n<context>\n${text.slice(0, 500)}\n</context>`
21
22 const { text: title } = await generateText({
23 model: openai("gpt-4.1-nano"),
24 prompt,
25 maxOutputTokens: 50,
26 })
27
28 const cleaned = title.trim().replace(/^"|"$/g, "")
29 const finalTitle =
30 cleaned.length > 30
31 ? `${cleaned.slice(0, 27).trim()}...`
32 : cleaned
33
34 return NextResponse.json({ title: finalTitle })
35 } catch (error) {
36 console.error("Error generating chat title:", error)
37 const fallback = text?.trim().slice(0, 30) || "New Chat"
38 return NextResponse.json({ title: fallback })
39 }
40}For the instructions I usually just give it this simple prompt:
1export const CHAT_TITLE_INSTRUCTIONS = `Generate a concise title that captures the user's intent.`There you go! Such a useful funciton, oh wait now you might be wondering how does this even work? Like how does this generateChatTitleFromText generate the title though? When do we pass the text to it so that it runs? You see the next title, the stream text function, it has a onFinish parameter which allows us to run things after the AI generates text, hence we can use it there, simple right!
Here’s one more example, i tried copying how Vercel domains might work in the background to show generate domains as users types a sentence.
The Stream Text Function
streamText does the same job as generateText, but it streams tokens as they arrive instead of waiting for the whole answer. The cookbook articles use it as the default for chat or any experience where you want the UI to feel alive. Here try the demo again, this will feel different!
Start a conversation
Messages will appear when you press the button above.
Amazing right, the text comes in beautifully! You can use this function for your everyday AI apps to generate messages!
Chat Template for testing
Before moving further, for all the experiments we do now, ive made a chat template which uses Vercel ai-elements to render assistant messages beautifully! If someone wants to skip setup and just test models or prompts, the fastest route is to start from an existing template.
repo: https://github.com/Montekkundan/chat-template
Also, Vercel maintains a full featured Next.js chatbot template, now surfaced as Chat SDK, that is built on top of the AI SDK and already wired for streaming, theming, and multiple providers, you can try that too!
Generating Images
The SDK also supports image generation through experimental_generateImage / generateImage. It is marked experimental in the docs, but the API is simple.
Try running this and feel how it works visually.
Start a conversation
Messages will appear when you press the button above.
You can also clone an example which generates images with dall-e-3, it uses the chat-template we discussed about earlier.
repo: https://github.com/Montekkundan/aisdk-generate-image
Using Images as a Prompt
Vision or multi modal models accept images as input as well as text. The Node and Next.js cookbooks show how to attach an image URL or bytes to a message and then call generateText or streamText on top.
Try running this as well, you’ll see how we can send images and AI ( vision or multi modal capable ) replies and tells us what is shown in the image.
Start a conversation
Messages will appear when you press the button above.
Using Files as a Prompt
Some models can read file content such as PDFs directly. The cookbook examples cover two main cases: chatting with PDFs and using a PDF to drive structured object generation
Try this, its same as above but instead we send a pdf.
Start a conversation
Messages will appear when you press the button above.
The Generate Object Function
generateObject is the part of the SDK that most feels like a super power. You give it a Zod schema, a model, and a prompt, and it returns a typed object that matches the schema. The cookbook puts it right next to the basic text recipes, which shows how central it is.
Here is an example, we can ask it “Create a recipe for chocolate chip cookies”, normally the llm would reply back text but we can have it send a structured response which makes us developers create beautiful UI’s on top of that!
Start a conversation
Messages will appear when you press the button above.
The Stream Object Function
Similarly streamObject extends the same idea, but lets you see or use parts of the object while the model is still generating. This is especially interesting for arrays, which appear item by item.
Start a conversation
Messages will appear when you press the button above.
Streaming Custom Data
Extending on the previous stream object AISDK also have a tutorial about streaming custom data, which is pretty amazing!
Here is an example app which shows all we can do with this!
repo: https://github.com/Montekkundan/streaming-custom-data
Rendering Markdown
If you are reading the cookbook about rendering markdown, I would suggest to use streamdown instead, it has pretty usefull features build in! And if you use ai-elements like we do in our chat-template this is already handled!
If you want to dig deeper in this you can read about how they solve the problem of broken streaming markdown!
Tool Calling
Tool calling is where the SDK stops being “just an LLM client” and becomes an agent toolkit. The core docs define tools as functions with typed input schemas that the model can choose to invoke. Tool calls show up as structured data in the stream, you execute the function, then you feed the result back to the model.
So far most examples are “one request in, one response out”. In practice you often want an agent that runs several internal steps inside a single user turn.
So we will look at the complex example rather than running just a simple tool call.
Multi step agents and Human in the Loop
A multi step agent uses streamText together with tools and a step limit so that the model can plan, call tools, refine its answer, and keep streaming into the same UI message instead of jumping between separate responses.
Human in the Loop (HITL) is the safety layer on top of that. The agent can propose actions during those steps, but a person decides which ones actually run. The official AISDK cookbook example defines tools that can mark themselves as “approval required”, and the UI surfaces Approve and Deny buttons before any sensitive tool call is executed.
In this repo I added a small multi step, Human in the Loop demo to make the idea concrete. It has three scenarios: a weather lookup that auto executes, a search plus analysis chain that auto executes and shows multiple tool calls, and a secure operation that pauses until you explicitly approve or deny it.
The app/api/chat/route.ts route uses streamText with a step limit and a processToolCalls layer to gate tools that need approval, then converts the result into a UI message stream. The app/page.tsx chat UI is built with useChat, detects pending tool calls that require confirmation, renders Approve and Deny buttons, and automatically continues once the tool calls finish.
Each tool invocation is rendered by a small AI Elements component that shows parameters, status badges, and the JSON output so you can see what the agent is doing at each step.
repo: https://github.com/Montekkundan/tool-calling
We now also have the tool registry where you can easily package tools and share them with people! Plus use them easily, more about it here https://ai-sdk.dev/tools-registry.
Rendering UI
Tool calling is not only for data. The same mechanism lets the model trigger UI fragments that you render as React components inside the chat stream.
If you follow this, instead of replying with “24°C and sunny,” the model calls getWeatherInformation, and your client turns that tool output into a weather card.
The server uses streamText with a tools object and returns toUIMessageStreamResponse(). On the client, useChat receives UIMessage parts; a switch(part.type) decides whether to render plain text, a confirmation prompt, or a rich component like the weather card.
Typical use cases:
Cards for weather, flights, bookings, or product recommendations
Inline confirmation prompts before running sensitive tools
Small dashboards or forms that appear as part of the conversation
From the user’s perspective it is still “chat,” but each message can carry both language and UI.
Here is another example, recently if you ask Chatgpt to write an email, it generates a separate UI for the email card which allows users to easily open in any mail app or copy it! Here is something similar which i created.
repo: https://github.com/Montekkundan/chat-email-ui
Conclusion
AISDK is also evolving fast. While I was finishing this guide, Vercel shipped v6 dev tools and even more cookbook recipes, which makes it much easier to inspect what your assistants are doing under the hood and debug tool calls step by step.
Think of this guide as a starting map, once you feel at home with generate and stream functions, objects, tools, multi step agents, and human in the loop patterns, you can dig into the official docs, the cookbook, and the sample repos I linked, and start wiring your own AI apps much faster.


