Antigravity-awesome-skills vercel-ai-sdk-expert
Expert in the Vercel AI SDK. Covers Core API (generateText, streamText), UI hooks (useChat, useCompletion), tool calling, and streaming UI components with React and Next.js.
git clone https://github.com/sickn33/antigravity-awesome-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/sickn33/antigravity-awesome-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/antigravity-awesome-skills/skills/vercel-ai-sdk-expert" ~/.claude/skills/sickn33-antigravity-awesome-skills-vercel-ai-sdk-expert-7003a7 && rm -rf "$T"
plugins/antigravity-awesome-skills/skills/vercel-ai-sdk-expert/SKILL.mdVercel AI SDK Expert
You are a production-grade Vercel AI SDK expert. You help developers build AI-powered applications, chatbots, and generative UI experiences primarily using Next.js and React. You are an expert in both the
ai (AI SDK Core) and @ai-sdk/react (AI SDK UI) packages. You understand streaming, language model integration, system prompts, tool calling (function calling), and structured data generation.
When to Use This Skill
- Use when adding AI chat or text generation features to a React or Next.js app
- Use when streaming LLM responses to a frontend UI
- Use when implementing tool calling / function calling with an LLM
- Use when returning structured data (JSON) from an LLM using
generateObject - Use when building AI-powered generative UIs (streaming React components)
- Use when migrating from direct OpenAI/Anthropic API calls to the unified AI SDK
- Use when troubleshooting streaming issues with
oruseChatstreamText
Core Concepts
Why Vercel AI SDK?
The Vercel AI SDK is a unified framework that abstracts away provider-specific APIs (OpenAI, Anthropic, Google Gemini, Mistral). It provides two main layers:
- AI SDK Core (
): Server-side functions to interact with LLMs (ai
,generateText
,streamText
).generateObject - AI SDK UI (
): Frontend hooks to manage chat state and streaming (@ai-sdk/react
,useChat
).useCompletion
Server-Side Generation (Core API)
Basic Text Generation
import { generateText } from "ai"; import { openai } from "@ai-sdk/openai"; // Returns the full string once completion is done (no streaming) const { text, usage } = await generateText({ model: openai("gpt-4o"), system: "You are a helpful assistant evaluating code.", prompt: "Review the following python code...", }); console.log(text); console.log(`Tokens used: ${usage.totalTokens}`);
Streaming Text
// app/api/chat/route.ts (Next.js App Router API Route) import { streamText } from 'ai'; import { openai } from '@ai-sdk/openai'; // Allow streaming responses up to 30 seconds export const maxDuration = 30; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: openai('gpt-4o'), system: 'You are a friendly customer support bot.', messages, }); // Automatically converts the stream to a readable web stream return result.toDataStreamResponse(); }
Structured Data (JSON) Generation
import { generateObject } from 'ai'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; const { object } = await generateObject({ model: openai('gpt-4o-2024-08-06'), // Use models good at structured output system: 'Extract information from the receipt text.', prompt: receiptText, // Pass a Zod schema to enforce output structure schema: z.object({ storeName: z.string(), totalAmount: z.number(), items: z.array(z.object({ name: z.string(), price: z.number(), })), date: z.string().describe("ISO 8601 date format"), }), }); // `object` is automatically fully typed according to the Zod schema! console.log(object.totalAmount);
Frontend UI Hooks
useChat
(Conversational UI)
useChat// app/page.tsx (Next.js Client Component) "use client"; import { useChat } from "ai/react"; export default function Chat() { const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({ api: "/api/chat", // Points to the streamText route created above // Optional callbacks onFinish: (message) => console.log("Done streaming:", message), onError: (error) => console.error(error) }); return ( <div className="flex flex-col h-screen max-w-md mx-auto p-4"> <div className="flex-1 overflow-y-auto mb-4"> {messages.map((m) => ( <div key={m.id} className={`mb-4 ${m.role === 'user' ? 'text-right' : 'text-left'}`}> <span className={`p-2 rounded-lg inline-block ${m.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-200'}`}> {m.target || m.content} </span> </div> ))} </div> <form onSubmit={handleSubmit} className="flex gap-2"> <input value={input} onChange={handleInputChange} placeholder="Say something..." className="flex-1 p-2 border rounded" disabled={isLoading} /> <button type="submit" disabled={isLoading} className="bg-black text-white p-2 rounded"> Send </button> </form> </div> ); }
Tool Calling (Function Calling)
Tools allow the LLM to interact with your code, fetching external data or performing actions before responding to the user.
Server-Side Tool Definition
// app/api/chat/route.ts import { streamText, tool } from 'ai'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: openai('gpt-4o'), messages, tools: { getWeather: tool({ description: 'Get the current weather in a given location', parameters: z.object({ location: z.string().describe('The city and state, e.g. San Francisco, CA'), unit: z.enum(['celsius', 'fahrenheit']).optional(), }), // Execute runs when the LLM decides to call this tool execute: async ({ location, unit = 'celsius' }) => { // Fetch from your actual weather API or database const temp = location.includes("San Francisco") ? 15 : 22; return `The weather in ${location} is ${temp}° ${unit}.`; }, }), }, // Allows the LLM to call tools automatically in a loop until it has the answer maxSteps: 5, }); return result.toDataStreamResponse(); }
UI for Multi-Step Tool Calls
When using
maxSteps, the useChat hook will display intermediate tool calls if you handle them in the UI.
// Inside the `useChat` messages.map loop {m.role === 'assistant' && m.toolInvocations?.map((toolInvocation) => ( <div key={toolInvocation.toolCallId} className="text-sm text-gray-500"> {toolInvocation.state === 'result' ? ( <p>✅ Fetched weather for {toolInvocation.args.location}</p> ) : ( <p>⏳ Fetching weather for {toolInvocation.args.location}...</p> )} </div> ))}
Best Practices
- ✅ Do: Use
oropenai('gpt-4o')
format (from specific provider packages likeanthropic('claude-3-5-sonnet-20240620')
) instead of the older edge runtime wrappers.@ai-sdk/openai - ✅ Do: Provide a strict Zod
and a clearschema
prompt when usingsystem
.generateObject() - ✅ Do: Set
(or higher if on Pro) in Next.js API routes that usemaxDuration = 30
, as LLMs take time to stream responses and Vercel's default is 10-15s.streamText - ✅ Do: Use
with comprehensivetool()
tags on Zod parameters, as the LLM relies entirely on those strings to understand when and how to call the tool.description - ✅ Do: Enable
(or similar) when providing tools, otherwise the LLM won't be able to reply to the user after seeing the tool result!maxSteps: 5 - ❌ Don't: Forget to return
in Next.js App Router API routes when usingresult.toDataStreamResponse()
; standard JSON responses will break chunking.streamText - ❌ Don't: Blindly trust the output of
without validation, even though Zod forces the shape — always handle failure states usinggenerateObject
.try/catch
Troubleshooting
Problem: The streaming chat cuts off abruptly after 10-15 seconds. Solution: The serverless function timed out. Add
export const maxDuration = 30; (or whatever your plan limit is) to the Next.js API route file.
Problem: "Tool execution failed" or the LLM didn't return an answer after using a tool. Solution:
streamText stops immediately after a tool call completes unless you provide maxSteps. Set maxSteps: 2 (or higher) to let the LLM see the tool result and construct a final text response.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.