一条 part 分支,给出生成式 UI 的设计前提

消息流里出现 'tool-generateImage' 时,UI 层要决定渲染什么。官方示例的做法是分支:

case 'text':
  return {part.text};
case 'tool-generateImage':
  return ;

这段代码背后是对“生成式 UI”的一种设计取舍:模型没有把组件代码写进消息流,模型只是触发了一个开发者预先注册的工具调用,前端拿到这个结构化 part 后,从本地组件实现中选出 ImageGenerationView。真正被“生成”的,是消息流中的文本与工具输出;UI 容器仍受开发者声明的组件清单控制。

这个示例来自 Vercel AI SDK。README 给自己的定义是 provider-agnostic TypeScript toolkit:面向 AI 应用与 Agent,覆盖 Next.js、React、Svelte、Vue、Angular 等 UI 框架和 Node.js runtime,要求 Node.js 22+。项目作者是 Vercel 与 Next.js 团队成员,并接受社区贡献。如果你只把它当作一个 LLM 调用封装,会忽略它真正想解决的问题:让 AI 应用与 Agent 的前后端交互拥有一套统一、类型化的数据结构。

若你使用 Claude Code、Cursor 这类编码 Agent,官方还建议在仓库中加入对应的 skill:npx skills add vercel/ai。这算是项目对“Agent 对话工程化”的自我定位细节。

Provider 接入有两条默认不同的路径

接入模型时,README 展示了两种写法。第一种直接传模型字符串:

const result = await generateText({
  model: 'anthropic/claude-opus-4.6', // 或 'openai/gpt-5.4', 'google/gemini-3-flash'
  prompt: 'Hello!',
});

这段代码下方注明:默认情况下,AI SDK 使用 Vercel AI Gateway 接入各主要 Provider。因此这里有一个需要提前确认的工程边界:最简写法并不等价于请求直连模型厂商,默认接入通道是 Vercel 的 AI Gateway。若你的场景要求直连,README 给出的替代路径是安装对应 Provider 的 SDK 包:

import { anthropic } from '@ai-sdk/anthropic';

const result = await generateText({
  model: anthropic('claude-opus-4-6'),
  prompt: 'Hello!',
});

两种写法并存,给 AI SDK 留出了“默认方便”与“链路可控”的切换空间。但这也意味着选型时就要确定走哪条路:模型字符串方案把 Provider 路由交给网关;直连方案会让代码多一层对 provider SDK 的引用。

从 Agent 工具到前端消息类型的完整链路

在基础生成能力上,README 还出现了几个关键原语:generateText 负责文本生成;配合 Output.object 与 zod schema 可让模型返回结构化数据;ToolLoopAgent 则把模型、system prompt 与 tools 组合成一个 Agent 对象。对 TypeScript 团队来说,结构化输出沿用了自己熟悉的 zod 生态,SDK 不必为此引入另一套 schema 语言。

真正把 Agent 与 UI 连接起来的设计,体现在图片生成 Agent 的示例中。Agent 在服务端定义:

export const imageGenerationAgent = new ToolLoopAgent({
  model: 'openai/gpt-5.4',
  tools: {
    generateImage: openai.tools.imageGeneration({
      partialImages: 3,
    }),
  },
});

随后通过 InferAgentUIMessage 把 Agent 的工具集合直接推导为前端消息类型:

export type ImageGenerationAgentMessage = InferAgentUIMessage;

服务端路由把请求接到 Agent 的响应通道上:

export async function POST(req: Request) {
  const { messages } = await req.json();
  return createAgentUIStreamResponse({
    agent: imageGenerationAgent,
    messages,
  });
}

前端 useChat() 拿到消息后,对 message.parts 做类型分支。对应的图片生成组件,接收的 prop 类型直接来自工具本身:

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

export default function ImageGenerationView({
  invocation,
}: {
  invocation: UIToolInvocation>;
}) {
  switch (invocation.state) {
    case 'input-available':
      return Generating image...;
    case 'output-available':
      return ;
  }
}

从官方 README 的图片生成示例可看出,“生成式 UI”的一种实现模式是:服务端声明 Agent 的工具集,工具类型被 InferAgentUIMessage 推导到前端;前端每个工具 part 对应一个组件;组件又通过 invocation.state 感知工具在服务端的执行阶段。模型只在“选择哪个已注册工具、生成什么内容”上有自由度,不再有“生成任意组件结构”的自由度。

这套边界适合什么场景

基于 README 的示例,可以提炼出几个可供选型判断的工程结论。

第一,如果你的应用需要 Agent 工具执行结果驱动前端展示,AI SDK 的这套类型链路会省掉大量手写消息协议的功夫。Agent 每增加一个工具,前端消息类型在类型层面会相应扩展;UI 组件只要按约定实现并做分支即可。至于类型推导的具体边界,可进一步用 ToolLoopAgent 的源码验证。

第二,UI 的可表达范围以“预先注册的工具”为上限。想展示新的界面形态,必须先在 Agent 侧定义工具、再在前端注册对应组件。如果产品需要的不是工具调用型交互,而是模型自由布局式的界面生成,这套把 UI 工具化的模型反而会成为约束。

第三,部署链路不是“开箱即直连”。README 默认接入的是 Vercel AI Gateway;不经过网关的用法需要改用 provider 直连 SDK。README 只在开头声明 Node.js 22+,并未给出边缘 Runtime 或自建网关的说明,这类环境兼容性应在官方文档或最小验证中确认。

如果准备进一步读源码,建议优先验证这几个问题:createAgentUIStreamResponse 内部使用什么协议切分流式消息?ToolLoopAgent 如何控制循环边界与工具异常?Svelte、Vue 的 UI hooks 与 React 版本的能力是否完全平级?这些问题都无法从当前 README 的示例中获得结论,但决定了 AI SDK 是否值得放进你的长期技术底座。