跳到正文

使用 A2UI 与 CopilotKit 智能体构建生成式 UI 应用

了解如何使用 Google 的 A2UI 开放标准和 CopilotKit 构建生成式 UI 应用,让智能体能够在各种主流框架中渲染丰富、可交互的界面。

本文目录文章开头

2026年10月29日

智能体与用户的交互正在从文本交换演变为丰富的用户界面。直到最近,大多数对话看起来是这样的:

用户:“帮我找一个三月去巴厘岛的度假套餐。”
智能体:(用散文形式列出六个套餐,每个都包含日期、酒店、航班、价格)
用户:“要那个五晚含早餐的。”
智能体:“这是链接。你可以在运营商的网站上预订。”

智能体可以规划行程,但所有内容都以大段文字的形式返回。它们没有标准的方法在对话内部渲染可选择的套餐列表、目的地地图或日期选择器来帮助你完成后续预订。

生成式 UI 是让智能体在运行时构建界面的层,根据每个请求的需要进行塑造——为用户提供丰富、交互式的体验。实现这一点需要两个部分:一种描述 UI 的方式,以及一个将你的智能体连接到应用程序并渲染该 UI 的智能体技术栈。

  • A2UI(Agent-to-UI) 是 Google 的与框架无关的生成式 UI 开放标准。智能体将界面描述为数据,你的应用程序使用你已有的组件来绘制它。它在设计上与传输方式无关。
  • CopilotKit 提供智能体集成栈,用于集成 “LangChain”、“AWS Strands”、“Google ADK” 等智能体框架,以构建面向用户的智能体应用。它提供了一个使用 A2UI 协议构建丰富应用的工具包,包括聊天界面、运行时,并在 React 和 Angular 中利用 A2UI 渲染器。CopilotKit 还为 Vue 和 Slack 提供自定义 A2UI 渲染器。

any-framework-any-surface

什么是 A2UI?

生成式 UI 涵盖了一系列方法,从使用预定义的高阶组件,到让 AI 智能体灵活决定如何构建 UI。

在受控的一端,你提前构建每个组件,智能体选择渲染哪一个以及使用什么数据。它是品牌安全的,但不允许根据用户意图进行深度定制和个性化。在开放的一端,智能体返回一个用 HTML、JavaScript 和/或 Dart 编写的原始 UI 程序,在沙盒化的 iframe 中渲染。这涵盖了你未预料到的所有情况,代价是界面会偏离你的设计系统,并执行模型编写的代码。

A2UI 适用于整个频谱。它既参与 使用决策模型的受控生成(如 Typesafe 的 Jev),也参与可能输出 A2UI JSON 消息的开放式代码生成。声明式模式是最流行的,智能体在此模式下组装预先声明的组件和函数。A2UI 是声明 UI 意图的与框架无关的标准,因此本地或远程智能体可以使用通用语言从你现有的组件目录中生成你的 UI。

  • 安全第一。A2UI 是一种声明式数据格式,而非可执行代码。客户端维护一个受信任组件的目录,因此智能体在该集合之外编造的任何内容都会在到达屏幕之前被拦截。
  • 对 LLM 友好且支持流式传输。有效负载是一个扁平的小型 JSON 消息列表,这些消息通过 ID 相互引用,因此智能体可以增量地发出它们,客户端在组件到达时进行渲染。
  • 与框架无关且可移植。同一个响应可以通过 React、Lit、Angular、SwiftUI、Jetpack Compose(Android)或 Flutter(多平台)渲染,也可以通过社区渲染器在 Vue 甚至终端中渲染。

前端开发者现在只需交付一次构建模块,智能体就能针对每个请求进行组合。

抱歉,您的浏览器不支持此视频的播放

基础目录包含 18 个通用原语,涵盖布局、显示、输入和容器。智能体可以根据请求需求,用这同样的 18 个原语组合出完全不同的界面。

three-primitives

基础目录是刻意精简的,因此大多数生产应用会定义自己的自定义目录。自定义组件可以是前端已经能渲染的任何东西,包括一个实时地图——智能体向其中填充坐标,而您的渲染器负责绘制路线。

map-genui

A2UI 与 CopilotKit 如何协同工作

CopilotKit 基于 AG-UI(智能体-用户交互协议)构建,它支持 A2UI 载荷,并为众多智能体后端提供 Agent SDK。

您的智能体发出 A2UI 操作。AG-UI 将它们作为类型化事件传递到客户端。当用户执行任何操作时,这些值会沿着同一条流发送回去。

A2UI 适用于任何兼容 AG-UI 的智能体。Google ADK、LangChain、Mastra 和 Strands 等框架都兼容 AG-UI,因此无论您的智能体运行在哪一个上,设置方式都是相同的。

cpk-a2ui-agui

在应用中设置 A2UI

设置归结为两件事:将您的智能体连接到 CopilotKit,以及定义智能体被允许使用哪些组件。

以 Google ADK 为例,ag_ui_adk 包装了任意 ADK 智能体,并将其作为 AG-UI 端点在 FastAPI 上提供服务:

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="/")

在应用端,您在 /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>

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 代理将 A2UI 界面流式传输到 CopilotKit 前端。

bi-directional surfaces

有两个要素使往返通信得以实现:绑定到数据路径的输入,以及携带动作、指明要回传哪些路径的按钮。

{ "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" } } } } }

验证在客户端运行,因此无效的邮箱会直接内联显示错误,而无需调用模型。在按钮触发之前,任何内容都不会到达代理。

然后客户端发送绑定的值,代理针对同一个 surfaceId 重新生成。这就是整个流程都存在于一个界面上的方式:航班搜索、结果、乘客详情和确认。

抱歉,您的浏览器不支持此视频的播放

在 AG-UI 上运行 A2UI 的优势

每个 AG-UI 集成都继承了这些优势,因此您无需自行构建:

  • 最小化的服务端设置:目录在设置时即可到达代理,因此只需在客户端注册即可。
  • 在专用子代理中生成:目录和协议规则不会占用主代理的上下文窗口,界面会在子代理生成时流式传输到客户端。
  • 自愈输出:无效的生成会被捕获,具体的错误会被回传以进行修正,因此不会有损坏的内容到达屏幕。
  • 优雅降级:当重试次数耗尽时,界面会解析为一条简短消息,对话继续进行,而不是陷入错误状态。

快速开始

创建一个完整的 A2UI + CopilotKit 应用程序。这将创建一个带有 CopilotKit 代理集成的入门级 A2UI 应用程序。

npx copilotkit@latest create --name my-app --framework a2ui

CopilotKit Dojo 提供可运行的 A2UI 演示:固定的服务端 schema、针对自定义目录的动态 schema,以及一个错误恢复示例——首次渲染无效后会自愈为有效渲染。

探索如何使用 CopilotKit 构建生成式 UI 代理,或深入阅读 A2UI 文档,了解如何将 A2UI 与您选择的任何框架集成。

阅读显示设置

调整正文排版

当前浏览器记住选择,应用于文章正文。手机上正文宽度以屏幕可用空间为限。

图表完整性提示

普通文章遇到图表保存问题时显示提示。