如何用 A2UI 与 CopilotKit 构建生成式 UI 应用
Build Generative UI Apps with A2UI & CopilotKit Agents
Google 介绍其框架无关的开放标准 A2UI,让智能体以声明式 JSON 描述界面,由应用用已有组件渲染。文章以 Google ADK 为例给出接入 CopilotKit 的代码,说明如何定义组件目录、映射渲染器并实现双向多步流程。A2UI 采用声明式数据格式而非可执行代码,客户端只渲染可信组件目录内的组件,同一响应可渲染到 React、Angular、SwiftUI、Flutter 等。
原文给出了 A2UI 与 CopilotKit 的完整接入代码和双向交互示例,可据此判断生成式 UI 的落地方式。
2026年10月29日
Agent 与用户的交互如今正从文本交流演进为丰富的 UI。直到不久前,大多数对话还是这样的:
用户:“帮我找一个三月去巴厘岛的度假套餐。”
Agent:(用大段文字列出六个套餐,每个都包含日期、酒店、航班、价格)
用户:“要那个含早餐的五晚套餐。”
Agent:“这是链接。你可以在运营商的网站上预订。”
Agent 能够规划行程,但所有内容都以大段文字的形式返回。它们没有标准方式来在对话本身之中渲染可选择的套餐列表、目的地地图,或引导你完成后续预订的日期选择器。
生成式 UI 是让 Agent 在运行时构建界面的层,界面形态由每个请求的需求决定——为用户带来丰富、可交互的体验。实现这一点需要两部分:一种描述 UI 的方式,以及一套 Agent 技术栈,将你的 Agent 连接到你的应用并渲染该 UI。
- A2UI(Agent-to-UI) 是 Google 推出的生成式 UI 框架无关开放标准。Agent 将界面描述为数据,你的应用用已有的组件将其绘制出来。它在设计上是传输无关的。
- CopilotKit 提供 Agent 集成技术栈,可与“LangChain”、“AWS Strands”、“Google ADK”等 Agent 框架集成,用于构建面向用户的 Agent 应用。它提供了一套工具包,用于借助 A2UI 协议构建丰富的应用,包括聊天界面、运行时,并在 React 和 Angular 中利用 A2UI 渲染器。CopilotKit 还为 Vue 和 Slack 提供自定义 A2UI 渲染器。
什么是 A2UI?
生成式 UI 涵盖一系列方法,从使用预定义的高阶组件,到让你的 AI Agent 灵活决定如何构建 UI。
在受控的一端,你预先构建每个组件,Agent 选择渲染哪一个以及使用什么数据。这种方式对品牌安全,但不允许基于用户意图进行深度定制和个性化。在开放的一端,Agent 返回用 HTML、Javascript 和/或 Dart 编写的原始 UI 程序,在沙箱 iframe 中渲染。这能覆盖你未曾预想到的任何情况,代价是界面会偏离你的设计系统,并执行模型编写的代码。
A2UI 贯穿整个谱系。它既参与借助 Typesafe 的 Jev 等决策模型进行的受控生成,也参与可能输出 A2UI JSON 消息的开放式代码生成。声明式模式——Agent 组装预先声明的组件和函数——是最流行的。A2UI 是声明 UI 意图的框架无关标准,因此本地或远程 Agent 可以使用一种通用语言,从你现有的组件目录生成你的 UI。
- 安全优先。A2UI 是声明式数据格式,而非可执行代码。客户端维护一个受信任组件的目录,因此 Agent 在该集合之外发明的任何内容都会在到达屏幕之前被拦截。
- 对 LLM 友好且支持流式传输。载荷是一个扁平的小型 JSON 消息列表,消息之间通过 ID 相互引用,因此 Agent 可以增量输出,客户端在组件到达时即进行渲染。
- 框架无关且可移植。同一个响应可通过 React、Lit、Angular、SwiftUI、Jetpack Compose(Android)或 Flutter(多平台)渲染,也可通过面向 Vue 甚至终端的社区渲染器渲染。
前端开发者现在只需交付一次构建块,智能体便会针对每个请求将它们组合起来。
抱歉,你的浏览器不支持播放此视频
基础目录提供 18 个通用原语,涵盖布局、显示、输入和容器。智能体可以根据请求需要,用同样的 18 个原语组合出完全不同的界面。
基础目录刻意保持精简,因此大多数生产应用会定义自己的自定义目录。自定义组件可以是你的前端已经渲染的任何内容,包括由智能体填入坐标、再由你的渲染器绘制路线的实时地图。
A2UI 与 CopilotKit 如何协同工作
CopilotKit 构建于 AG-UI(Agent-User Interaction Protocol)之上,后者支持 A2UI 载荷,并提供跨多种智能体后端的 Agent SDK。
你的智能体发出 A2UI 操作。AG-UI 以类型化事件的形式将它们传送到客户端。当用户执行任何操作时,这些值会沿同一条流返回。
A2UI 可与任何兼容 AG-UI 的智能体配合使用。Google ADK、LangChain、Mastra 和 Strands 等框架都兼容 AG-UI,因此无论你的智能体运行在哪个框架上,设置方式都完全相同。
在你的应用中设置 A2UI
设置归结为两件事:将你的智能体连接到 CopilotKit,以及定义智能体允许使用哪些组件。
以 Google ADK 为例,ag_ui_adk 包可包装任意 ADK 智能体,并将其作为 FastAPI 上的 AG-UI 端点提供服务:
from fastapi import FastAPI
from google.adk.agents import LlmAgent
from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint
root_agent = LlmAgent(
name="flight_agent",
model="gemini-3.8-flash",
instruction="Help users find and book flights. Call generate_a2ui to show results.",
)
adk_agent = ADKAgent(
adk_agent=root_agent,
app_name="flights",
user_id="demo_user",
use_in_memory_services=True,
)
app = FastAPI()
add_adk_fastapi_endpoint(app, adk_agent, path="/")Python
已复制
在应用侧,你在 /api/copilotkit 处将该端点注册到 CopilotKit 运行时。这只是几行标准设置, Google ADK 快速入门中已有介绍,且不需要任何 A2UI 专属内容。
A2UI 本身从客户端启用,而你的组件已经在客户端。定义智能体允许绘制的内容,将每个定义映射到渲染器,并将目录传递给 CopilotKit provider。
import { CopilotKit, CopilotChat } from '@copilotkit/react-core/v2';
import {
createCatalog,
type CatalogDefinitions,
type CatalogRenderers,
} from '@copilotkit/a2ui-renderer';
import { z } from 'zod';
const catalogDefinitions = {
FlightCard: {
description: 'A flight result with airline, times, and stops.',
props: z.object({
airline: z.string(),
departs: z.string(),
arrives: z.string(),
stops: z.number(),
}),
},
} satisfies CatalogDefinitions;
const catalogRenderers = {
FlightCard: MyFlightCard, // your React component
} satisfies CatalogRenderers<typeof catalogDefinitions>;
const catalog = createCatalog(catalogDefinitions, catalogRenderers, {
catalogId: 'flight-catalog',
includeBasicCatalog: true,
});
<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ catalog }}>
<CopilotChat />
</CopilotKit>JavaScript
已复制
description 会进入智能体的提示词,因此模型知道何时应使用 FlightCard 而不是通用卡片。Zod schema 会校验它发回的 props。
A2UI 配置可以提前在服务器上设置,也可以动态创建,随请求从客户端发送到服务器。上面的 ADK 代码使用了动态配置,因此它使用了 generate_a2ui 而无需定义它。文档涵盖这两种方式。
这就是 CopilotKit 路径。你也可以直接用 @ag-ui/client 消费事件流,并将 A2UI 操作交给任何兼容的渲染器: @a2ui/react,或 Flutter、Lit、Angular 的对应版本。
抱歉,你的浏览器不支持播放此视频
构建双向 A2UI 界面
大多数智能体生成的 UI 都是一次性的。智能体绘制出内容,你阅读它,而一旦有任何变化,它就会过时。
A2UI 界面是双向的,组件是响应式的,这使得多步骤流程成为可能。用户在界面上执行的任何操作(选择日期、选择航班、输入乘客信息)都会沿同一条流返回,智能体随后使用这些值重新发出该界面。
下面是一个端到端预订流程的高层架构示例:Cloud Run 上的 AG-UI agent 将 A2UI 界面流式传输到 CopilotKit 前端。
往返流程能正常工作靠两点:绑定到数据路径的输入,以及一个携带 action 的按钮,该 action 指明要回传哪些路径。
{ "id": "cabin", "component": "ChoicePicker", "variant": "mutuallyExclusive",
"options": [ { "label": "Economy", "value": "eco" },
{ "label": "Business", "value": "biz" } ],
"value": { "path": "/booking/cabin" } },
{ "id": "confirm", "component": "Button", "child": "confirm_label",
"action": { "event": { "name": "confirmBooking",
"context": { "cabin": { "path": "/booking/cabin" },
"email": { "path": "/booking/email" } } } } }JSON
已复制
校验在客户端运行,因此错误的邮箱会就地显示错误,而不会调用模型。在按钮触发之前,任何内容都不会到达 agent。
随后客户端发送绑定的值,agent 针对同一个 surfaceId 重新发出。整个流程就这样存在于同一个界面上:航班搜索、结果、乘客详情和确认。
抱歉,你的浏览器不支持此视频的播放
通过 AG-UI 运行 A2UI 的优势
每个 AG-UI 集成都会继承这些优势,因此你无需自行构建:
- 极少的服务端设置:catalog 在设置阶段就会到达 agent,因此只需在客户端注册即可。
- 在专用子 agent 中生成:catalog 和协议规则不会进入主 agent 的上下文窗口,并且子 agent 生成界面时会将其流式传输到客户端。
- 自愈输出:无效的生成会被捕获,具体错误会被回传以进行修正,因此不会有损坏的内容到达屏幕。
- 优雅失败:当重试耗尽时,界面会解析为一条简短消息,对话继续进行,而不是陷入错误状态。
开始使用
创建一个完整的 A2UI + CopilotKit 应用。这会创建一个带有 CopilotKit Agent 集成的 A2UI 入门应用。
npx copilotkit@latest create --name my-app --framework a2uiShell
已复制
CopilotKit Dojo 提供了可运行的 A2UI 演示:固定服务端 schema、针对自定义 catalog 的动态 schema,以及一个错误恢复示例,其中无效的首次渲染会自愈为有效渲染。
探索如何使用 CopilotKit 构建生成式 UI Agent,或深入阅读 A2UI 文档,了解如何将 A2UI 与你选择的任意框架集成。
上一页
下一页
来源:Google Developers Blog · developers.googleblog.com