用 A2UI 与 CopilotKit 智能体构建生成式 UI 应用
Build Generative UI Apps with A2UI & CopilotKit Agents
谷歌介绍其框架无关的开放标准 A2UI,让智能体以声明式 JSON 描述界面,由应用用已有组件渲染,并配合 CopilotKit 的 AG-UI 协议接入 LangChain、Google ADK、Mastra、Strands 等智能体框架。
原文给出 A2UI 与 CopilotKit 的完整接入代码和双向交互示例,可据此判断生成式 UI 的落地方式。
2026年10月29日
Agent-User 交互现在正从文本交换发展到丰富的 UI。直到最近,大多数对话看起来是这样的:
User: "为我找到三月份去巴厘岛的假日套餐。">
Agent: (六份用散文描述的套餐,每份都有日期、酒店、航班和价格)
User: "五晚的带早餐的那个。">
Agent: "这是链接。你可以在运营商的网站上预订它。
Agents 可以计划旅行,但所有内容都以文本墙的形式返回。他们没有标准的方法来渲染可选择的套餐列表、目的地的地图或日期选择器,以在对话本身中完成其余的预订。
生成式 UI 是允许 agents 在运行时构建接口的层,其形状由每个请求的需要决定 - 为用户提供丰富的交互式体验。实现这一点需要两个部分:一种描述 UI 的方法和一个 agentic 堆栈,它将你的 agent 连接到你的应用程序并渲染该 UI。
- A2UI (Agent-to-UI) 是 Google 的框架无关的生成式 UI 开放标准。Agent 将界面描述为数据,而你的应用程序使用你已有的组件来绘制它。它按设计是传输无关的。
- CopilotKit 提供了 agent 集成堆栈,用于与 agent 框架如“LangChain”、“AWS Strands”、“Google ADK”等进行集成,用于构建面向用户的面板应用程序。它提供了一个使用 A2UI 协议构建丰富应用程序的工具包,包括聊天界面、运行时,并利用 A2UI 渲染器,跨越 React 和 Angular。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,甚至终端渲染。
前端开发者现在可以一次性交付构建块,而代理会为每个请求组合它们。
抱歉,您的浏览器不支持此视频的播放
The Basic Catalog包含18种通用原语,涵盖布局、显示、输入和容器。代理可以根据请求需要,从相同的18种原语中组合出完全不同的界面。
基本目录故意保持简洁,因此大多数生产应用程序 定义自己的自定义目录。自定义组件可以是前端已经渲染的任何内容,包括代理在您的渲染器绘制路线时填充坐标的实时地图。
A2UI 和 CopilotKit 如何协同工作
CopilotKit 基于 AG-UI (代理-用户交互协议)构建,该协议支持 A2UI 负载,并在许多代理后端提供代理 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 提供者。
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 模式验证它返回的属性。
A2UI 配置可以在服务器上提前设置,也可以动态创建,随着请求从客户端发送到服务器。上面的 ADK 代码使用了动态配置,这就是为什么它使用了 generate_a2ui 而没有定义它的原因。 文档涵盖了这两种方法。
这就是 CopilotKit 的路径。你也可以直接使用 @ag-ui/client 消费事件流,并将 A2UI 操作交给任何兼容的渲染器: @a2ui/react,或者 Flutter、Lit 或 Angular 的等效版本。
抱歉,您的浏览器不支持此视频的播放
构建双向 A2UI 表面
大多数代理生成的 UI 都是单次的。代理绘制一些内容,你读取它,一旦有任何变化,它就会过时。
A2UI 表面是双向的,组件是响应式的,这使得多步骤流程成为可能。用户在界面上的任何操作(选择日期、选择航班、输入乘客详细信息)都会沿着相同的流返回,代理会使用这些值从那里重新发出表面。
这是一个端到端预订流程的高级架构示例,AG-UI 代理在 Cloud Run 上流式传输 A2UI 表面到 CopilotKit 前端。
有两个因素使往返行程工作:绑定到数据路径的输入,以及一个携带动作的按钮,该按钮命名要发送回哪些路径。
{ "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
已复制
验证在客户端运行,因此一个坏电子邮件会直接显示错误,而无需调用模型。直到按钮触发之前,没有任何内容到达代理。
然后客户端发送绑定值,代理重新对相同的 surfaceId 发出。这就是整个流程如何存在于一个表面上:航班搜索、结果、乘客详情和确认。
抱歉,您的浏览器不支持此视频的播放
运行 A2UI 而不是 AG-UI 的优势
每个 AG-UI 集成都继承了这些优势,因此您不必自己构建它们:
- 最小的服务器端设置:目录在设置时到达代理,因此只需在客户端注册它。
- 在专用子代理中生成:目录和协议规则保持在您主代理的上下文中,表面随着子代理生成它而流式传输到客户端。
- 自愈输出:无效的生成被捕获,具体的错误会返回以进行更正,因此没有任何损坏的内容到达屏幕。
- 优雅的失败:当重试用尽时,表面解析为简短的消息,对话继续而不是处于错误状态中。
开始使用
创建一个完整的 A2UI + CopilotKit 应用程序。这会创建一个带有 CopilotKit 代理集成的 A2UI 启动应用程序。
npx copilotkit@latest create --name my-app --framework a2uiShell
已复制
The CopilotKit Dojo 有可运行的 A2UI 演示:固定的服务器端模式、针对自定义目录的动态模式,以及一个错误恢复示例,其中无效的第一个渲染会恢复为有效的。
探索如何使用 CopilotKit 构建生成式 UI 代理,或者深入研究 A2UI 文档 以了解如何将 A2UI 与您选择的任何框架集成。
上一个
下一个
来源: Google Developers Blog · developers.googleblog.com