ai-sdk-core

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AI SDK Core

AI SDK 核心模块

Backend AI with Vercel AI SDK v5 and v6.
Installation:
bash
npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google zod

使用Vercel AI SDK v5和v6构建后端AI。
安装步骤:
bash
npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google zod

AI SDK 6 (Stable - January 2026)

AI SDK 6(稳定版 - 2026年1月)

Status: Stable Latest: ai@6.0.26 (Jan 2026)
状态: 稳定版 最新版本: ai@6.0.26(2026年1月)

BREAKING: Output API Replaces generateObject/streamObject

重大变更:Output API 替代 generateObject/streamObject

⚠️ CRITICAL:
generateObject()
and
streamObject()
are DEPRECATED and will be removed in a future version. Use the new Output API instead.
Before (v5 - DEPRECATED):
typescript
// ❌ DEPRECATED - will be removed
import { generateObject } from 'ai';

const result = await generateObject({
  model: openai('gpt-5'),
  schema: z.object({ name: z.string(), age: z.number() }),
  prompt: 'Generate a person',
});
After (v6 - USE THIS):
typescript
// ✅ NEW OUTPUT API
import { generateText, Output } from 'ai';

const result = await generateText({
  model: openai('gpt-5'),
  output: Output.object({ schema: z.object({ name: z.string(), age: z.number() }) }),
  prompt: 'Generate a person',
});

// Access the typed object
console.log(result.object); // { name: "Alice", age: 30 }
⚠️ 重要提示
generateObject()
streamObject()
已被弃用,将在后续版本中移除,请使用新的Output API替代。
之前(v5 - 已弃用):
typescript
// ❌ 已弃用 - 将会被移除
import { generateObject } from 'ai';

const result = await generateObject({
  model: openai('gpt-5'),
  schema: z.object({ name: z.string(), age: z.number() }),
  prompt: 'Generate a person',
});
现在(v6 - 推荐使用):
typescript
// ✅ 新的OUTPUT API
import { generateText, Output } from 'ai';

const result = await generateText({
  model: openai('gpt-5'),
  output: Output.object({ schema: z.object({ name: z.string(), age: z.number() }) }),
  prompt: 'Generate a person',
});

// 访问类型化对象
console.log(result.object); // { name: "Alice", age: 30 }

Output Types

输出类型

typescript
import { generateText, Output } from 'ai';

// Object with Zod schema
output: Output.object({ schema: myZodSchema })

// Array of typed objects
output: Output.array({ schema: personSchema })

// Enum/choice from options
output: Output.choice({ choices: ['positive', 'negative', 'neutral'] })

// Plain text (explicit)
output: Output.text()

// Unstructured JSON (no schema validation)
output: Output.json()
typescript
import { generateText, Output } from 'ai';

// 基于Zod schema的对象
output: Output.object({ schema: myZodSchema })

// 类型化对象数组
output: Output.array({ schema: personSchema })

// 从选项中选择枚举值
output: Output.choice({ choices: ['positive', 'negative', 'neutral'] })

// 纯文本(显式声明)
output: Output.text()

// 无结构JSON(无schema验证)
output: Output.json()

Streaming with Output API

结合Output API实现流式输出

typescript
import { streamText, Output } from 'ai';

const result = streamText({
  model: openai('gpt-5'),
  output: Output.object({ schema: personSchema }),
  prompt: 'Generate a person',
});

// Stream partial objects
for await (const partialObject of result.objectStream) {
  console.log(partialObject); // { name: "Ali..." } -> { name: "Alice", age: ... }
}

// Get final object
const finalObject = await result.object;
typescript
import { streamText, Output } from 'ai';

const result = streamText({
  model: openai('gpt-5'),
  output: Output.object({ schema: personSchema }),
  prompt: 'Generate a person',
});

// 流式获取部分对象
for await (const partialObject of result.objectStream) {
  console.log(partialObject); // { name: "Ali..." } -> { name: "Alice", age: ... }
}

// 获取最终完整对象
const finalObject = await result.object;

v6 New Features

v6 新特性

1. Agent Abstraction Unified interface for building agents with
ToolLoopAgent
class:
  • Full control over execution flow, tool loops, and state management
  • Replaces manual tool calling orchestration
2. Tool Execution Approval (Human-in-the-Loop)
Use selective approval for better UX. Not every tool call needs approval.
typescript
tools: {
  payment: tool({
    // Dynamic approval based on input
    needsApproval: async ({ amount }) => amount > 1000,
    inputSchema: z.object({ amount: z.number() }),
    execute: async ({ amount }) => { /* process payment */ },
  }),

  readFile: tool({
    needsApproval: false, // Safe operations don't need approval
    inputSchema: z.object({ path: z.string() }),
    execute: async ({ path }) => fs.readFile(path),
  }),

  deleteFile: tool({
    needsApproval: true, // Destructive operations always need approval
    inputSchema: z.object({ path: z.string() }),
    execute: async ({ path }) => fs.unlink(path),
  }),
}
Best Practices:
  • Use dynamic approval for operations where risk depends on parameters (e.g., payment amount)
  • Always require approval for destructive operations (delete, modify, purchase)
  • Don't require approval for safe read operations
  • Add system instruction: "When a tool execution is not approved, do not retry it"
  • Implement timeout for approval requests to prevent stuck states
  • Store user preferences for repeat actions
Sources:
3. Reranking for RAG
typescript
import { rerank } from 'ai';

const result = await rerank({
  model: cohere.reranker('rerank-v3.5'),
  query: 'user question',
  documents: searchResults,
  topK: 5,
});
4. MCP Tools (Model Context Protocol)
⚠️ SECURITY WARNING: MCP tools have significant production risks. See security section below.
typescript
import { experimental_createMCPClient } from 'ai';

const mcpClient = await experimental_createMCPClient({
  transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem'] },
});

const tools = await mcpClient.tools();

const result = await generateText({
  model: openai('gpt-5'),
  tools,
  prompt: 'List files in the current directory',
});
Known Issue: MCP tools may not execute in streaming mode (Vercel Community Discussion). Use
generateText()
instead of
streamText()
for MCP tools.
MCP Security Considerations
⚠️ CRITICAL: Dynamic MCP tools in production have security risks:
Risks:
  • Tool definitions become part of your agent's prompt
  • Can change unexpectedly without warning
  • Compromised MCP server can inject malicious prompts
  • New tools can escalate user privileges (e.g., adding delete to read-only server)
Solution - Use Static Tool Generation:
typescript
// ❌ RISKY: Dynamic tools change without your control
const mcpClient = await experimental_createMCPClient({ /* ... */ });
const tools = await mcpClient.tools(); // Can change anytime!

// ✅ SAFE: Generate static, versioned tool definitions
// Step 1: Install mcp-to-ai-sdk
npm install -g mcp-to-ai-sdk

// Step 2: Generate static tools (one-time, version controlled)
npx mcp-to-ai-sdk generate stdio 'npx -y @modelcontextprotocol/server-filesystem'

// Step 3: Import static tools
import { tools } from './generated-mcp-tools';

const result = await generateText({
  model: openai('gpt-5'),
  tools, // Static, reviewed, versioned
  prompt: 'Use tools',
});
Best Practice: Generate static tools, review them, commit to version control, and only update intentionally.
5. Language Model Middleware
typescript
import { wrapLanguageModel, extractReasoningMiddleware } from 'ai';

const wrappedModel = wrapLanguageModel({
  model: anthropic('claude-sonnet-4-5-20250929'),
  middleware: extractReasoningMiddleware({ tagName: 'think' }),
});

// Reasoning extracted automatically from <think>...</think> tags
6. Telemetry (OpenTelemetry)
typescript
const result = await generateText({
  model: openai('gpt-5'),
  prompt: 'Hello',
  experimental_telemetry: {
    isEnabled: true,
    functionId: 'my-chat-function',
    metadata: { userId: '123' },
    recordInputs: true,
    recordOutputs: true,
  },
});

1. Agent抽象层 通过
ToolLoopAgent
类提供构建Agent的统一接口:
  • 完全控制执行流程、工具循环和状态管理
  • 替代手动编排工具调用的方式
2. 工具执行审批(人机协作)
使用选择性审批提升用户体验,并非所有工具调用都需要审批。
typescript
tools: {
  payment: tool({
    // 根据输入动态判断是否需要审批
    needsApproval: async ({ amount }) => amount > 1000,
    inputSchema: z.object({ amount: z.number() }),
    execute: async ({ amount }) => { /* 处理支付 */ },
  }),

  readFile: tool({
    needsApproval: false, // 安全的读取操作无需审批
    inputSchema: z.object({ path: z.string() }),
    execute: async ({ path }) => fs.readFile(path),
  }),

  deleteFile: tool({
    needsApproval: true, // 破坏性操作始终需要审批
    inputSchema: z.object({ path: z.string() }),
    execute: async ({ path }) => fs.unlink(path),
  }),
}
最佳实践:
  • 对于风险取决于参数的操作(如支付金额),使用动态审批
  • 对于破坏性操作(删除、修改、购买),始终要求审批
  • 安全的读取操作无需审批
  • 添加系统指令:"当工具执行未获审批时,请勿重试"
  • 为审批请求设置超时,避免流程卡住
  • 存储用户对重复操作的偏好设置
参考来源:
3. RAG重排序
typescript
import { rerank } from 'ai';

const result = await rerank({
  model: cohere.reranker('rerank-v3.5'),
  query: 'user question',
  documents: searchResults,
  topK: 5,
});
4. MCP工具(模型上下文协议)
⚠️ 安全警告:MCP工具在生产环境中存在重大风险,请查看下方的安全章节。
typescript
import { experimental_createMCPClient } from 'ai';

const mcpClient = await experimental_createMCPClient({
  transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem'] },
});

const tools = await mcpClient.tools();

const result = await generateText({
  model: openai('gpt-5'),
  tools,
  prompt: 'List files in the current directory',
});
已知问题:MCP工具在流式模式下可能无法执行(Vercel社区讨论)。使用MCP工具时,请使用
generateText()
而非
streamText()
MCP安全注意事项
⚠️ 重要提示:生产环境中使用动态MCP工具存在安全风险:
风险:
  • 工具定义会成为Agent提示词的一部分
  • 工具定义可能会意外变更,无预警
  • 被攻陷的MCP服务器可能注入恶意提示词
  • 新增工具可能提升用户权限(例如,为只读服务器添加删除权限)
解决方案 - 使用静态工具生成:
typescript
// ❌ 有风险:动态工具会不受控制地变更
const mcpClient = await experimental_createMCPClient({ /* ... */ });
const tools = await mcpClient.tools(); // 随时可能变更!

// ✅ 安全方案:生成静态、版本化的工具定义
// 步骤1:安装mcp-to-ai-sdk
npm install -g mcp-to-ai-sdk

// 步骤2:生成静态工具(一次性操作,纳入版本控制)
npx mcp-to-ai-sdk generate stdio 'npx -y @modelcontextprotocol/server-filesystem'

// 步骤3:导入静态工具
import { tools } from './generated-mcp-tools';

const result = await generateText({
  model: openai('gpt-5'),
  tools, // 静态、已审核、版本化
  prompt: 'Use tools',
});
最佳实践:生成静态工具,进行审核,提交到版本控制系统,仅在必要时更新。
5. 语言模型中间件
typescript
import { wrapLanguageModel, extractReasoningMiddleware } from 'ai';

const wrappedModel = wrapLanguageModel({
  model: anthropic('claude-sonnet-4-5-20250929'),
  middleware: extractReasoningMiddleware({ tagName: 'think' }),
});

// 自动从<think>...</think>标签中提取推理过程
6. 遥测(OpenTelemetry)
typescript
const result = await generateText({
  model: openai('gpt-5'),
  prompt: 'Hello',
  experimental_telemetry: {
    isEnabled: true,
    functionId: 'my-chat-function',
    metadata: { userId: '123' },
    recordInputs: true,
    recordOutputs: true,
  },
});

Latest AI Models (2025-2026)

最新AI模型(2025-2026)

OpenAI

OpenAI

GPT-5.2 (Dec 2025):
  • 400k context window, 128k output tokens
  • Enhanced reasoning capabilities
  • Available in API platform
GPT-5.1 (Nov 2025):
  • Improved speed and efficiency over GPT-5
  • "Warmer" and more intelligent responses
GPT-5 (Aug 2025):
  • 45% less hallucination than GPT-4o
  • State-of-the-art in math, coding, visual perception
o3 Reasoning Models (Dec 2025):
  • o3, o3-pro, o3-mini - Advanced reasoning
  • o4-mini - Fast reasoning
typescript
import { openai } from '@ai-sdk/openai';
const gpt52 = openai('gpt-5.2');
const gpt51 = openai('gpt-5.1');
const gpt5 = openai('gpt-5');
const o3 = openai('o3');
const o3mini = openai('o3-mini');
GPT-5.2(2025年12月):
  • 400k上下文窗口,128k输出tokens
  • 增强的推理能力
  • 已在API平台上线
GPT-5.1(2025年11月):
  • 比GPT-5更快、更高效
  • 回复更"人性化"且更智能
GPT-5(2025年8月):
  • 幻觉率比GPT-4o低45%
  • 在数学、编码、视觉感知领域达到最先进水平
o3推理模型(2025年12月):
  • o3, o3-pro, o3-mini - 高级推理能力
  • o4-mini - 快速推理
typescript
import { openai } from '@ai-sdk/openai';
const gpt52 = openai('gpt-5.2');
const gpt51 = openai('gpt-5.1');
const gpt5 = openai('gpt-5');
const o3 = openai('o3');
const o3mini = openai('o3-mini');

Anthropic

Anthropic

Claude 4 Family (May-Oct 2025):
  • Opus 4 (May 22): Best for complex reasoning, $15/$75 per million tokens
  • Sonnet 4 (May 22): Balanced performance, $3/$15 per million tokens
  • Opus 4.1 (Aug 5): Enhanced agentic tasks, real-world coding
  • Sonnet 4.5 (Sept 29): Most capable for coding, agents, computer use
  • Haiku 4.5 (Oct 15): Small, fast, low-latency model
typescript
import { anthropic } from '@ai-sdk/anthropic';
const sonnet45 = anthropic('claude-sonnet-4-5-20250929');  // Latest
const opus41 = anthropic('claude-opus-4-1-20250805');
const haiku45 = anthropic('claude-haiku-4-5-20251015');
Claude 4系列(2025年5-10月):
  • Opus 4(5月22日): 最适合复杂推理,每百万tokens费用$15/$75
  • Sonnet 4(5月22日): 性能均衡,每百万tokens费用$3/$15
  • Opus 4.1(8月5日): 增强Agent任务处理能力,支持实际场景编码
  • Sonnet 4.5(9月29日): 最适合编码、Agent、计算机操作的版本
  • Haiku 4.5(10月15日): 轻量、快速、低延迟模型
typescript
import { anthropic } from '@ai-sdk/anthropic';
const sonnet45 = anthropic('claude-sonnet-4-5-20250929');  // 最新版本
const opus41 = anthropic('claude-opus-4-1-20250805');
const haiku45 = anthropic('claude-haiku-4-5-20251015');

Google

Google

Gemini 2.5 Family (Mar-Sept 2025):
  • Pro (March 2025): Most intelligent, #1 on LMArena at launch
  • Pro Deep Think (May 2025): Enhanced reasoning mode
  • Flash (May 2025): Fast, cost-effective
  • Flash-Lite (Sept 2025): Updated efficiency
typescript
import { google } from '@ai-sdk/google';
const pro = google('gemini-2.5-pro');
const flash = google('gemini-2.5-flash');
const lite = google('gemini-2.5-flash-lite');

Gemini 2.5系列(2025年3-9月):
  • Pro(2025年3月): 最智能,发布时在LMArena排名第一
  • Pro Deep Think(2025年5月): 增强推理模式
  • Flash(2025年5月): 快速、高性价比
  • Flash-Lite(2025年9月): 优化后的高效版本
typescript
import { google } from '@ai-sdk/google';
const pro = google('gemini-2.5-pro');
const flash = google('gemini-2.5-flash');
const lite = google('gemini-2.5-flash-lite');

Core Functions

核心功能

Text Generation

文本生成

generateText() - Text completion with tools streamText() - Real-time streaming
generateText() - 支持工具调用的文本补全 streamText() - 实时流式输出

Structured Output (v6 Output API)

结构化输出(v6 Output API)

Output.object() - Typed objects with Zod schema (replaces generateObject) Output.array() - Typed arrays Output.choice() - Enum selection Output.json() - Unstructured JSON
See "AI SDK 6" section above for usage examples.
Output.object() - 基于Zod schema的类型化对象(替代generateObject) Output.array() - 类型化数组 Output.choice() - 枚举选择 Output.json() - 无结构JSON
使用示例请查看上方"AI SDK 6"章节。

Multi-Modal Capabilities

多模态能力

Speech Synthesis (Text-to-Speech)

语音合成(文本转语音)

typescript
import { experimental_generateSpeech as generateSpeech } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await generateSpeech({
  model: openai.speech('tts-1-hd'),
  voice: 'alloy',
  text: 'Hello, how can I help you today?',
});

// result.audio is an ArrayBuffer containing the audio
const audioBuffer = result.audio;
Supported Providers:
  • OpenAI: tts-1, tts-1-hd, gpt-4o-mini-tts
  • ElevenLabs: eleven_multilingual_v2, eleven_turbo_v2
  • LMNT, Hume
typescript
import { experimental_generateSpeech as generateSpeech } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await generateSpeech({
  model: openai.speech('tts-1-hd'),
  voice: 'alloy',
  text: 'Hello, how can I help you today?',
});

// result.audio是包含音频的ArrayBuffer
const audioBuffer = result.audio;
支持的提供商:
  • OpenAI: tts-1, tts-1-hd, gpt-4o-mini-tts
  • ElevenLabs: eleven_multilingual_v2, eleven_turbo_v2
  • LMNT, Hume

Transcription (Speech-to-Text)

语音转文字

typescript
import { experimental_transcribe as transcribe } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await transcribe({
  model: openai.transcription('whisper-1'),
  audio: audioFile, // File, Blob, ArrayBuffer, or URL
});

console.log(result.text); // Transcribed text
console.log(result.segments); // Timestamped segments
Supported Providers:
  • OpenAI: whisper-1
  • ElevenLabs, Deepgram, AssemblyAI, Groq, Rev.ai
typescript
import { experimental_transcribe as transcribe } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await transcribe({
  model: openai.transcription('whisper-1'),
  audio: audioFile, // File, Blob, ArrayBuffer或URL
});

console.log(result.text); // 转录后的文本
console.log(result.segments); // 带时间戳的分段内容
支持的提供商:
  • OpenAI: whisper-1
  • ElevenLabs, Deepgram, AssemblyAI, Groq, Rev.ai

Image Generation

图像生成

typescript
import { generateImage } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await generateImage({
  model: openai.image('dall-e-3'),
  prompt: 'A futuristic city at sunset',
  size: '1024x1024',
  n: 1,
});

// result.images is an array of generated images
const imageUrl = result.images[0].url;
const imageBase64 = result.images[0].base64;
Supported Providers:
  • OpenAI: dall-e-2, dall-e-3
  • Google: imagen-3.0
  • Fal AI, Black Forest Labs (Flux), Luma AI, Replicate
typescript
import { generateImage } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = await generateImage({
  model: openai.image('dall-e-3'),
  prompt: 'A futuristic city at sunset',
  size: '1024x1024',
  n: 1,
});

// result.images是生成的图像数组
const imageUrl = result.images[0].url;
const imageBase64 = result.images[0].base64;
支持的提供商:
  • OpenAI: dall-e-2, dall-e-3
  • Google: imagen-3.0
  • Fal AI, Black Forest Labs (Flux), Luma AI, Replicate

Embeddings

向量嵌入

typescript
import { embed, embedMany, cosineSimilarity } from 'ai';
import { openai } from '@ai-sdk/openai';

// Single embedding
const result = await embed({
  model: openai.embedding('text-embedding-3-small'),
  value: 'Hello world',
});
console.log(result.embedding); // number[]

// Multiple embeddings (parallel processing)
const results = await embedMany({
  model: openai.embedding('text-embedding-3-small'),
  values: ['Hello', 'World', 'AI'],
  maxParallelCalls: 5, // Parallel processing
});

// Compare similarity
const similarity = cosineSimilarity(
  results.embeddings[0],
  results.embeddings[1]
);
console.log(`Similarity: ${similarity}`); // 0.0 to 1.0
Supported Providers:
  • OpenAI: text-embedding-3-small, text-embedding-3-large
  • Google: text-embedding-004
  • Cohere, Voyage AI, Mistral, Amazon Bedrock
typescript
import { embed, embedMany, cosineSimilarity } from 'ai';
import { openai } from '@ai-sdk/openai';

// 单个文本嵌入
const result = await embed({
  model: openai.embedding('text-embedding-3-small'),
  value: 'Hello world',
});
console.log(result.embedding); // number[]

// 多个文本嵌入(并行处理)
const results = await embedMany({
  model: openai.embedding('text-embedding-3-small'),
  values: ['Hello', 'World', 'AI'],
  maxParallelCalls: 5, // 并行处理
});

// 计算相似度
const similarity = cosineSimilarity(
  results.embeddings[0],
  results.embeddings[1]
);
console.log(`Similarity: ${similarity}`); // 0.0到1.0之间
支持的提供商:
  • OpenAI: text-embedding-3-small, text-embedding-3-large
  • Google: text-embedding-004
  • Cohere, Voyage AI, Mistral, Amazon Bedrock

Multi-Modal Prompts (Files, Images, PDFs)

多模态提示词(文件、图像、PDF)

typescript
import { generateText } from 'ai';
import { google } from '@ai-sdk/google';

const result = await generateText({
  model: google('gemini-2.5-pro'),
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'Summarize this document' },
      { type: 'file', data: pdfBuffer, mimeType: 'application/pdf' },
    ],
  }],
});

// Or with images
const result = await generateText({
  model: openai('gpt-5'),
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What is in this image?' },
      { type: 'image', image: imageBuffer },
    ],
  }],
});
See official docs for full API: https://ai-sdk.dev/docs/ai-sdk-core

typescript
import { generateText } from 'ai';
import { google } from '@ai-sdk/google';

const result = await generateText({
  model: google('gemini-2.5-pro'),
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'Summarize this document' },
      { type: 'file', data: pdfBuffer, mimeType: 'application/pdf' },
    ],
  }],
});

// 或者结合图像
const result = await generateText({
  model: openai('gpt-5'),
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What is in this image?' },
      { type: 'image', image: imageBuffer },
    ],
  }],
});
完整API请查看官方文档:https://ai-sdk.dev/docs/ai-sdk-core

v5 Stream Response Methods

v5 流式响应方法

When returning streaming responses from an API, use the correct method:
MethodOutput FormatUse Case
toTextStreamResponse()
Plain text chunksSimple text streaming
toUIMessageStreamResponse()
SSE with JSON eventsChat UIs (text-start, text-delta, text-end, finish)
For chat widgets and UIs, always use
toUIMessageStreamResponse()
:
typescript
const result = streamText({
  model: workersai('@cf/qwen/qwen3-30b-a3b-fp8'),
  messages,
  system: 'You are helpful.',
});

// ✅ For chat UIs - returns SSE with JSON events
return result.toUIMessageStreamResponse({
  headers: { 'Access-Control-Allow-Origin': '*' },
});

// ❌ For simple text - returns plain text chunks only
return result.toTextStreamResponse();
Note:
toDataStreamResponse()
does NOT exist in AI SDK v5 (common misconception).

从API返回流式响应时,请使用正确的方法:
方法输出格式使用场景
toTextStreamResponse()
纯文本分片简单文本流式输出
toUIMessageStreamResponse()
带JSON事件的SSE聊天UI(text-start, text-delta, text-end, finish)
对于聊天组件和UI,始终使用
toUIMessageStreamResponse()
:
typescript
const result = streamText({
  model: workersai('@cf/qwen/qwen3-30b-a3b-fp8'),
  messages,
  system: 'You are helpful.',
});

// ✅ 聊天UI使用 - 返回带JSON事件的SSE
return result.toUIMessageStreamResponse({
  headers: { 'Access-Control-Allow-Origin': '*' },
});

// ❌ 简单文本使用 - 仅返回纯文本分片
return result.toTextStreamResponse();
注意: AI SDK v5中不存在
toDataStreamResponse()
(常见误解)。

workers-ai-provider Version Compatibility

workers-ai-provider 版本兼容性

IMPORTANT:
workers-ai-provider@2.x
requires AI SDK v5, NOT v4.
bash
undefined
重要提示:
workers-ai-provider@2.x
需要AI SDK v5,不支持v4。
bash
undefined

✅ Correct - AI SDK v5 with workers-ai-provider v2

✅ 正确搭配 - AI SDK v5 + workers-ai-provider v2

npm install ai@^5.0.0 workers-ai-provider@^2.0.0 zod@^3.25.0
npm install ai@^5.0.0 workers-ai-provider@^2.0.0 zod@^3.25.0

❌ Wrong - AI SDK v4 causes error

❌ 错误搭配 - AI SDK v4会导致错误

npm install ai@^4.0.0 workers-ai-provider@^2.0.0
npm install ai@^4.0.0 workers-ai-provider@^2.0.0

Error: "AI SDK 4 only supports models that implement specification version v1"

错误信息: "AI SDK 4 only supports models that implement specification version v1"


**Zod Version:** AI SDK v5 requires `zod@^3.25.0` or later for `zod/v3` and `zod/v4` exports. Older versions (3.22.x) cause build errors: "Could not resolve zod/v4".

---

**Zod版本:** AI SDK v5需要`zod@^3.25.0`或更高版本,以支持`zod/v3`和`zod/v4`导出。旧版本(3.22.x)会导致构建错误:"Could not resolve zod/v4"。

---

Cloudflare Workers Startup Fix

Cloudflare Workers 启动修复

Problem: AI SDK v5 + Zod causes >270ms startup time (exceeds Workers 400ms limit).
Solution:
typescript
// ❌ BAD: Top-level imports cause startup overhead
import { createWorkersAI } from 'workers-ai-provider';
const workersai = createWorkersAI({ binding: env.AI });

// ✅ GOOD: Lazy initialization inside handler
app.post('/chat', async (c) => {
  const { createWorkersAI } = await import('workers-ai-provider');
  const workersai = createWorkersAI({ binding: c.env.AI });
  // ...
});
Additional:
  • Minimize top-level Zod schemas
  • Move complex schemas into route handlers
  • Monitor startup time with Wrangler

问题: AI SDK v5 + Zod导致启动时间超过270ms(超过Workers 400ms限制)。
解决方案:
typescript
// ❌ 不良实践:顶层导入会增加启动开销
import { createWorkersAI } from 'workers-ai-provider';
const workersai = createWorkersAI({ binding: env.AI });

// ✅ 良好实践:在处理器内部延迟初始化
app.post('/chat', async (c) => {
  const { createWorkersAI } = await import('workers-ai-provider');
  const workersai = createWorkersAI({ binding: c.env.AI });
  // ...
});
额外建议:
  • 尽量减少顶层Zod schema
  • 将复杂schema移到路由处理器内部
  • 使用Wrangler监控启动时间

v5 Tool Calling Changes

v5 工具调用变更

Breaking Changes:
  • parameters
    inputSchema
    (Zod schema)
  • Tool properties:
    args
    input
    ,
    result
    output
  • ToolExecutionError
    removed (now
    tool-error
    content parts)
  • maxSteps
    parameter removed → Use
    stopWhen(stepCountIs(n))
New in v5:
  • Dynamic tools (add tools at runtime based on context)
  • Agent class (multi-step execution with tools)

重大变更:
  • parameters
    inputSchema
    (Zod schema)
  • 工具属性:
    args
    input
    ,
    result
    output
  • ToolExecutionError
    已移除(现在使用
    tool-error
    内容片段)
  • maxSteps
    参数已移除 → 使用
    stopWhen(stepCountIs(n))
v5 新特性:
  • 动态工具(根据上下文在运行时添加工具)
  • Agent类(支持多步工具执行)

Critical v4→v5 Migration

关键v4→v5迁移指南

AI SDK v5 introduced extensive breaking changes. If migrating from v4, follow this guide.
AI SDK v5引入了大量重大变更。如果从v4迁移,请遵循本指南。

Breaking Changes Overview

重大变更概述

  1. Parameter Renames
    • maxTokens
      maxOutputTokens
    • providerMetadata
      providerOptions
  2. Tool Definitions
    • parameters
      inputSchema
    • Tool properties:
      args
      input
      ,
      result
      output
  3. Message Types
    • CoreMessage
      ModelMessage
    • Message
      UIMessage
    • convertToCoreMessages
      convertToModelMessages
  4. Tool Error Handling
    • ToolExecutionError
      class removed
    • Now
      tool-error
      content parts
    • Enables automated retry
  5. Multi-Step Execution
    • maxSteps
      stopWhen
    • Use
      stepCountIs()
      or
      hasToolCall()
  6. Message Structure
    • Simple
      content
      string →
      parts
      array
    • Parts: text, file, reasoning, tool-call, tool-result
  7. Streaming Architecture
    • Single chunk → start/delta/end lifecycle
    • Unique IDs for concurrent streams
  8. Tool Streaming
    • Enabled by default
    • toolCallStreaming
      option removed
  9. Package Reorganization
    • ai/rsc
      @ai-sdk/rsc
    • ai/react
      @ai-sdk/react
    • LangChainAdapter
      @ai-sdk/langchain
  1. 参数重命名
    • maxTokens
      maxOutputTokens
    • providerMetadata
      providerOptions
  2. 工具定义
    • parameters
      inputSchema
    • 工具属性:
      args
      input
      ,
      result
      output
  3. 消息类型
    • CoreMessage
      ModelMessage
    • Message
      UIMessage
    • convertToCoreMessages
      convertToModelMessages
  4. 工具错误处理
    • ToolExecutionError
      类已移除
    • 现在使用
      tool-error
      内容片段
    • 支持自动重试
  5. 多步执行
    • maxSteps
      stopWhen
    • 使用
      stepCountIs()
      hasToolCall()
  6. 消息结构
    • 简单
      content
      字符串 →
      parts
      数组
    • 片段类型: text, file, reasoning, tool-call, tool-result
  7. 流式架构
    • 单一分片 → start/delta/end生命周期
    • 为并发流分配唯一ID
  8. 工具流式输出
    • 默认启用
    • toolCallStreaming
      选项已移除
  9. 包结构调整
    • ai/rsc
      @ai-sdk/rsc
    • ai/react
      @ai-sdk/react
    • LangChainAdapter
      @ai-sdk/langchain

Migration Examples

迁移示例

Before (v4):
typescript
import { generateText } from 'ai';

const result = await generateText({
  model: openai.chat('gpt-4-turbo'),
  maxTokens: 500,
  providerMetadata: { openai: { user: 'user-123' } },
  tools: {
    weather: {
      description: 'Get weather',
      parameters: z.object({ location: z.string() }),
      execute: async (args) => { /* args.location */ },
    },
  },
  maxSteps: 5,
});
After (v5):
typescript
import { generateText, tool, stopWhen, stepCountIs } from 'ai';

const result = await generateText({
  model: openai('gpt-4-turbo'),
  maxOutputTokens: 500,
  providerOptions: { openai: { user: 'user-123' } },
  tools: {
    weather: tool({
      description: 'Get weather',
      inputSchema: z.object({ location: z.string() }),
      execute: async ({ location }) => { /* input.location */ },
    }),
  },
  stopWhen: stepCountIs(5),
});
之前(v4):
typescript
import { generateText } from 'ai';

const result = await generateText({
  model: openai.chat('gpt-4-turbo'),
  maxTokens: 500,
  providerMetadata: { openai: { user: 'user-123' } },
  tools: {
    weather: {
      description: 'Get weather',
      parameters: z.object({ location: z.string() }),
      execute: async (args) => { /* args.location */ },
    },
  },
  maxSteps: 5,
});
现在(v5):
typescript
import { generateText, tool, stopWhen, stepCountIs } from 'ai';

const result = await generateText({
  model: openai('gpt-4-turbo'),
  maxOutputTokens: 500,
  providerOptions: { openai: { user: 'user-123' } },
  tools: {
    weather: tool({
      description: 'Get weather',
      inputSchema: z.object({ location: z.string() }),
      execute: async ({ location }) => { /* input.location */ },
    }),
  },
  stopWhen: stepCountIs(5),
});

Migration Checklist

迁移检查清单

  • Update all
    maxTokens
    to
    maxOutputTokens
  • Update
    providerMetadata
    to
    providerOptions
  • Convert tool
    parameters
    to
    inputSchema
  • Update tool execute functions:
    args
    input
  • Replace
    maxSteps
    with
    stopWhen(stepCountIs(n))
  • Update message types:
    CoreMessage
    ModelMessage
  • Remove
    ToolExecutionError
    handling
  • Update package imports (
    ai/rsc
    @ai-sdk/rsc
    )
  • Test streaming behavior (architecture changed)
  • Update TypeScript types
  • 将所有
    maxTokens
    更新为
    maxOutputTokens
  • providerMetadata
    更新为
    providerOptions
  • 将工具
    parameters
    转换为
    inputSchema
  • 更新工具执行函数:
    args
    input
  • stopWhen(stepCountIs(n))
    替换
    maxSteps
  • 更新消息类型:
    CoreMessage
    ModelMessage
  • 移除
    ToolExecutionError
    相关处理
  • 更新包导入路径(
    ai/rsc
    @ai-sdk/rsc
  • 测试流式输出行为(架构已变更)
  • 更新TypeScript类型

Automated Migration

自动迁移

AI SDK provides a migration tool:
bash
npx ai migrate
This will update most breaking changes automatically. Review changes carefully.

AI SDK提供迁移工具:
bash
npx ai migrate
该工具会自动修复大部分重大变更。请仔细检查变更内容。

Top 15 Errors & Solutions

15个常见错误及解决方案

1. AI_APICallError

1. AI_APICallError

Cause: API request failed (network, auth, rate limit).
Solution:
typescript
import { AI_APICallError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_APICallError) {
    console.error('API call failed:', error.message);
    console.error('Status code:', error.statusCode);
    console.error('Response:', error.responseBody);

    // Check common causes
    if (error.statusCode === 401) {
      // Invalid API key
    } else if (error.statusCode === 429) {
      // Rate limit - implement backoff
    } else if (error.statusCode >= 500) {
      // Provider issue - retry
    }
  }
}
Prevention:
  • Validate API keys at startup
  • Implement retry logic with exponential backoff
  • Monitor rate limits
  • Handle network errors gracefully

原因: API请求失败(网络、认证、速率限制)。
解决方案:
typescript
import { AI_APICallError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_APICallError) {
    console.error('API调用失败:', error.message);
    console.error('状态码:', error.statusCode);
    console.error('响应内容:', error.responseBody);

    // 检查常见原因
    if (error.statusCode === 401) {
      // API密钥无效
    } else if (error.statusCode === 429) {
      // 速率限制 - 实现退避重试
    } else if (error.statusCode >= 500) {
      // 提供商问题 - 重试
    }
  }
}
预防措施:
  • 在启动时验证API密钥
  • 实现带指数退避的重试逻辑
  • 监控速率限制
  • 优雅处理网络错误

2. AI_NoObjectGeneratedError

2. AI_NoObjectGeneratedError

Cause: Model didn't generate valid object matching schema.
Solution:
typescript
import { AI_NoObjectGeneratedError } from 'ai';

try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: z.object({ /* complex schema */ }),
    prompt: 'Generate data',
  });
} catch (error) {
  if (error instanceof AI_NoObjectGeneratedError) {
    console.error('No valid object generated');

    // Solutions:
    // 1. Simplify schema
    // 2. Add more context to prompt
    // 3. Provide examples in prompt
    // 4. Try different model (gpt-5 or claude-sonnet-4-5 for complex objects)
  }
}
Prevention:
  • Start with simple schemas, add complexity incrementally
  • Include examples in prompt: "Generate a person like: { name: 'Alice', age: 30 }"
  • Use GPT-4 for complex structured output
  • Test schemas with sample data first

原因: 模型未生成符合schema的有效对象。
解决方案:
typescript
import { AI_NoObjectGeneratedError } from 'ai';

try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: z.object({ /* 复杂schema */ }),
    prompt: 'Generate data',
  });
} catch (error) {
  if (error instanceof AI_NoObjectGeneratedError) {
    console.error('未生成有效对象');

    // 解决方案:
    // 1. 简化schema
    // 2. 在提示词中添加更多上下文
    // 3. 在提示词中提供示例
    // 4. 尝试不同模型(复杂对象推荐使用gpt-5或claude-sonnet-4-5)
  }
}
预防措施:
  • 从简单schema开始,逐步增加复杂度
  • 在提示词中包含示例:"Generate a person like: { name: 'Alice', age: 30 }"
  • 复杂结构化输出使用GPT-4
  • 先用样本数据测试schema

3. Worker Startup Limit (270ms+)

3. Worker启动超时(270ms+)

Cause: AI SDK v5 + Zod initialization overhead in Cloudflare Workers exceeds startup limits.
Solution:
typescript
// BAD: Top-level imports cause startup overhead
import { createWorkersAI } from 'workers-ai-provider';
import { complexSchema } from './schemas';

const workersai = createWorkersAI({ binding: env.AI });

// GOOD: Lazy initialization inside handler
export default {
  async fetch(request, env) {
    const { createWorkersAI } = await import('workers-ai-provider');
    const workersai = createWorkersAI({ binding: env.AI });

    // Use workersai here
  }
}
Prevention:
  • Move AI SDK imports inside route handlers
  • Minimize top-level Zod schemas
  • Monitor Worker startup time (must be <400ms)
  • Use Wrangler's startup time reporting
GitHub Issue: Search for "Workers startup limit" in Vercel AI SDK issues

原因: Cloudflare Workers中AI SDK v5 + Zod的初始化开销超过启动限制。
解决方案:
typescript
// 不良实践:顶层导入会增加启动开销
import { createWorkersAI } from 'workers-ai-provider';
import { complexSchema } from './schemas';

const workersai = createWorkersAI({ binding: env.AI });

// 良好实践:在处理器内部延迟初始化
export default {
  async fetch(request, env) {
    const { createWorkersAI } = await import('workers-ai-provider');
    const workersai = createWorkersAI({ binding: env.AI });

    // 在此处使用workersai
  }
}
预防措施:
  • 将AI SDK导入移到路由处理器内部
  • 尽量减少顶层Zod schema
  • 监控Worker启动时间(必须<400ms)
  • 使用Wrangler的启动时间报告

4. streamText Fails Silently

4. streamText 静默失败

Cause: Stream errors can be swallowed by
createDataStreamResponse
.
Status:RESOLVED - Fixed in ai@4.1.22 (February 2025)
Solution (Recommended):
typescript
// Use the onError callback (added in v4.1.22)
const stream = streamText({
  model: openai('gpt-4-turbo'),
  prompt: 'Hello',
  onError({ error }) {
    console.error('Stream error:', error);
    // Custom error logging and handling
  },
});

// Stream safely
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}
Alternative (Manual try-catch):
typescript
// Fallback if not using onError callback
try {
  const stream = streamText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });

  for await (const chunk of stream.textStream) {
    process.stdout.write(chunk);
  }
} catch (error) {
  console.error('Stream error:', error);
}
Prevention:
  • Use
    onError
    callback
    for proper error capture (recommended)
  • Implement server-side error monitoring
  • Test stream error handling explicitly
  • Always log on server side in production
GitHub Issue: #4726 (RESOLVED)

原因: 流错误可能被
createDataStreamResponse
吞噬。
状态:已解决 - 在ai@4.1.22版本修复(2025年2月)
解决方案(推荐):
typescript
// 使用onError回调(v4.1.22新增)
const stream = streamText({
  model: openai('gpt-4-turbo'),
  prompt: 'Hello',
  onError({ error }) {
    console.error('流错误:', error);
    // 自定义错误日志和处理
  },
});

// 安全处理流
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}
替代方案(手动try-catch):
typescript
// 如果不使用onError回调的回退方案
try {
  const stream = streamText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });

  for await (const chunk of stream.textStream) {
    process.stdout.write(chunk);
  }
} catch (error) {
  console.error('流错误:', error);
}
预防措施:
  • 使用
    onError
    回调
    正确捕获错误(推荐)
  • 实现服务器端错误监控
  • 显式测试流错误处理
  • 生产环境中始终在服务器端记录日志
GitHub Issue: #4726(已解决)

5. AI_LoadAPIKeyError

5. AI_LoadAPIKeyError

Cause: Missing or invalid API key.
Solution:
typescript
import { AI_LoadAPIKeyError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_LoadAPIKeyError) {
    console.error('API key error:', error.message);

    // Check:
    // 1. .env file exists and loaded
    // 2. Correct env variable name (OPENAI_API_KEY)
    // 3. Key format is valid (starts with sk-)
  }
}
Prevention:
  • Validate API keys at application startup
  • Use environment variable validation (e.g., zod)
  • Provide clear error messages in development
  • Document required environment variables

原因: API密钥缺失或无效。
解决方案:
typescript
import { AI_LoadAPIKeyError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_LoadAPIKeyError) {
    console.error('API密钥错误:', error.message);

    // 检查:
    // 1. .env文件存在且已加载
    // 2. 环境变量名称正确(OPENAI_API_KEY)
    // 3. 密钥格式有效(以sk-开头)
  }
}
预防措施:
  • 在应用启动时验证API密钥
  • 使用环境变量验证(如zod)
  • 在开发环境中提供清晰的错误提示
  • 记录所需的环境变量

6. AI_InvalidArgumentError

6. AI_InvalidArgumentError

Cause: Invalid parameters passed to function.
Solution:
typescript
import { AI_InvalidArgumentError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    maxOutputTokens: -1,  // Invalid!
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_InvalidArgumentError) {
    console.error('Invalid argument:', error.message);
    // Check parameter types and values
  }
}
Prevention:
  • Use TypeScript for type checking
  • Validate inputs before calling AI SDK functions
  • Read function signatures carefully
  • Check official docs for parameter constraints

原因: 传递给函数的参数无效。
解决方案:
typescript
import { AI_InvalidArgumentError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    maxOutputTokens: -1,  // 无效参数!
    prompt: 'Hello',
  });
} catch (error) {
  if (error instanceof AI_InvalidArgumentError) {
    console.error('无效参数:', error.message);
    // 检查参数类型和值
  }
}
预防措施:
  • 使用TypeScript进行类型检查
  • 在调用AI SDK函数前验证输入
  • 仔细阅读函数签名
  • 查看官方文档了解参数约束

7. AI_NoContentGeneratedError

7. AI_NoContentGeneratedError

Cause: Model generated no content (safety filters, etc.).
Solution:
typescript
import { AI_NoContentGeneratedError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Some prompt',
  });
} catch (error) {
  if (error instanceof AI_NoContentGeneratedError) {
    console.error('No content generated');

    // Possible causes:
    // 1. Safety filters blocked output
    // 2. Prompt triggered content policy
    // 3. Model configuration issue

    // Handle gracefully:
    return { text: 'Unable to generate response. Please try different input.' };
  }
}
Prevention:
  • Sanitize user inputs
  • Avoid prompts that may trigger safety filters
  • Have fallback messaging
  • Log occurrences for analysis

原因: 模型未生成任何内容(如安全过滤等)。
解决方案:
typescript
import { AI_NoContentGeneratedError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Some prompt',
  });
} catch (error) {
  if (error instanceof AI_NoContentGeneratedError) {
    console.error('未生成任何内容');

    // 可能原因:
    // 1. 安全过滤阻止了输出
    // 2. 提示词触发了内容政策
    // 3. 模型配置问题

    // 优雅处理:
    return { text: '无法生成响应,请尝试其他输入。' };
  }
}
预防措施:
  • 清理用户输入
  • 避免可能触发安全过滤的提示词
  • 提供回退消息
  • 记录此类事件以便分析

8. AI_TypeValidationError

8. AI_TypeValidationError

Cause: Zod schema validation failed on generated output.
Solution:
typescript
import { AI_TypeValidationError } from 'ai';

try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: z.object({
      age: z.number().min(0).max(120),  // Strict validation
    }),
    prompt: 'Generate person',
  });
} catch (error) {
  if (error instanceof AI_TypeValidationError) {
    console.error('Validation failed:', error.message);

    // Solutions:
    // 1. Relax schema constraints
    // 2. Add more guidance in prompt
    // 3. Use .optional() for unreliable fields
  }
}
Prevention:
  • Start with lenient schemas, tighten gradually
  • Use
    .optional()
    for fields that may not always be present
  • Add validation hints in field descriptions
  • Test with various prompts

原因: 生成的输出未通过Zod schema验证。
解决方案:
typescript
import { AI_TypeValidationError } from 'ai';

try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: z.object({
      age: z.number().min(0).max(120),  // 严格验证
    }),
    prompt: 'Generate person',
  });
} catch (error) {
  if (error instanceof AI_TypeValidationError) {
    console.error('验证失败:', error.message);

    // 解决方案:
    // 1. 放宽schema约束
    // 2. 在提示词中添加更多指导
    // 3. 对不可靠字段使用.optional()
  }
}
预防措施:
  • 从宽松的schema开始,逐步收紧
  • 对可能不总是存在的字段使用
    .optional()
  • 在字段描述中添加验证提示
  • 使用各种提示词进行测试

9. AI_RetryError

9. AI_RetryError

Cause: All retry attempts failed.
Solution:
typescript
import { AI_RetryError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
    maxRetries: 3,  // Default is 2
  });
} catch (error) {
  if (error instanceof AI_RetryError) {
    console.error('All retries failed');
    console.error('Last error:', error.lastError);

    // Check root cause:
    // - Persistent network issue
    // - Provider outage
    // - Invalid configuration
  }
}
Prevention:
  • Investigate root cause of failures
  • Adjust retry configuration if needed
  • Implement circuit breaker pattern for provider outages
  • Have fallback providers

原因: 所有重试尝试均失败。
解决方案:
typescript
import { AI_RetryError } from 'ai';

try {
  const result = await generateText({
    model: openai('gpt-4-turbo'),
    prompt: 'Hello',
    maxRetries: 3,  // 默认是2
  });
} catch (error) {
  if (error instanceof AI_RetryError) {
    console.error('所有重试均失败');
    console.error('最后一次错误:', error.lastError);

    // 检查根本原因:
    // - 持续网络问题
    // - 提供商服务中断
    // - 无效配置
  }
}
预防措施:
  • 调查失败的根本原因
  • 如有需要调整重试配置
  • 为提供商服务中断实现断路器模式
  • 提供备用提供商

10. Rate Limiting Errors

10. 速率限制错误

Cause: Exceeded provider rate limits (RPM/TPM).
Solution:
typescript
// Implement exponential backoff
async function generateWithBackoff(prompt: string, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await generateText({
        model: openai('gpt-4-turbo'),
        prompt,
      });
    } catch (error) {
      if (error instanceof AI_APICallError && error.statusCode === 429) {
        const delay = Math.pow(2, i) * 1000;  // Exponential backoff
        console.log(`Rate limited, waiting ${delay}ms`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Rate limit retries exhausted');
}
Prevention:
  • Monitor rate limit headers
  • Queue requests to stay under limits
  • Upgrade provider tier if needed
  • Implement request throttling

原因: 超过提供商的速率限制(RPM/TPM)。
解决方案:
typescript
// 实现指数退避
async function generateWithBackoff(prompt: string, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await generateText({
        model: openai('gpt-4-turbo'),
        prompt,
      });
    } catch (error) {
      if (error instanceof AI_APICallError && error.statusCode === 429) {
        const delay = Math.pow(2, i) * 1000;  // 指数退避
        console.log(`速率受限,等待${delay}ms`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('速率限制重试次数已耗尽');
}
预防措施:
  • 监控速率限制头信息
  • 对请求进行排队以保持在限制内
  • 如有需要升级提供商套餐
  • 实现请求限流

11. TypeScript Performance with Zod

11. Zod导致的TypeScript性能问题

Cause: Complex Zod schemas slow down TypeScript type checking.
Solution:
typescript
// Instead of deeply nested schemas at top level:
// const complexSchema = z.object({ /* 100+ fields */ });

// Define inside functions or use type assertions:
function generateData() {
  const schema = z.object({ /* complex schema */ });
  return generateObject({ model: openai('gpt-4-turbo'), schema, prompt: '...' });
}

// Or use z.lazy() for recursive schemas:
type Category = { name: string; subcategories?: Category[] };
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    subcategories: z.array(CategorySchema).optional(),
  })
);
Prevention:
  • Avoid top-level complex schemas
  • Use
    z.lazy()
    for recursive types
  • Split large schemas into smaller ones
  • Use type assertions where appropriate

原因: 复杂的Zod schema会减慢TypeScript类型检查速度。
解决方案:
typescript
// 不要在顶层定义深度嵌套的schema:
// const complexSchema = z.object({ /* 100+字段 */ });

// 在函数内部定义或使用类型断言:
function generateData() {
  const schema = z.object({ /* 复杂schema */ });
  return generateObject({ model: openai('gpt-4-turbo'), schema, prompt: '...' });
}

// 或者对递归schema使用z.lazy():
type Category = { name: string; subcategories?: Category[] };
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    subcategories: z.array(CategorySchema).optional(),
  })
);
预防措施:
  • 避免在顶层定义复杂schema
  • 对递归类型使用
    z.lazy()
  • 将大型schema拆分为较小的schema
  • 在适当的地方使用类型断言

12. Invalid JSON Response (Provider-Specific)

12. 无效JSON响应(提供商特定)

Cause: Some models occasionally return invalid JSON.
Solution:
typescript
// Use built-in retry and mode selection
const result = await generateObject({
  model: openai('gpt-4-turbo'),
  schema: mySchema,
  prompt: 'Generate data',
  mode: 'json',  // Force JSON mode (supported by GPT-4)
  maxRetries: 3,  // Retry on invalid JSON
});

// Or catch and retry manually:
try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: mySchema,
    prompt: 'Generate data',
  });
} catch (error) {
  // Retry with different model
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: mySchema,
    prompt: 'Generate data',
  });
}
Prevention:
  • Use
    mode: 'json'
    when available
  • Prefer GPT-4 for structured output
  • Implement retry logic
  • Validate responses
GitHub Issue: #4302 (Imagen 3.0 Invalid JSON)

原因: 某些模型偶尔会返回无效JSON。
解决方案:
typescript
// 使用内置重试和模式选择
const result = await generateObject({
  model: openai('gpt-4-turbo'),
  schema: mySchema,
  prompt: 'Generate data',
  mode: 'json',  // 强制JSON模式(GPT-4支持)
  maxRetries: 3,  // 无效JSON时重试
});

// 或者手动捕获并重试:
try {
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: mySchema,
    prompt: 'Generate data',
  });
} catch (error) {
  // 使用不同模型重试
  const result = await generateObject({
    model: openai('gpt-4-turbo'),
    schema: mySchema,
    prompt: 'Generate data',
  });
}
预防措施:
  • 可用时使用
    mode: 'json'
  • 结构化输出优先使用GPT-4
  • 实现重试逻辑
  • 验证响应
GitHub Issue: #4302(Imagen 3.0返回无效JSON)

13. Gemini Implicit Caching Fails with Tools

13. Gemini 隐式缓存在使用工具时失效

Error: No error, but higher API costs due to disabled caching Cause: Google Gemini 3 Flash's cost-saving implicit caching doesn't work when any tools are defined, even if never used. Source: GitHub Issue #11513
Why It Happens: Gemini API disables caching when tools are present in the request, regardless of whether they're invoked.
Prevention:
typescript
// Conditionally add tools only when needed
const needsTools = await analyzePrompt(userInput);

const result = await generateText({
  model: google('gemini-3-flash'),
  tools: needsTools ? { weather: weatherTool } : undefined,
  prompt: userInput,
});
Impact: High - Can significantly increase API costs for repeated context

错误: 无错误提示,但因缓存禁用导致API成本增加 原因: Google Gemini 3 Flash的成本优化隐式缓存功能在定义任何工具时失效,即使工具从未被使用。 来源: GitHub Issue #11513
为什么会发生: Gemini API在请求中存在工具时会禁用缓存,无论工具是否被调用。
预防措施:
typescript
// 仅在需要时有条件地添加工具
const needsTools = await analyzePrompt(userInput);

const result = await generateText({
  model: google('gemini-3-flash'),
  tools: needsTools ? { weather: weatherTool } : undefined,
  prompt: userInput,
});
影响: 高 - 会显著增加重复上下文场景下的API成本

14. Anthropic Tool Error Results Cause JSON Parse Crash

14. Anthropic工具错误结果导致JSON解析崩溃

Error:
SyntaxError: "[object Object]" is not valid JSON
Cause: Anthropic provider built-in tools (web_fetch, etc.) return error objects that SDK tries to JSON.parse Source: GitHub Issue #11856
Why It Happens: When Anthropic built-in tools fail (e.g., url_not_allowed), they return error objects. AI SDK incorrectly tries to parse these as JSON strings.
Prevention:
typescript
try {
  const result = await generateText({
    model: anthropic('claude-sonnet-4-5-20250929'),
    tools: { web_fetch: { type: 'anthropic_defined', name: 'web_fetch' } },
    prompt: userPrompt,
  });
} catch (error) {
  if (error.message.includes('is not valid JSON')) {
    // Tool returned error result, handle gracefully
    console.error('Tool execution failed - likely blocked URL or permission issue');
    // Retry without tool or use custom tool
  }
  throw error;
}
Impact: High - Production crashes when using Anthropic built-in tools

错误:
SyntaxError: "[object Object]" is not valid JSON
原因: Anthropic提供商的内置工具(如web_fetch)返回错误对象,SDK尝试将其作为JSON字符串解析。 来源: GitHub Issue #11856
为什么会发生: 当Anthropic内置工具失败时(如url_not_allowed),它们会返回错误对象。AI SDK错误地尝试将这些对象解析为JSON字符串。
预防措施:
typescript
try {
  const result = await generateText({
    model: anthropic('claude-sonnet-4-5-20250929'),
    tools: { web_fetch: { type: 'anthropic_defined', name: 'web_fetch' } },
    prompt: userPrompt,
  });
} catch (error) {
  if (error.message.includes('is not valid JSON')) {
    // 工具执行失败 - 可能是URL被阻止或权限问题
    console.error('工具执行失败 - 可能是URL被阻止或权限问题');
    // 不使用工具重试或使用自定义工具
  }
  throw error;
}
影响: 高 - 使用Anthropic内置工具时会导致生产环境崩溃

15. Tool-Result in Assistant Message (Anthropic)

15. Assistant消息中的Tool-Result(Anthropic)

Error: Anthropic API error -
tool-result
in assistant message not allowed Cause: Server-executed tools incorrectly place
tool-result
parts in assistant messages Source: GitHub Issue #11855
Why It Happens: When using server-executed tools (tools where
execute
runs on server, not sent to model), the AI SDK incorrectly includes
tool-result
parts in the assistant message. Anthropic expects tool-result only in user messages.
Prevention:
typescript
// Workaround: Filter messages before sending
const filteredMessages = messages.map(msg => {
  if (msg.role === 'assistant') {
    return {
      ...msg,
      content: msg.content.filter(part => part.type !== 'tool-result'),
    };
  }
  return msg;
});

const result = await generateText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: { database: databaseTool },
  messages: filteredMessages,
  prompt: 'Get user data',
});
Impact: High - Breaks server-executed tool pattern with Anthropic provider
Status: Known issue, PR #11854 submitted


错误: Anthropic API错误 -
tool-result
不允许出现在assistant消息中 原因: 服务器执行的工具错误地将
tool-result
片段放在assistant消息中 来源: GitHub Issue #11855
为什么会发生: 当使用服务器执行的工具(
execute
在服务器运行,而非发送给模型的工具)时,AI SDK错误地在assistant消息中包含
tool-result
片段。Anthropic要求tool-result只能出现在user消息中。
预防措施:
typescript
// 解决方法: 在发送前过滤消息
const filteredMessages = messages.map(msg => {
  if (msg.role === 'assistant') {
    return {
      ...msg,
      content: msg.content.filter(part => part.type !== 'tool-result'),
    };
  }
  return msg;
});

const result = await generateText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: { database: databaseTool },
  messages: filteredMessages,
  prompt: 'Get user data',
});
影响: 高 - 破坏Anthropic提供商的服务器执行工具模式
状态: 已知问题,PR #11854已提交


Known Issues & Limitations

已知问题与限制

useChat Stale Closures with Memoized Options

useChat 与 memoized选项的闭包过时问题

Issue: When using
useChat
with memoized options (common for performance), the
onData
and
onFinish
callbacks have stale closures and don't see updated state variables.
Reproduction:
typescript
const [count, setCount] = useState(0);

const chatOptions = useMemo(() => ({
  onFinish: (message) => {
    console.log('Count:', count); // ALWAYS 0, never updates!
  },
}), []); // Empty deps = stale closure

const { messages, append } = useChat(chatOptions);
Workaround 1 - Don't Memoize Callbacks:
typescript
const { messages, append } = useChat({
  onFinish: (message) => {
    console.log('Count:', count); // Now sees current count
  },
});
Workaround 2 - Use useRef:
typescript
const countRef = useRef(count);
useEffect(() => { countRef.current = count; }, [count]);

const chatOptions = useMemo(() => ({
  onFinish: (message) => {
    console.log('Count:', countRef.current); // Always current
  },
}), []);

问题: 当使用
useChat
搭配memoized选项(常见于性能优化)时,
onData
onFinish
回调会有过时闭包,无法看到更新后的状态变量。
复现:
typescript
const [count, setCount] = useState(0);

const chatOptions = useMemo(() => ({
  onFinish: (message) => {
    console.log('Count:', count); // 始终为0,从未更新!
  },
}), []); // 空依赖 = 过时闭包

const { messages, append } = useChat(chatOptions);
解决方法1 - 不要Memoize回调:
typescript
const { messages, append } = useChat({
  onFinish: (message) => {
    console.log('Count:', count); // 现在可以看到当前count
  },
});
解决方法2 - 使用useRef:
typescript
const countRef = useRef(count);
useEffect(() => { countRef.current = count; }, [count]);

const chatOptions = useMemo(() => ({
  onFinish: (message) => {
    console.log('Count:', countRef.current); // 始终为当前值
  },
}), []);

Stream Resumption Fails on Tab Switch

切换标签页时流恢复失败

Issue: When users switch browser tabs or background the app during an AI stream, the stream does not resume when they return. The connection is lost and does not automatically reconnect.
Impact: High - Major UX issue for long-running streams
Workaround 1 - Implement onError Handler:
typescript
const { messages, append, reload } = useChat({
  api: '/api/chat',
  onError: (error) => {
    if (error.message.includes('stream') || error.message.includes('aborted')) {
      // Attempt to reload last message
      reload();
    }
  },
});
Workaround 2 - Detect Visibility Change:
typescript
useEffect(() => {
  const handleVisibilityChange = () => {
    if (document.visibilityState === 'visible') {
      // Check if stream was interrupted
      const lastMessage = messages[messages.length - 1];
      if (lastMessage?.role === 'assistant' && !lastMessage.content) {
        reload();
      }
    }
  };

  document.addEventListener('visibilitychange', handleVisibilityChange);
  return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
}, [messages, reload]);
Status: Known limitation, no auto-reconnection built-in

问题: 当用户在AI流输出期间切换浏览器标签页或让应用进入后台,返回时流无法恢复。连接会丢失且不会自动重连。
影响: 高 - 对长时间运行的流来说是重大UX问题
解决方法1 - 实现onError处理器:
typescript
const { messages, append, reload } = useChat({
  api: '/api/chat',
  onError: (error) => {
    if (error.message.includes('stream') || error.message.includes('aborted')) {
      // 尝试重新加载最后一条消息
      reload();
    }
  },
});
解决方法2 - 检测可见性变化:
typescript
useEffect(() => {
  const handleVisibilityChange = () => {
    if (document.visibilityState === 'visible') {
      // 检查流是否被中断
      const lastMessage = messages[messages.length - 1];
      if (lastMessage?.role === 'assistant' && !lastMessage.content) {
        reload();
      }
    }
  };

  document.addEventListener('visibilitychange', handleVisibilityChange);
  return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
}, [messages, reload]);
状态: 已知限制,无内置自动重连功能

When to Use This Skill

何时使用本技能

Use ai-sdk-core when:

当你需要以下场景时使用ai-sdk-core:

  • Building backend AI features (server-side text generation)
  • Implementing server-side text generation (Node.js, Workers, Next.js)
  • Creating structured AI outputs (JSON, forms, data extraction)
  • Building AI agents with tools (multi-step workflows)
  • Integrating multiple AI providers (OpenAI, Anthropic, Google, Cloudflare)
  • Migrating from AI SDK v4 to v5
  • Encountering AI SDK errors (AI_APICallError, AI_NoObjectGeneratedError, etc.)
  • Using AI in Cloudflare Workers (with workers-ai-provider)
  • Using AI in Next.js Server Components/Actions
  • Need consistent API across different LLM providers
  • 构建后端AI功能(服务器端文本生成)
  • 实现服务器端文本生成(Node.js, Workers, Next.js)
  • 创建结构化AI输出(JSON、表单、数据提取)
  • 构建带工具的AI Agent(多步工作流)
  • 集成多个AI提供商(OpenAI, Anthropic, Google, Cloudflare)
  • 从AI SDK v4迁移到v5
  • 遇到AI SDK错误(AI_APICallError, AI_NoObjectGeneratedError等)
  • 在Cloudflare Workers中使用AI(搭配workers-ai-provider)
  • 在Next.js Server Components/Actions中使用AI
  • 需要在不同LLM提供商间使用一致的API

Don't use this skill when:

不要在以下场景使用本技能:

  • Building React chat UIs (use ai-sdk-ui skill instead)
  • Need frontend hooks like useChat (use ai-sdk-ui skill instead)
  • Need advanced topics like embeddings or image generation (check official docs)
  • Building native Cloudflare Workers AI apps without multi-provider (use cloudflare-workers-ai skill instead)
  • Need Generative UI / RSC (see https://ai-sdk.dev/docs/ai-sdk-rsc)

  • 构建React聊天UI(请使用ai-sdk-ui技能)
  • 需要前端hooks如useChat(请使用ai-sdk-ui技能)
  • 需要向量嵌入或图像生成等高级主题(请查看官方文档)
  • 构建原生Cloudflare Workers AI应用且不需要多提供商支持(请使用cloudflare-workers-ai技能)
  • 需要生成式UI / RSC(查看https://ai-sdk.dev/docs/ai-sdk-rsc)

Versions

版本信息

AI SDK:
  • Stable: ai@6.0.26 (Jan 2026)
  • ⚠️ Skip v6.0.40 - Breaking streaming change (reverted in v6.0.41)
  • Legacy v5: ai@5.0.117 (ai-v5 tag)
  • Zod 3.x/4.x both supported
Latest Models (2026):
  • OpenAI: GPT-5.2, GPT-5.1, GPT-5, o3, o3-mini, o4-mini
  • Anthropic: Claude Sonnet 4.5, Opus 4.1, Haiku 4.5
  • Google: Gemini 2.5 Pro/Flash/Lite
Check Latest:
bash
npm view ai version
npm view ai dist-tags

AI SDK:
  • 稳定版: ai@6.0.26(2026年1月)
  • ⚠️ 跳过v6.0.40 - 流式输出重大变更(已在v6.0.41中回滚)
  • 旧版v5: ai@5.0.117(ai-v5标签)
  • 同时支持Zod 3.x/4.x
2026年最新模型:
  • OpenAI: GPT-5.2, GPT-5.1, GPT-5, o3, o3-mini, o4-mini
  • Anthropic: Claude Sonnet 4.5, Opus 4.1, Haiku 4.5
  • Google: Gemini 2.5 Pro/Flash/Lite
检查最新版本:
bash
npm view ai version
npm view ai dist-tags

Official Docs

官方文档

Core:
Multi-Modal:
GitHub:

Last Updated: 2026-01-20 Skill Version: 2.1.0 Changes: Added 3 new errors (Gemini caching, Anthropic tool errors, tool-result placement), MCP security guidance, tool approval best practices, React hooks edge cases, stream resumption workarounds AI SDK: 6.0.26 stable (avoid v6.0.40)
核心文档:
多模态文档:
GitHub:

最后更新: 2026-01-20 技能版本: 2.1.0 变更内容: 新增3个错误(Gemini缓存、Anthropic工具错误、tool-result放置)、MCP安全指导、工具审批最佳实践、React hooks边缘情况、流恢复解决方法 AI SDK版本: 6.0.26稳定版(避免使用v6.0.40)