| name | ref-vercel-ai-sdk |
| description | Reference for Vercel AI SDK v6 with Google Gemini provider. Covers streamText, generateText, structured output with Zod, useChat hook, and API route patterns for Next.js App Router. Consult when implementing AI features, debugging streaming, or working with structured outputs. |
Vercel AI SDK + Gemini Reference
Packages
bun add ai @ai-sdk/react @ai-sdk/google zod
ai — Core SDK (v6+): generateText, streamText, Output, tool calling
@ai-sdk/react — React hooks: useChat, useCompletion, useObject
@ai-sdk/google — Gemini provider adapter
zod — Schema validation for structured outputs
Environment Variables
GOOGLE_GENERATIVE_AI_API_KEY=your_gemini_key
The @ai-sdk/google provider reads this env var automatically. No manual config needed.
Core Patterns
1. Streaming Chat (API Route + useChat)
API Route (app/api/chat/route.ts):
import { google } from "@ai-sdk/google";
import { streamText, UIMessage, convertToModelMessages } from "ai";
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: google("gemini-2.5-flash"),
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
Client (components/Chat.tsx):
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
export function Chat() {
const { messages, sendMessage, status, error } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
body: { userId: 'demo-user' },
}),
messages: [
{
id: 'welcome',
role: 'assistant' as 'system' | 'user' | 'assistant',
parts: [{ type: 'text' as const, text: 'Hello!' }],
},
],
});
const isStreaming = status === || status === ;
messages.( ({
: msg.,
: msg..( p. === ).( (p {: }).).(),
}));
({ : });
}
2. Structured Output (generateText + Zod)
import { generateText, Output } from "ai";
import { google } from "@ai-sdk/google";
import { z } from "zod";
const problemSchema = z.object({
title: z.string().describe("Problem title"),
statement: z.string().describe("Problem statement in Markdown"),
skeleton: z.string().describe("Starter code with TODO markers"),
solution: z.string().describe("Complete solution code"),
testCases: z.array(z.object({
input: z.string(),
expectedOutput: z.string(),
description: z.string(),
})).describe("Test cases for validation"),
difficulty: z.enum(["beginner", "intermediate", "advanced"]),
tags: z.array(z.string()),
});
const { output } = await generateText({
: (),
: .({ : problemSchema }),
: ,
});
3. Streaming Structured Output
import { streamText, Output } from "ai";
const { partialOutputStream } = streamText({
model: google("gemini-3.1-pro-preview"),
output: Output.object({ schema: problemSchema }),
prompt: userPrompt,
onError({ error }) {
console.error("Stream error:", error);
},
});
for await (const partialObject of partialOutputStream) {
}
4. Tool Calling
const result = await generateText({
model: google("gemini-3.1-pro-preview"),
tools: {
getWeather: {
description: "Get weather for a location",
parameters: z.object({ location: z.string() }),
execute: async ({ location }) => { },
},
},
prompt: "What's the weather in SF?",
});
Key API Functions
| Function | Use Case |
|---|
generateText() | One-shot generation, background tasks |
streamText() | Real-time streaming to UI |
Output.object({ schema }) | Structured JSON output with Zod validation |
Output.text() | Plain text (default) |
convertToModelMessages() | Convert UIMessage[] to model format |
result.toUIMessageStreamResponse() | Return streaming response for useChat |
result.toDataStreamResponse() | Return streaming response (legacy) |
Gemini Model Names
| Model | ID | Notes |
|---|
| Gemini 2.5 Flash | gemini-2.5-flash | Fast, low latency — use for MCQs, code review |
| Gemini 2.5 Pro | gemini-2.5-pro | Best quality, use for problem generation |
Confirmed Working in This Project
generateObject() with ProblemSchema, MCQBatchSchema, CodeReviewSchema — all compile and build
@ai-sdk/google v3.0.52 — installed, compatible with ai v6.0.134
- Zod v4.3.6 — NOT v3. This project uses Zod v4 which works with AI SDK v6
- Model config in
src/lib/ai/models.ts — centralized, import geminiFlash / geminiPro
Gotchas
- AI SDK v6 uses Server Actions — can bypass API routes entirely, but API routes still work fine
maxDuration — set on API routes to avoid Vercel timeout (default 10s on Hobby)
- Structured output + streaming — use
partialOutputStream NOT output for streaming
- Zod
.describe() — always describe fields, it helps the model understand what to generate
@ai-sdk/google auto-reads GOOGLE_GENERATIVE_AI_API_KEY — don't pass key manually
- No lazy init needed — unlike ElevenLabs/BetterAuth, the
google() function doesn't throw at build time. Safe to call at module scope.
convertToModelMessages() may be async in this SDK build — await convertToModelMessages(messages) before passing to streamText(). Passing the unresolved Promise produces Invalid prompt: The messages do not match the ModelMessage[] schema.