Vercel AI SDK + eve 深度实战:当 TypeScript 成为 AI Agent 开发的一等公民——从统一模型层到文件系统优先框架、从多步工具调用到生产级 Agent 部署的完全指南(2026)
引言:为什么 Vercel AI SDK 是 2026 年最值得关注的 AI 开发工具栈
2026 年,AI Agent 开发已经从实验阶段进入了工程化阶段。但一个尴尬的现实是:大多数开发者仍然在手动处理模型差异、自行拼接流式输出、手工编写工具调用逻辑。OpenAI 的 API 和 Anthropic 的 API 不仅参数格式不同,连流式响应的结构都不一样。每换一个模型提供商,你的代码就要改一遍。
Vercel AI SDK 正是为了解决这个问题而生的。它提供了一个统一的 TypeScript API 层,让你用同一套代码调用不同的大模型——从 OpenAI、Anthropic、Google 到各种开源模型。更重要的是,它在 2026 年的 Vercel Ship 大会上,配合开源的 eve 框架一起,形成了从底层 SDK 到上层 Agent 框架的完整工具链。
本文将从以下角度进行深度分析:
- AI SDK Core 的核心架构:generateText / streamText / tool calling 的统一抽象
- Tool Calling 深度实战:从简单工具到多步 Agent 循环
- Structured Output:类型安全的结构化数据生成
- AI SDK UI:与 React/Next.js 的无缝集成
- eve 框架:文件系统优先的 Durable Agent 开发框架
- Mastra 生态:从 Gatsby 团队带来的全栈 AI Agent 框架
- 生产级实践:从可观测性到成本控制、从安全审批到部署策略
一、AI SDK Core:统一模型层的架构设计
1.1 核心设计理念
Vercel AI SDK 的核心设计哲学可以总结为三个词:统一、类型安全、可组合。
统一意味着你只需要学习一套 API。不管底层是 OpenAI 还是 Anthropic,代码结构不变:
import { generateText } from "ai";
// 使用 Anthropic
const result1 = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt: "解释什么是闭包",
});
// 使用 OpenAI——只需要改 model 字符串
const result2 = await generateText({
model: "openai/gpt-4o",
prompt: "解释什么是闭包",
});
类型安全意味着所有输入输出都有 TypeScript 类型推断。你的工具参数、结构化输出、消息历史——全部是强类型的。
可组合意味着 SDK 的各个功能模块可以像乐高积木一样组合。generateText 可以和 tool calling 组合,streamText 可以和 structured output 组合,形成强大的复合能力。
1.2 两大核心函数:generateText 与 streamText
AI SDK Core 围绕两个核心函数构建:
| 函数 | 用途 | 场景 |
|---|---|---|
generateText | 非流式文本生成 + 工具调用 | 自动化任务、Agent 编排、数据处理 |
streamText | 流式文本生成 + 工具调用 | 聊天机器人、实时应用、Generative UI |
两个函数共享同一套配置接口,包括:
model:模型标识符(格式为provider/model-id)system:系统提示词prompt/messages:用户输入tools:工具定义output:结构化输出定义stopWhen:多步调用的停止条件
generateText 返回的是一个 Promise,包含完整结果:
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt: "用一句话解释函数式编程",
});
console.log(result.text); // 生成的文本
console.log(result.usage); // Token 使用量
console.log(result.finishReason); // 停止原因
console.log(result.response.messages); // 可追加到消息历史
streamText 返回的是一个流式结果对象:
const result = streamText({
model: "anthropic/claude-sonnet-4.5",
prompt: "写一首关于 TypeScript 的诗",
onError({ error }) {
console.error("流式错误:", error);
},
});
// 作为 AsyncIterable 消费
for await (const textPart of result.textStream) {
process.stdout.write(textPart);
}
1.3 模型提供商体系
AI SDK 采用提供商插件架构,每个提供商是一个独立的 npm 包:
# 核心包
npm install ai
# 提供商包(按需安装)
npm install @ai-sdk/openai
npm install @ai-sdk/anthropic
npm install @ai-sdk/google
npm install @ai-sdk/mistral
npm install @ai-sdk/amazon-bedrock
npm install @ai-sdk/azure
模型标识符格式为 provider/model-id,例如:
anthropic/claude-sonnet-4.5openai/gpt-4ogoogle/gemini-2.5-promistral/mistral-large-latest
这种设计使得切换模型只需要改一个字符串,其他代码完全不变。
1.4 提供商配置
每个提供商都可以独立配置:
import { createOpenAI } from "@ai-sdk/openai";
import { createAnthropic } from "@ai-sdk/anthropic";
// 自定义 OpenAI 配置(支持兼容 API)
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: "https://my-custom-endpoint.com/v1", // 支持自定义端点
});
// 自定义 Anthropic 配置
const anthropic = createAnthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// 使用自定义提供商实例
const result = await generateText({
model: anthropic("claude-sonnet-4.5"),
prompt: "Hello",
});
这个设计非常实用——你可以用它来对接 DeepSeek、通义千问、智谱 GLM 等兼容 OpenAI API 格式的国产模型。
二、Tool Calling:从简单工具到 Agent 循环
2.1 工具定义的基本模式
Tool Calling 是 AI Agent 的核心能力。AI SDK 的工具定义非常优雅——使用 Zod schema 来定义参数,TypeScript 自动推断类型:
import { generateText, tool } from "ai";
import { z } from "zod";
const weatherTool = tool({
description: "获取指定城市的天气信息",
inputSchema: z.object({
city: z.string().describe("城市名称"),
unit: z.enum(["celsius", "fahrenheit"]).optional().describe("温度单位"),
}),
execute: async ({ city, unit = "celsius" }) => {
// 实际调用天气 API
const response = await fetch(
`https://api.weather.com/v1?city=${city}&unit=${unit}`
);
return response.json();
},
});
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
tools: { getWeather: weatherTool },
prompt: "北京今天天气怎么样?",
});
2.2 多步调用(Multi-Step Agent Loop)
真正的 Agent 能力来自于多步调用——模型可以连续调用多个工具,每一步的结果反馈给模型,让它决定下一步做什么。
AI SDK 通过 stopWhen 参数控制这个循环:
import { generateText, tool, stepCountIs } from "ai";
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
tools: {
searchDatabase: tool({
description: "搜索数据库中的用户信息",
inputSchema: z.object({
query: z.string(),
}),
execute: async ({ query }) => {
// 数据库搜索逻辑
return await db.users.search(query);
},
}),
sendEmail: tool({
description: "发送邮件给指定用户",
inputSchema: z.object({
userId: z.string(),
subject: z.string(),
body: z.string(),
}),
execute: async ({ userId, subject, body }) => {
return await emailService.send({ userId, subject, body });
},
}),
},
stopWhen: stepCountIs(10), // 最多 10 步
prompt: "找到所有上个月没有登录的用户,给他们发送激活邮件",
});
内置的停止条件有:
stepCountIs(count)— 步数限制hasToolCall(toolName)— 调用了特定工具后停止isLoopFinished()— 永不主动停止,让模型自然结束- 自定义条件函数
- 条件数组(任意一个满足即停止)
2.3 步骤跟踪与调试
多步调用中,你可以通过 steps 属性获取每一步的详细信息:
const { steps } = await generateText({
model: "anthropic/claude-sonnet-4.5",
stopWhen: stepCountIs(10),
tools: { /* ... */ },
prompt: "帮我分析一下这份代码的性能问题",
});
// 遍历每一步
for (const step of steps) {
console.log(`步骤 ${step.stepNumber}:`);
console.log(` 文本: ${step.text || "(无文本)"}`);
console.log(` 工具调用:`, step.toolCalls);
console.log(` 工具结果:`, step.toolResults);
console.log(` Token 用量:`, step.usage);
}
2.4 生命周期回调:可观测性的基石
AI SDK 提供了完整生命周期回调链,这是生产级可观测性的基础:
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
tools: { /* ... */ },
prompt: "分析这个 bug",
// 整体开始
experimental_onStart({ model, settings, functionId }) {
logger.info("生成开始", { model: model.modelId, functionId });
},
// 每一步开始
experimental_onStepStart({ stepNumber, model, promptMessages }) {
logger.info(`步骤 ${stepNumber} 开始`, { promptLength: promptMessages.length });
},
// 工具调用开始
experimental_onToolCallStart({ toolName, toolCallId, input }) {
logger.info(`调用工具: ${toolName}`, { toolCallId, input });
startTimer(toolCallId);
},
// 工具调用结束
experimental_onToolCallFinish({ toolName, toolCallId, output, error, durationMs }) {
const elapsed = durationMs;
if (error) {
logger.error(`工具 ${toolName} 失败`, { toolCallId, error, elapsed });
} else {
logger.info(`工具 ${toolName} 完成`, { toolCallId, elapsed });
}
metrics.record("tool.duration", durationMs, { toolName });
},
// 每一步结束
onStepFinish({ stepNumber, finishReason, usage }) {
logger.info(`步骤 ${stepNumber} 完成`, { finishReason, usage });
metrics.record("tokens.used", usage?.totalTokens ?? 0);
},
});
2.5 工具执行审批机制
这是 AI SDK 一个非常实用的安全特性。对于敏感操作(如删除数据、执行命令、支付),你可以要求人工审批:
const deleteFileTool = tool({
description: "删除指定文件",
inputSchema: z.object({
filePath: z.string(),
}),
needsApproval: true, // 强制需要人工审批
execute: async ({ filePath }) => {
return await fs.unlink(filePath);
},
});
// 也可以根据参数动态决定是否需要审批
const paymentTool = tool({
description: "处理支付",
inputSchema: z.object({
amount: z.number(),
recipient: z.string(),
}),
needsApproval: async ({ amount }) => amount > 1000, // 超过 1000 元需要审批
execute: async ({ amount, recipient }) => {
return await processPayment(amount, recipient);
},
});
审批流程是一个两阶段设计:第一次 generateText 返回 approval request,你的应用收集用户决策后,把 approval response 加入消息历史再次调用。
2.6 流式工具结果
AI SDK 支持工具返回 AsyncIterable,实现流式状态更新:
const researchTool = tool({
description: "深度研究某个主题",
inputSchema: z.object({
topic: z.string(),
}),
async *execute({ topic }) {
// 先返回"正在搜索"状态
yield {
status: "searching" as const,
message: `正在搜索关于"${topic}"的信息...`,
data: null,
};
const results = await searchEngine.search(topic);
// 返回中间结果
yield {
status: "analyzing" as const,
message: `找到 ${results.length} 条结果,正在分析...`,
data: { resultCount: results.length },
};
// 最终结果
yield {
status: "done" as const,
message: "分析完成",
data: { summary: "..." },
};
},
});
2.7 动态工具与 MCP 集成
对于运行时才知道工具 schema 的场景(比如 MCP 协议的动态工具),AI SDK 提供了 dynamicTool:
import { dynamicTool } from "ai";
const mcpTool = dynamicTool({
description: "通过 MCP 协议调用的动态工具",
inputSchema: z.object({}), // 运行时才知道具体 schema
execute: async (input) => {
// input 类型为 unknown,需要运行时校验
return await mcpClient.callTool(input);
},
});
// 类型安全处理
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
tools: { weather: weatherTool, mcp: mcpTool },
onStepFinish({ toolCalls }) {
for (const call of toolCalls) {
if (call.dynamic) {
console.log("动态工具:", call.toolName, call.input);
} else {
// 静态工具:完整的类型推断
switch (call.toolName) {
case "weather":
console.log(call.input.city); // TypeScript 知道这是 string
break;
}
}
}
},
});
2.8 prepareStep:每一步的精细控制
prepareStep 回调允许你在每一步开始前修改配置——这是实现复杂 Agent 编排的关键:
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
tools: { search: searchTool, analyze: analyzeTool, summarize: summarizeTool },
stopWhen: stepCountIs(10),
prompt: "研究并总结最新的 AI 框架趋势",
prepareStep: async ({ stepNumber, steps, messages }) => {
// 第一步:强制使用搜索工具
if (stepNumber === 0) {
return {
toolChoice: { type: "tool", toolName: "search" },
activeTools: ["search"],
};
}
// 第二步:强制分析
if (stepNumber === 1) {
return {
toolChoice: { type: "tool", toolName: "analyze" },
activeTools: ["analyze"],
};
}
// 后续步骤:使用更便宜的模型做总结
if (stepNumber >= 2) {
return {
model: "anthropic/claude-haiku-4",
activeTools: ["summarize"],
};
}
// 长循环中的消息压缩
if (messages.length > 20) {
return {
messages: messages.slice(-10), // 只保留最近 10 条
};
}
return {}; // 使用默认配置
},
});
三、Structured Output:类型安全的结构化数据生成
3.1 基本用法
Structured Output 让大模型生成符合你定义的 TypeScript 类型的数据。这对于信息提取、分类、数据生成等场景极为实用:
import { generateText } from "ai";
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt: "分析这篇技术文章的核心观点",
output: {
type: "object",
schema: z.object({
title: z.string().describe("文章标题"),
summary: z.string().describe("一句话摘要"),
keyPoints: z.array(z.string()).describe("核心观点列表"),
difficulty: z.enum(["beginner", "intermediate", "advanced"])
.describe("技术难度"),
tags: z.array(z.string()).describe("标签"),
}),
},
});
// result.object 是类型安全的
console.log(result.object.title);
console.log(result.object.keyPoints); // string[]
console.log(result.object.difficulty); // "beginner" | "intermediate" | "advanced"
3.2 数组输出
const result = await generateText({
model: "openai/gpt-4o",
prompt: "列出 10 个提高 Go 性能的技巧",
output: {
type: "array",
schema: z.object({
name: z.string(),
description: z.string(),
codeExample: z.string().optional(),
impact: z.enum(["low", "medium", "high"]),
}),
},
});
// result.object 是类型安全数组
for (const tip of result.object) {
console.log(`${tip.name}: ${tip.impact}`);
}
3.3 Generative UI:流式生成 React 组件
Structured Output 结合 streamText 可以实现"AI 生成 UI"的效果——模型输出的结构化数据直接映射为 React 组件:
// API Route
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: "anthropic/claude-sonnet-4.5",
messages,
tools: {
showWeatherCard: tool({
description: "显示天气卡片",
inputSchema: z.object({
city: z.string(),
temperature: z.number(),
condition: z.string(),
}),
}),
showStockChart: tool({
description: "显示股票图表",
inputSchema: z.object({
symbol: z.string(),
price: z.number(),
change: z.number(),
}),
}),
},
});
return result.toUIMessageStreamResponse();
}
// 前端
import { useChat } from "@ai-sdk/react";
function Chat() {
const { messages } = useChat({
api: "/api/chat",
});
return (
<div>
{messages.map((msg) => (
<div key={msg.id}>
{msg.content.map((part, i) => {
if (part.type === "tool-invocation") {
const { state, toolName } = part.toolInvocation;
if (toolName === "showWeatherCard" && state === "result") {
const { city, temperature, condition } = part.toolInvocation.result;
return <WeatherCard city={city} temp={temperature} condition={condition} />;
}
if (toolName === "showStockChart" && state === "result") {
const { symbol, price, change } = part.toolInvocation.result;
return <StockChart symbol={symbol} price={price} change={change} />;
}
}
return <span key={i}>{part.text}</span>;
})}
</div>
))}
</div>
);
}
四、AI SDK UI:前端集成的三种模式
4.1 useChat:聊天应用的核心 Hook
useChat 是 AI SDK UI 最常用的 Hook,专为聊天场景设计:
"use client";
import { useChat } from "@ai-sdk/react";
export default function ChatPage() {
const {
messages, // 消息历史
input, // 当前输入
setInput, // 设置输入
handleSubmit, // 提交处理
isLoading, // 是否加载中
error, // 错误信息
reload, // 重新生成
stop, // 停止生成
append, // 追加消息
data, // 额外数据
} = useChat({
api: "/api/chat",
initialMessages: [], // 可选的初始消息
body: {
// 每次请求附带的额外参数
userId: "user-123",
},
onFinish({ message }) {
// 生成完成回调
analytics.track("chat_message", {
role: message.role,
contentLength: message.content.length,
});
},
onError(error) {
console.error("Chat error:", error);
},
});
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4">
{messages.map((message) => (
<div key={message.id} className="mb-4">
<div className="font-bold">{message.role === "user" ? "你" : "AI"}</div>
<div>{message.content}</div>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="p-4 border-t">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="输入消息..."
className="w-full p-2 border rounded"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? "思考中..." : "发送"}
</button>
</form>
</div>
);
}
4.2 工具执行审批的前端处理
结合前面提到的 needsApproval,前端可以这样处理审批流程:
const { messages, setMessages } = useChat({ api: "/api/chat" });
// 监听消息更新,处理审批请求
useEffect(() => {
const lastMessage = messages[messages.length - 1];
if (!lastMessage) return;
for (const part of lastMessage.parts) {
if (part.type === "tool-invocation" && part.toolInvocation.state === "call") {
const { toolName, args } = part.toolInvocation;
// 弹出确认对话框
const confirmed = window.confirm(
`AI 请求调用工具 "${toolName}",参数:${JSON.stringify(args)},是否允许?`
);
// 发送审批响应
addToolApprovalResponse({
approvalId: part.toolInvocation.toolCallId,
approved: confirmed,
reason: confirmed ? "用户确认" : "用户拒绝",
});
}
}
}, [messages]);
4.3 useCompletion:文本补全
import { useCompletion } from "@ai-sdk/react";
function CodeAssistant() {
const {
completion,
input,
setInput,
handleSubmit,
isLoading,
} = useCompletion({
api: "/api/complete",
prompt: "你是一个 TypeScript 代码补全助手",
});
return (
<div>
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="输入你的代码..."
/>
<button onClick={handleSubmit}>补全</button>
{isLoading && <span>生成中...</span>}
{completion && (
<pre><code>{completion}</code></pre>
)}
</div>
);
}
五、eve 框架:文件系统优先的 Durable Agent
5.1 设计哲学:约定优于配置
2026 年 Vercel Ship 大会最重磅的开源发布之一就是 eve——一个"文件系统优先"的 Agent 开发框架。它的核心理念是:Agent 的所有能力都应该通过文件系统的约定来组织,而不是通过复杂的编程 API。
这和 Rails 的"约定优于配置"思想一脉相承。一个 eve Agent 的项目结构:
my-agent/
└── agent/
├── agent.ts # 可选:模型和运行时配置
├── instructions.md # 必需:始终在线的系统提示词
├── tools/ # 可选:类型安全的工具函数
│ └── get_weather.ts
├── skills/ # 可选:按需加载的技能(Markdown)
│ └── plan_a_trip.md
├── channels/ # 可选:消息通道(HTTP、Slack、Discord)
│ └── slack.ts
└── schedules/ # 可选:定时任务
└── weekly_recap.ts
5.2 快速上手
npx eve@latest init my-agent
cd my-agent
npm run dev
instructions.md 是 Agent 的"灵魂"——它就是 Agent 的 system prompt,始终在线:
你是一个专业的技术博客助手。你的职责是:
1. 帮助开发者撰写高质量的技术文章
2. 提供代码审查和架构建议
3. 解释复杂的技术概念
回答要求:
- 使用中文
- 代码示例用 TypeScript
- 风格简洁直接,不要套话
工具定义也非常直观:
// agent/tools/search_articles.ts
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "搜索技术文章数据库",
inputSchema: z.object({
query: z.string().min(1).describe("搜索关键词"),
limit: z.number().min(1).max(50).optional().describe("返回数量"),
}),
async execute({ query, limit = 10 }) {
const results = await articleDB.search(query, limit);
return {
articles: results.map((r) => ({
id: r.id,
title: r.title,
summary: r.summary,
url: r.url,
})),
};
},
});
Agent 配置:
// agent/agent.ts
import { defineAgent } from "eve";
export default defineAgent({
model: "anthropic/claude-sonnet-4.5",
// 可以覆盖运行时配置
// maxSteps: 20,
// temperature: 0.7,
});
5.3 Skills:按需加载的技能
这是 eve 最独特的设计之一。Skills 是 Markdown 文件,定义了 Agent 可以"按需加载"的能力——类似于 Claude Code 的 SKILL.md 概念:
<!-- agent/skills/code_review.md -->
# 代码审查技能
当用户要求代码审查时,使用以下流程:
1. 阅读目标代码文件
2. 检查以下维度:
- 代码风格一致性
- 潜在的 bug 和安全问题
- 性能优化建议
- 可维护性
3. 输出审查报告,包含:
- 严重程度分级(Critical/Warning/Info)
- 具体的修改建议和代码示例
- 优先级排序
5.4 多通道支持
Agent 可以同时接入多个消息通道:
// agent/channels/slack.ts
import { defineChannel } from "eve/channels";
export default defineChannel({
type: "slack",
name: "团队通知频道",
botToken: process.env.SLACK_BOT_TOKEN,
channelId: process.env.SLACK_CHANNEL_ID,
});
// agent/channels/http.ts
import { defineChannel } from "eve/channels";
export default defineChannel({
type: "http",
port: 3000,
});
5.5 定时任务
// agent/schedules/weekly_recap.ts
import { defineSchedule } from "eve/schedules";
export default defineSchedule({
name: "weekly-recap",
cron: "0 9 * * 1", // 每周一上午 9 点
description: "生成上周技术总结报告",
});
5.6 eve 的核心优势
- 零学习成本的约定式开发:不需要学习复杂的框架 API,只需要按约定创建文件
- 可检查性:所有 Agent 能力都显式存在于文件系统中,任何团队成员都可以直接查看
- 可扩展性:工具、技能、通道、调度器都是独立模块,按需添加
- AI 友好:eve 包自带完整文档,Claude Code 等编程 Agent 可以直接从
node_modules/eve/docs读取文档进行辅助开发 - Durable:Agent 状态持久化,支持从失败点恢复
六、Mastra:Gatsby 团队的全栈 AI Agent 框架
Mastra 是另一个值得关注的生态项目。它来自 Gatsby 团队,是一个功能全面的全栈 AI Agent 框架,GitHub 上已有 15000+ commits,活跃度极高。
6.1 核心特性
Mastra 的设计更加"重量级",适合构建复杂的 AI 应用:
import { Mastra } from "@mastra/core";
const mastra = new Mastra({
workflows: {
customerSupport: customerSupportWorkflow,
dataAnalysis: dataAnalysisWorkflow,
},
agents: {
supportAgent: supportAgent,
analystAgent: analystAgent,
},
tools: {
searchDB: searchDBTool,
sendNotification: sendNotificationTool,
},
});
6.2 Workflow 编排
Mastra 提供了强大的 Workflow 引擎,适合复杂的业务流程编排:
import { Workflow } from "@mastra/core/workflow";
const supportWorkflow = new Workflow({
name: "customer-support",
steps: [
{
id: "classify",
execute: async ({ context }) => {
// 分类用户问题
const category = await classifyTicket(context.ticket);
return { category };
},
},
{
id: "route",
execute: async ({ context }) => {
// 根据分类路由到不同处理流程
if (context.category === "technical") {
return { assignee: "tech-team" };
}
return { assignee: "general-team" };
},
},
{
id: "respond",
execute: async ({ context }) => {
// 生成回复
const response = await generateResponse(context.ticket, context.category);
await sendEmail(context.ticket.email, response);
return { responseSent: true };
},
},
],
});
Mastra 和 eve 的定位不同:eve 是轻量级的、约定式的 Agent 框架,适合快速构建个人/小团队的 AI Agent;Mastra 是全栈的、功能完整的 AI 应用框架,适合构建企业级 AI 产品。
七、生产级实践:从开发到部署
7.1 多模型策略:降低成本的同时保证质量
生产环境中,不同任务应该用不同的模型:
// 简单任务用便宜模型
const fastModel = "anthropic/claude-haiku-4";
// 复杂推理用强模型
const smartModel = "anthropic/claude-sonnet-4.5";
// 最高要求用最强模型
const topModel = "anthropic/claude-opus-4";
async function processRequest(request: Request) {
// 简单查询用 Haiku
if (request.type === "simple_query") {
return generateText({ model: fastModel, prompt: request.prompt });
}
// 复杂分析用 Sonnet
if (request.type === "analysis") {
return generateText({ model: smartModel, prompt: request.prompt });
}
// 关键决策用 Opus
return generateText({ model: topModel, prompt: request.prompt });
}
通过 prepareStep 实现动态模型切换:
const result = await generateText({
model: smartModel, // 默认模型
tools: { search, analyze, summarize },
stopWhen: stepCountIs(10),
prompt: "深度分析这份报告",
prepareStep: async ({ stepNumber, steps }) => {
// 前两步用强模型做搜索和分析
if (stepNumber < 2) return { model: smartModel };
// 后续步骤用便宜模型做整合和总结
return { model: fastModel };
},
});
7.2 成本监控与限制
async function generateWithBudget(prompt: string, maxTokens: number) {
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt,
maxTokens, // 限制最大输出 token
onFinish({ totalUsage }) {
const inputCost = (totalUsage.promptTokens / 1_000_000) * 3; // $3/M
const outputCost = (totalUsage.completionTokens / 1_000_000) * 15; // $15/M
const totalCost = inputCost + outputCost;
if (totalCost > 0.5) { // 单次请求超过 $0.5 告警
alert(`本次请求成本 $${totalCost.toFixed(4)}`);
}
metrics.gauge("ai.cost.usd", totalCost);
metrics.counter("ai.tokens.prompt", totalUsage.promptTokens);
metrics.counter("ai.tokens.completion", totalUsage.completionTokens);
},
});
return result;
}
7.3 消息历史管理
import { generateText, type ModelMessage } from "ai";
class ConversationManager {
private messages: ModelMessage[] = [];
private maxTokens: number;
constructor(maxTokens = 100_000) {
this.maxTokens = maxTokens;
}
async addAndGenerate(userMessage: string): Promise<string> {
this.messages.push({ role: "user", content: userMessage });
// 压缩过长的消息历史
const compressed = await this.compressHistory();
if (compressed) {
this.messages = compressed;
}
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
messages: this.messages,
tools: { /* ... */ },
});
// 追加 Assistant 消息到历史
this.messages.push(...result.response.messages);
return result.text;
}
private async compressHistory(): Promise<ModelMessage[] | null> {
if (this.messages.length <= 10) return null;
// 保留系统消息和最近 5 轮对话
const recent = this.messages.slice(-10);
return recent;
}
}
7.4 错误处理与重试策略
import { generateText } from "ai";
async function reliableGenerate(params: Parameters<typeof generateText>[0]) {
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = [1000, 2000, 4000]; // 指数退避
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
return await generateText(params);
} catch (error) {
const isRetryable = error instanceof Error && (
error.message.includes("rate_limit") ||
error.message.includes("timeout") ||
error.message.includes("529") ||
error.message.includes("503")
);
if (!isRetryable || attempt === MAX_RETRIES - 1) {
throw error;
}
await new Promise(resolve =>
setTimeout(resolve, RETRY_DELAY_MS[attempt])
);
}
}
}
7.5 部署架构
Next.js App Router 方案(推荐):
next-app/
├── app/
│ └── api/
│ └── chat/
│ └── route.ts # streamText API
├── components/
│ ├── ChatWindow.tsx # useChat 集成
│ └── ToolResultCard.tsx # Generative UI 组件
└── lib/
├── tools/
│ ├── search.ts
│ └── database.ts
└── prompts/
└── system.ts
API Route 示例:
// app/api/chat/route.ts
import { streamText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { searchTool, databaseTool } from "@/lib/tools";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: anthropic("claude-sonnet-4.5"),
system: "你是一个技术助手,擅长编程和架构设计。",
messages,
tools: {
search: searchTool,
database: databaseTool,
},
stopWhen: stepCountIs(10),
maxTokens: 4096,
onError({ error }) {
console.error("Stream error:", error);
},
onFinish({ totalUsage }) {
// 记录使用量
console.log(`Tokens: ${JSON.stringify(totalUsage)}`);
},
});
return result.toUIMessageStreamResponse();
}
7.6 可观测性:与 Langfuse / OpenInference 集成
AI SDK 可以与 Langfuse 等可观测性平台无缝集成,实现 LLM 应用的全链路追踪:
// 使用 OpenTelemetry Instrumentation
import { instrument } from "ai-observability/openinference";
import { Langfuse } from "langfuse";
// 初始化 Langfuse
const langfuse = new Langfuse({
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
secretKey: process.env.LANGFUSE_SECRET_KEY,
baseUrl: "https://cloud.langfuse.com",
});
// AI SDK 自动采集 span 数据
const result = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt: "分析这段代码",
experimental_trace: {
name: "code-analysis",
metadata: {
userId: "user-123",
sessionId: "session-456",
},
},
tools: { /* ... */ },
});
八、Vercel AI SDK vs 其他框架的对比
| 维度 | Vercel AI SDK | LangChain | Pydantic AI | Mastra |
|---|---|---|---|---|
| 语言 | TypeScript | Python/JS | Python | TypeScript |
| 核心定位 | 统一模型调用层 | 全链路 AI 框架 | 类型安全 Agent | 全栈 AI 应用 |
| 学习曲线 | 低 | 高 | 中 | 中高 |
| 流式支持 | 原生优秀 | 一般 | 良好 | 良好 |
| 类型安全 | 原生 TypeScript | 弱 | 原生 Python | 原生 TypeScript |
| 工具调用 | 统一抽象 | 繁琐 | 简洁 | 灵活 |
| 前端集成 | useChat/useCompletion | 需自行实现 | 无内置 | 有基础支持 |
| 多模型支持 | 优秀 | 良好 | 良好 | 良好 |
| Agent 循环 | stopWhen 机制 | AgentExecutor | Loop | Workflow |
| 生产就绪 | 高(Vercel 背书) | 中 | 中 | 中高 |
| 社区活跃度 | 极高 | 高 | 高 | 中 |
选择建议:
- TypeScript 开发者:首选 Vercel AI SDK + eve/Mastra
- Python 开发者:首选 Pydantic AI(类型安全)或 LangChain(生态全面)
- 全栈 AI 应用:Mastra 提供最完整的方案
- 快速构建 Agent:eve 的约定式开发效率最高
九、完整实战:构建一个技术文章研究 Agent
让我们把所有知识串联起来,构建一个完整的技术文章研究 Agent:
9.1 项目结构
article-researcher/
├── agent/
│ ├── agent.ts
│ ├── instructions.md
│ ├── tools/
│ │ ├── search_web.ts
│ │ ├── search_github.ts
│ │ ├── read_article.ts
│ │ ├── analyze_code.ts
│ │ └── generate_outline.ts
│ └── skills/
│ ├── technical_writing.md
│ └── trend_analysis.md
├── package.json
└── tsconfig.json
9.2 核心实现
// agent/agent.ts
import { defineAgent } from "eve";
export default defineAgent({
model: "anthropic/claude-sonnet-4.5",
});
<!-- agent/instructions.md -->
你是一个技术文章研究助手。你的任务是:
1. 搜索最新技术趋势和热门开源项目
2. 分析技术文章的质量和深度
3. 生成高质量的技术文章大纲
工作流程:
1. 先用 search_web 搜索相关主题
2. 用 search_github 查找相关开源项目
3. 用 read_article 阅读重点文章
4. 用 analyze_code 分析关键代码
5. 最后用 generate_outline 生成文章大纲
输出要求:
- 中文
- 结构化的 Markdown 格式
- 包含代码示例
- 标注参考资料来源
// agent/tools/search_web.ts
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "搜索技术文章和最新资讯",
inputSchema: z.object({
query: z.string().min(1).describe("搜索关键词"),
freshness: z.enum(["day", "week", "month"]).optional()
.describe("时间范围"),
count: z.number().min(1).max(20).optional()
.describe("返回结果数量"),
}),
async execute({ query, freshness = "week", count = 10 }) {
const results = await searchService.search({
query,
freshness,
count,
});
return {
results: results.map((r) => ({
title: r.title,
url: r.url,
snippet: r.snippet,
publishedAt: r.publishedAt,
})),
};
},
});
// agent/tools/search_github.ts
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "搜索 GitHub 上的热门开源项目",
inputSchema: z.object({
topic: z.string().describe("搜索主题"),
sort: z.enum(["stars", "updated", "forks"]).optional()
.describe("排序方式"),
language: z.string().optional().describe("编程语言"),
}),
async execute({ topic, sort = "stars", language }) {
const results = await github.search({
q: `${topic}${language ? ` language:${language}` : ""}`,
sort,
order: "desc",
per_page: 10,
});
return {
repos: results.items.map((r) => ({
name: r.full_name,
description: r.description,
stars: r.stargazers_count,
forks: r.forks_count,
url: r.html_url,
language: r.language,
updatedAt: r.updated_at,
})),
};
},
});
// agent/tools/generate_outline.ts
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "基于收集的信息生成技术文章大纲",
inputSchema: z.object({
title: z.string().describe("文章标题"),
keyPoints: z.array(z.string()).describe("核心要点"),
targetAudience: z.enum(["beginner", "intermediate", "advanced"])
.describe("目标读者"),
estimatedWords: z.number().describe("预估字数"),
}),
async execute({ title, keyPoints, targetAudience, estimatedWords }) => {
const outline = await generateText({
model: "anthropic/claude-sonnet-4.5",
prompt: `为以下文章生成详细大纲:
标题:${title}
核心要点:${keyPoints.join("、")}
目标读者:${targetAudience}
预估字数:${estimatedWords}
要求:
1. 每个章节都要有明确的技术要点
2. 标注需要代码示例的位置
3. 包含实战案例
4. 输出 Markdown 格式`,
});
return { outline: outline.text };
},
});
十、总结与展望
10.1 核心价值
Vercel AI SDK + eve 生态在 2026 年提供的核心价值可以总结为:
- 统一模型层:一套代码对接所有大模型,消除模型切换的工程负担
- 类型安全的工具调用:Zod schema + TypeScript,从定义到执行全链路类型安全
- 多步 Agent 循环:stopWhen + prepareStep,精细控制 Agent 行为
- 安全审批机制:敏感操作人工确认,平衡自动化与安全性
- 前端深度集成:useChat / useCompletion / Generative UI,开箱即用的前端体验
- 约定式 Agent 开发:eve 的文件系统约定,让 Agent 开发回归简单
- 全栈覆盖:从 Core 到 UI 到 eve 到 Mastra,覆盖从简单到复杂的全场景
10.2 2026 下半年值得关注的趋势
- eve 正式版发布:目前处于 beta,正式版可能会带来更多企业级特性
- AI SDK 5.0 规划:更强大的 Agent 编排能力、更完善的可观测性
- 跨框架协作标准:OpenTelemetry + OpenInference 统一 LLM 应用的可观测性
- 成本优化:更多模型提供商支持、更智能的模型路由策略
- 边缘 AI:Cloudflare Workers、Vercel Edge Runtime 上的轻量 AI Agent
10.3 给开发者的建议
- 如果你刚开始 AI Agent 开发:从 Vercel AI SDK Core 开始,先掌握 generateText + tool calling,再逐步接触 streamText 和 AI SDK UI。
- 如果你在构建生产级聊天应用:直接使用 AI SDK UI 的 useChat,配合 Next.js App Router。
- 如果你在构建独立的 AI Agent:尝试 eve 的约定式开发,体验零配置的快感。
- 如果你在构建企业级 AI 产品:考虑 Mastra 的全栈方案,利用其 Workflow 编排和多 Agent 协作。
- 无论哪种场景:都要重视可观测性——AI 应用不同于传统软件,其行为具有一定的不确定性,需要更完善的监控和追踪体系。
2026 年是 AI Agent 工程化的元年。Vercel AI SDK 生态正在为 TypeScript 开发者铺就一条从简单到大复杂的完整路径。不管你是要构建一个简单的聊天机器人,还是一个复杂的多 Agent 协作系统,这套工具链都值得一试。
记住一句话:AI 的价值不在模型本身,而在你能用模型构建什么样的应用。Vercel AI SDK 给你的,正是构建应用的脚手架。