vercel/ai 是 Vercel 与 Next.js 团队主导的开源项目,README 将其定位为 provider-agnostic 的 TypeScript 工具包,用于在 Next.js、React、Svelte、Vue、Angular 等 UI 框架以及 Node.js 运行时上构建 AI 应用与 Agent。仓库 Topics 同时覆盖 openai、anthropic、gemini、language-model、react、svelte、vue、nextjs,说明它公开的元数据横跨多个模型 Provider 与多个前端框架。本文只依据官方 README 与仓库公开信息,梳理它的接入层边界与 Agent 工具链形态;涉及内部实现细节的部分,均标注为需要进一步查源码确认的工程判断。
两条接入路径:统一模型字符串 vs 直连 Provider 包
README 给出的第一种方式是默认走 Vercel AI Gateway,直接传模型字符串:
const result = await generateText({
model: 'anthropic/claude-opus-5.5',
prompt: 'Hello!',
});
第二种方式是安装具体 Provider 包后调用工厂函数:
import { anthropic } from '@ai-sdk/anthropic';
const result = await generateText({
model: anthropic('claude-opus-5-5'),
prompt: 'Hello!',
});
这两条路径共用同一个 generateText 入口,是理解抽象层边界的关键。从公开 API 形态看,抽象层收敛的是调用侧契约:模型标识、prompt、输出结构、工具定义等参数形状保持一致,而 Provider 差异被下沉到模型对象或网关路由之后。README 没有展开说明 Provider 适配器内部如何映射各家的请求体、鉴权头、流式事件格式与错误码,因此“差异具体在哪一层被抹平”属于需要读 packages/ 下对应 Provider 源码才能确认的问题,不能仅凭 README 推断。
对开发者的直接含义是:如果只需要文本生成与结构化输出,统一入口足以覆盖;一旦涉及某家独有的能力(例如特定工具类型、特定多模态参数),就要确认该能力是否已被对应 Provider 包暴露,否则需要自行封装。
结构化输出:用 schema 约束而非解析文本
README 展示了 Output.object 配合 zod schema 的用法:
const { output } = await generateText({
model: 'openai/gpt-6-astra',
output: Output.object({
schema: z.object({
recipe: z.object({
name: z.string(),
ingredients: z.array(z.object({ name: z.string(), amount: z.string() })),
steps: z.array(z.string()),
}),
}),
}),
prompt: 'Generate a lasagna recipe.',
});
这里值得注意的工程点是:schema 由调用方提供,返回结果直接是类型化的 output,而不是让开发者自己从文本里正则提取 JSON。README 未说明底层是依赖各 Provider 的原生结构化输出能力,还是通过提示词加校验重试实现,这一点同样需要查源码确认。若你的场景对失败重试、schema 校验失败后的行为有强要求,建议先验证该路径的实际失败模式。
Agent:ToolLoopAgent 与工具循环
Agent 部分的核心是 ToolLoopAgent。README 的示例构造了一个带 shell 工具的 Agent:
const sandboxAgent = new ToolLoopAgent({
model: 'openai/gpt-6-astra',
system: 'You are an agent with access to a shell environment.',
tools: {
shell: openai.tools.localShell({
execute: async ({ action }) => {
const [cmd, ...args] = action.command;
const sandbox = await getSandbox();
const command = await sandbox.runCommand({ cmd, args });
return { output: await command.stdout() };
},
}),
},
});
从命名与结构可以读出几点:工具以对象字典形式注册,键名即工具名;工具由 Provider 包提供(openai.tools.localShell),执行函数由使用者注入,负责真正调用外部环境。ToolLoopAgent 的“Loop”暗示模型调用与工具执行之间存在循环,直到满足终止条件——但循环的终止判定、最大步数、并发工具调用的处理策略,README 均未给出,属于必须查源码或 API Reference 才能落地的部分。
另一个示例是图像生成 Agent,工具为 openai.tools.imageGeneration({ partialImages: 3 }),并用 InferAgentUIMessage 导出消息类型。这说明 Agent 的类型信息可以从实例反推,供前端复用,减少前后端类型漂移。
UI 层:流式响应与工具调用的渲染衔接
服务端用 createAgentUIStreamResponse 把 Agent 与消息数组转成流式响应:
export async function POST(req: Request) {
const { messages } = await req.json();
return createAgentUIStreamResponse({ agent: imageGenerationAgent, messages });
}
客户端用 useChat 消费,并按 message.parts 的 type 分支渲染:文本走 part.text,工具调用走 tool-generateImage 这类带工具名的 part,交给专门的组件处理。工具组件通过 UIToolInvocation 接收 invocation,并按 invocation.state 分支:input-available 显示加载态,output-available 渲染结果。
这套设计的工程价值在于把“工具调用的中间状态”提升为一等公民:UI 不需要等最终文本,而是可以针对工具的不同阶段渲染不同界面,这正是 generative-ui 场景的常见需求。README 明确说明 AI SDK UI 的 hooks 是框架无关的,可用于 Next.js、React、Svelte 和 Vue,按框架安装对应包(如 @ai-sdk/react)。但框架无关的具体实现方式(共享核心加薄适配层,还是各框架独立实现)README 未说明。
选型判断与自封装边界
基于以上公开信息,可以给出如下判断,其中事实部分来自 README,判断部分属于工程分析:
- 事实:需要 Node.js 22+,安装命令为
npm install ai;提供npx skills add vercel/ai以便在 Claude Code、Cursor 等编码 Agent 中使用。 - 事实:默认走 Vercel AI Gateway 即可用模型字符串访问多家 Provider,也可直连 Provider 包。
- 判断:若你的技术栈是 Next.js/React 且需要聊天式 UI 与工具调用渲染,AI SDK 的 UI 层与 Agent 类型推导能省掉不少胶水代码。
- 判断:若你需要精细控制重试、并发、缓存或 Provider 独有参数,应先在源码中确认对应能力是否已暴露;README 层面无法回答这些问题。
- 判断:Provider 适配的边界在“调用契约统一”,而非“能力完全对齐”。跨 Provider 迁移时,模型字符串与工厂函数可替换,但工具定义、结构化输出支持度、流式事件语义仍需逐个验证。
仓库当前约 27.4k stars、5.4k forks、9,119 次提交,采用 pnpm workspace 与 turbo 组织多包结构,packages/ 与 apps/docs 分离,说明这是一个多包单仓项目。要验证本文标注为“需查源码”的结论,建议从 packages/ 下 Provider 包与 Agent 相关实现入手,对照 API Reference 逐项确认,而不是仅凭 README 与 Topics 推断内部架构。