Install any skill in seconds. Free to start, no credit card required.
Get Started Free →You are an expert in the Vercel AI SDK, the TypeScript toolkit for building AI-powered applications. You help developers integrate LLMs (OpenAI, Anthropic, Google, Mistral, Ollama) with React Server Components, streaming UI, tool calling, structured output with Zod schemas, RAG pipelines, multi-step agents, and edge-compatible AI features — the standard way to add AI to Next.js, Nuxt, SvelteKit, and any Node.js app.
.claude/skills/terminalskills-ai-sdk/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 32% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 92% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 891% | 0% |
You are an expert in the Vercel AI SDK, the TypeScript toolkit for building AI-powered applications. You help developers integrate LLMs (OpenAI, Anthropic, Google, Mistral, Ollama) with React Server Components, streaming UI, tool calling, structured output with Zod schemas, RAG pipelines, multi-step agents, and edge-compatible AI features — the standard way to add AI to Next.js, Nuxt, SvelteKit, and any Node.js app.
typescript// AI SDK Core — works in any Node.js/Edge environment import { generateText, generateObject, streamText, streamObject, tool } from "ai"; import { openai } from "@ai-sdk/openai"; import { anthropic } from "@ai-sdk/anthropic"; import { z } from "zod"; // Simple text generation const { text } = await generateText({ model: openai("gpt-4o"), prompt: "Explain quantum computing in 3 sentences", }); // Structured output with Zod schema const { object: analysis } = await generateObject({ model: anthropic("claude-sonnet-4-20250514"), schema: z.object({ sentiment: z.enum(["positive", "negative", "neutral"]), topics: z.array(z.string()), summary: z.string(), confidence: z.number().min(0).max(1), }), prompt: `Analyze this review: "${reviewText}"`, }); // analysis.sentiment → "positive" (fully typed) // Streaming text const result = streamText({ model: openai("gpt-4o"), messages: [{ role: "user", content: "Write a poem about TypeScript" }], }); for await (const chunk of result.textStream) { process.stdout.write(chunk); } // Tool calling (agents) const { text: answer, toolResults } = await generateText({ model: openai("gpt-4o"), tools: { getWeather: tool({ description: "Get weather for a city", parameters: z.object({ city: z.string() }), execute: async ({ city }) => { const res = await fetch(`https://wttr.in/${city}?format=j1`); return res.json(); }, }), searchDatabase: tool({ description: "Search products database", parameters: z.object({ query: z.string(), limit: z.number().default(5) }), execute: async ({ query, limit }) => db.products.search(query, limit), }), }, maxSteps: 5, // Multi-step agent loop prompt: "What's the weather in Tokyo and find related travel products?", });
tsx// app/api/chat/route.ts — API route with streaming import { streamText } from "ai"; import { openai } from "@ai-sdk/openai"; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: openai("gpt-4o"), system: "You are a helpful assistant.", messages, }); return result.toDataStreamResponse(); } // app/chat/page.tsx — Client component "use client"; import { useChat } from "ai/react"; export default function Chat() { const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat(); return ( <div> {messages.map(m => ( <div key={m.id} className={m.role === "user" ? "text-right" : "text-left"}> <p>{m.content}</p> </div> ))} <form onSubmit={handleSubmit}> <input value={input} onChange={handleInputChange} placeholder="Ask anything..." /> <button type="submit" disabled={isLoading}>Send</button> </form> </div> ); } // Streaming UI with RSC import { streamUI } from "ai/rsc"; async function submitMessage(input: string) { "use server"; const result = await streamUI({ model: openai("gpt-4o"), messages: [{ role: "user", content: input }], tools: { showStockPrice: { description: "Show stock price chart", parameters: z.object({ symbol: z.string() }), generate: async function* ({ symbol }) { yield <Spinner />; const data = await getStockData(symbol); return <StockChart data={data} />; // Stream React components! }, }, }, }); return result.value; }
typescriptimport { openai } from "@ai-sdk/openai"; import { anthropic } from "@ai-sdk/anthropic"; import { google } from "@ai-sdk/google"; import { createOllama } from "ollama-ai-provider"; const ollama = createOllama({ baseURL: "http://localhost:11434/api" }); // Same code, different providers const models = { fast: openai("gpt-4o-mini"), smart: anthropic("claude-sonnet-4-20250514"), vision: google("gemini-2.0-flash"), local: ollama("llama3"), }; const { text } = await generateText({ model: models[selectedModel], // Switch provider with zero code changes prompt: userQuery, });
bashnpm install ai @ai-sdk/openai @ai-sdk/anthropic # Provider packages: @ai-sdk/google, @ai-sdk/mistral, ollama-ai-provider
maxSteps: 5-10 for agent loops; AI calls tools, gets results, reasons, repeatsexperimental_telemetry for OpenTelemetry traces; track token usage, latency, errors| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 10,725 | 4,941 | -54% | 1 | 1 | 0% | 2,265 | 2,580 | +14% | 0 | 0 | — |
case-02 | fail→pass | 7,564 | 4,458 | -41% | 1 | 1 | 0% | 1,618 | 2,445 | +51% | 0 | 0 | — |
case-03 | pass→pass | 12,397 | 9,009 | -27% | 1 | 1 | 0% | 2,433 | 3,436 | +41% | 0 | 0 | — |
case-04 | fail→pass | 12,326 | 4,216 | -66% | 1 | 1 | 0% | 2,272 | 2,428 | +7% | 0 | 0 | — |
case-05 | pass→pass | 5,746 | 3,602 | -37% | 1 | 1 | 0% | 1,118 | 2,236 | +100% | 0 | 0 | — |
case-06 | pass→pass | 3,647 | 4,064 | +11% | 1 | 1 | 0% | 672 | 2,469 | +267% | 0 | 0 | — |
case-07 | pass→pass | 5,727 | 7,985 | +39% | 1 | 1 | 0% | 1,044 | 3,138 | +201% | 0 | 0 | — |
case-08 | pass→pass | 16,551 | 10,909 | -34% | 1 | 1 | 0% | 3,326 | 3,974 | +19% | 0 | 0 | — |
case-09 | pass→pass | 11,413 | 7,630 | -33% | 1 | 1 | 0% | 2,295 | 3,205 | +40% | 0 | 0 | — |
case-10 | fail→pass | 10,227 | 6,080 | -41% | 1 | 1 | 0% | 2,209 | 2,911 | +32% | 0 | 0 | — |
case-11 | fail→pass | 5,553 | 2,243 | -60% | 1 | 1 | 0% | 1,051 | 2,022 | +92% | 0 | 0 | — |
case-12 | fail→pass | 1,760 | 2,263 | +29% | 1 | 1 | 0% | 204 | 2,022 | +891% | 0 | 0 | — |
case-13 | pass→pass | 5,742 | 4,229 | -26% | 1 | 1 | 0% | 1,111 | 2,379 | +114% | 0 | 0 | — |
case-14 | pass→pass | 11,239 | 7,976 | -29% | 1 | 1 | 0% | 2,142 | 3,410 | +59% | 0 | 0 | — |
case-15 | pass→pass | 9,347 | 8,740 | -6% | 1 | 1 | 0% | 1,946 | 3,677 | +89% | 0 | 0 | — |
case-16 | pass→pass | 2,357 | 3,311 | +40% | 1 | 1 | 0% | 370 | 2,094 | +466% | 0 | 0 | — |
case-17 | pass→pass | 5,424 | 4,232 | -22% | 1 | 1 | 0% | 966 | 2,212 | +129% | 0 | 0 | — |
case-18 | pass→pass | 9,671 | 8,041 | -17% | 1 | 1 | 0% | 1,963 | 3,308 | +69% | 0 | 0 | — |
case-19 | pass→pass | 5,169 | 5,159 | -0% | 1 | 1 | 0% | 1,183 | 2,728 | +131% | 0 | 0 | — |
case-20 | pass→pass | 10,967 | 9,550 | -13% | 1 | 1 | 0% | 2,189 | 3,462 | +58% | 0 | 0 | — |
case-21 | pass→pass | 7,323 | 6,740 | -8% | 1 | 1 | 0% | 1,440 | 3,003 | +109% | 0 | 0 | — |
case-22 | pass→pass | 5,630 | 4,841 | -14% | 1 | 1 | 0% | 1,149 | 2,476 | +115% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.