读见

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

原题Build Generative UI Apps with A2UI & CopilotKit Agents

约 7 分钟约 1,535 字原文英文已翻译

推荐理由Google 介绍 A2UI 与 CopilotKit 的界面生成方法,可学习怎样将智能体意图交给受控组件呈现,兼顾交互表达与应用约束。

读前速览

4 个要点

本文介绍 A2UI 与 CopilotKit,这是一个利用声明式数据而非原始代码,为 AI 智能体构建安全、双向生成式 UI 的框架。

  1. 通过 A2UI 实现声明式生成式 UI

    智能体不再返回可执行代码,而是由 A2UI 允许智能体以声明式数据描述界面,客户端使用受信任的组件进行渲染,从而确保安全性。

  2. 双向交互界面

    A2UI 界面支持多步骤流程,用户操作(如选择日期)会通过同一数据流回传给智能体,使智能体能够重新发出更新后的界面。

  3. 自愈能力与可靠性

    该框架在客户端捕获无效的生成内容,并将错误回传给智能体进行修正,确保不会有损坏的 UI 触达最终用户。

  4. 与框架无关的集成

    通过 CopilotKit 与 AG-UI 协议,A2UI 可兼容多种智能体后端,包括 LangChain、AWSrock 和 Google ADK。

完整摘要

文章探讨了从基于文本的 AI 交互向生成式 UI 的转变。文中介绍了 A2UI(Agent-to-UI),这是一个与框架无关的标准,允许智能体以数据形式描述界面,再由客户端进行渲染。借助 CopilotKit,开发者可以将其与 LangChain、Google ADK 等多种智能体框架集成。其核心特性包括:通过声明式格式实现安全优先的设计、对 LLM 友好的流式传输,以及自愈能力——无效的生成内容会在触达用户之前被修正,而这一切都在单一界面内完成。

目录 · 6 节

查看原文
cover-without-title

智能体与用户的交互正从文本交流发展为丰富的用户界面。直到最近,大多数对话还都是这样的:Agent-User Interactions are now evolving from text exchanges to rich UIs. Until recently, most conversations looked like this:

用户:“帮我找一个三月份去巴厘岛的度假套餐。”智能体:(用文字介绍六个套餐,每个都包含日期、酒店、航班和价格)用户:“那个住五晚、含早餐的。”智能体:“这是链接。你可以在旅行社的网站上预订。”User: "Find me a holiday package to Bali in March."
Agent: (six packages in prose, each with dates, hotel, flights, price)
User: "The five-night one with breakfast."
Agent: "Here's the link. You can book it on the operator's site."

智能体可以规划行程,但返回的内容全是一大堆文字。在对话中,他们没有标准方式来呈现可供选择的套餐列表、目的地地图或日期选择器,带你完成后续预订流程。Agents could plan the trip, but everything came back as walls of text. They had no standard way to render a selectable list of packages, a map of the destinations, or a date picker to carry you through the rest of the booking, inside the conversation itself.

生成式 UI 是一层技术,让智能体能够在运行时构建界面,并根据每个请求的需求塑造界面,为用户带来丰富的交互体验。要实现这一点,需要两部分:一种描述 UI 的方式,以及一个将智能体连接到应用并渲染 UI 的智能体技术栈。Generative UI is the layer that lets agents build interfaces at runtime, shaped by what each request needs - giving users a rich, interactive experience. Implementing that takes two pieces: a way to describe the UI and an agentic stack that connects your agent to your application and renders that UI.

  • A2UI(Agent-to-UI)是 Google 推出的、与框架无关的生成式 UI 开放标准。智能体以数据的形式描述界面,应用则使用已有组件将其渲染出来。它在设计上不依赖特定传输方式。
    A2UI (Agent-to-UI) is Google's framework-agnostic open standard for Generative UI. The agent describes an interface as data, and your application draws it with the components you already have. It's transport-agnostic by design.
  • CopilotKit 提供智能体集成技术栈,可与“LangChain”“AWS Strands”“Google ADK”等智能体框架集成,用于构建面向用户的智能体应用。它提供了一套基于 A2UI 协议构建丰富应用的工具包,涵盖聊天界面和运行时,并支持在 React 和 Angular 中使用 A2UI 渲染器。CopilotKit 还为 Vue 和 Slack 提供自定义 A2UI 渲染器。
    CopilotKit provides the agent-integration stack to integrate with agent frameworks like “LangChain”, “AWS Strands”, “Google ADK”, etc. for building user-facing agentic apps. It provides a toolkit for building rich applications with A2UI protocol, including the chat surface, runtime, and leverages A2UI renderer, across React and Angular. CopilotKit also provides custom A2UI renderers for Vue and Slack.
any-framework-any-surface

什么是 A2UI?What is A2UI?

生成式 UI 涵盖多种实现方式,从使用预定义的高阶组件,到赋予 AI 智能体灵活性,由其自行决定如何构建 UI。Generative UI covers a spectrum of approaches, from using predefined higher order components, to enabling your AI agent to have the flexibility to decide how to build the UI.

在受控端,你会提前构建好每个组件,由智能体选择渲染哪个组件,以及使用什么数据。这种方式符合品牌规范,但无法根据用户意图进行深度定制和个性化。在开放端,智能体会返回一段以 HTML、JavaScript 和/或 Dart 编写的原始 UI 程序,在沙盒化的 iframe 中渲染。这样就能覆盖任何未预先规划的情况,但代价是界面可能偏离你的设计系统,而且执行的是模型编写的代码。At the controlled end, you build each component ahead of time, and the agent picks which one to render and with what data. It's brand-safe but it does not allow for deep customization and personalization based on the user’s intent. At the open end, the agent returns a raw UI program written in HTML, Javascript and/or Dart that renders inside a sandboxed iframe. That covers anything you did not plan for, at the cost of a surface that drifts from your design system and executes code a model wrote.

A2UI 涵盖了完整的生成谱系。它既适用于由 Typesafe 的 Jev 等决策模型控制的生成,也适用于可能输出 A2UI JSON 消息的开放式代码生成。其中最受欢迎的是声明式模式:智能体通过组合预先声明的组件和函数来构建界面。A2UI 是用于声明 UI 意图、与框架无关的标准,因此本地或远程智能体都可以使用通用语言,根据你现有的组件目录生成 UI。A2UI works through the entire spectrum. It participates in controlled generation with decision models like Typesafe’s Jev and also open-ended code generation that may output A2UI JSON messages. The declarative mode, where agents assemble pre-declared components and functions, is the most popular. A2UI is the framework-agnostic standard for declaring UI intent, so local or remote agents can generate your UI from your existing component catalog using a common language.

  • 安全至上。A2UI 是一种声明式数据格式,而非可执行代码。客户端维护着一份可信组件目录,因此,代理生成的任何不在该目录中的内容,都会在显示到屏幕上之前被拦截。
    Security first. A2UI is a declarative data format rather than executable code. The client keeps a catalog of trusted components, so anything the agent invents outside that set is caught before it reaches the screen.
  • 兼容 LLM,支持流式传输。载荷是一个由小型 JSON 消息组成的扁平列表,这些消息通过 ID 相互引用,因此代理可以逐步输出,客户端则在组件到达时即时渲染。
    LLM-friendly and streaming. The payload is a flat list of small JSON messages that reference each other by ID, so the agent emits it incrementally and the client renders components as they arrive.
  • 与框架无关且可移植。同一响应可通过 React、Lit、Angular、SwiftUI、Jetpack Compose(Android)或 Flutter(多平台)进行渲染,也可通过 Vue 社区渲染器,甚至在终端中渲染。
    Framework-agnostic and portable. The same response renders through React, Lit, Angular, SwiftUI, Jetpack Compose (Android) or Flutter (multi-platform), and through community renderers for Vue, or even the terminal.

前端开发者现在可以一次性发布这些构建模块,由智能体针对每个请求将它们组合起来。Frontend developers can now ship the building blocks once, and the agent composes them for each request.

抱歉,您的浏览器不支持播放此视频。Sorry, your browser doesn't support playback for this video

基础目录提供 18 种通用原语,涵盖布局、显示、输入和容器。智能体可以根据请求的需求,使用相同的 18 种原语组合出截然不同的界面。The Basic Catalog ships 18 general-purpose primitives across layout, display, input, and containers. The agent can compose entirely different interfaces from the same 18 primitives, depending on what the request needs.

three-primitives

基础目录有意保持精简,因此大多数生产级应用都会定义自己的自定义目录。自定义组件可以是前端已经渲染的任何内容,包括一张实时地图:智能体填入坐标,同时由你的渲染器绘制路线。The Basic Catalog is deliberately sparse, so most production apps define their own custom catalog. A custom component can be anything your frontend already renders, including a live map the agent fills with coordinates while your renderer draws the route.

map-genui

A2UI 与 CopilotKit 如何协同工作How A2UI and CopilotKit work together

CopilotKit 构建于 AG-UI(Agent-User Interaction Protocol,智能体-用户交互协议)之上,支持 A2UI 负载,并为众多智能体后端提供 Agent SDK。CopilotKit is built on AG-UI (Agent-User Interaction Protocol), which supports A2UI payload and provides Agent SDKs across many agentic backends.

你的智能体会发出 A2UI 操作。AG-UI 会以类型化事件的形式将这些操作传递给客户端。用户执行任何操作时,相关值都会沿同一数据流发送回来。Your agent emits A2UI operations. AG-UI carries them to the client as typed events. When the user takes any action, the values are sent back along the same stream.

A2UI 可与任何兼容 AG-UI 的智能体配合使用。Google ADK、LangChain、Mastra 和 Strands 等框架都兼容 AG-UI,因此无论你的智能体基于哪个框架运行,设置方式都相同。A2UI works with any AG-UI compatible agent. Frameworks like Google ADK, LangChain, Mastra and Strands are all AG-UI compatible, so the setup is identical whichever one your agent runs on.

cpk-a2ui-agui

在你的应用中设置 A2UISetting up A2UI in your app

设置归结为两件事:将你的智能体连接到 CopilotKit,并定义智能体可以使用哪些组件。Setup comes down to two things: connecting your agent to CopilotKit, and defining which components the agent is allowed to use.

以 Google ADK 为例,ag_ui_adk 包会封装任意 ADK 智能体,并通过 FastAPI 将其作为 AG-UI 端点提供服务:Using Google ADK as the example, the ag_ui_adk package wraps any ADK agent and serves it as an AG-UI endpoint on 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="/")
Python

在应用端,你需要在 /api/copilotkit 将该端点注册到 CopilotKit 运行时中。这只需几行标准配置,Google ADK 快速入门中对此有介绍,而且无需进行任何 A2UI 专属配置。On the app side, you register that endpoint with the CopilotKit runtime at /api/copilotkit. It's a few lines of standard setup, covered in the Google ADK quickstart, and it needs nothing A2UI-specific.

A2UI 本身在客户端启用,你的组件也已经位于客户端。定义代理可以渲染的内容,将每个定义映射到一个渲染器,然后把目录传递给 CopilotKit 提供程序。A2UI itself turns on from the client, where your components already are. Define what the agent is allowed to draw, map each definition to a renderer, and pass the catalog to the 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

描述会写入代理的提示词中,让模型知道何时应使用 FlightCard,而不是通用卡片。Zod schema 会验证它返回的 props。The description goes into the agent's prompt, so the model knows when to reach for FlightCard instead of a generic card. The Zod schema validates the props it sends back.

A2UI 配置可以提前在服务器上设置,也可以动态创建,并随请求从客户端发送到服务器。上面的 ADK 代码使用了动态配置,因此调用了 generate_a2ui,却没有对其进行定义。文档涵盖了这两种方式。The A2UI configuration can be set up ahead of time on the server, or it can be created dynamically, shipped from the client to the server with the request. The ADK code above used dynamic configuration which is why it used generate_a2ui without defining it. The docs cover both approaches.

这就是 CopilotKit 的接入方式。你也可以直接通过 @ag-ui/client 消费事件流,并将 A2UI 操作交给任何兼容的渲染器:@a2ui/react,或 Flutter、Lit、Angular 的对应实现。That’s the CopilotKit path. You can also consume the event stream directly with @ag-ui/client and hand the A2UI operations to any compliant renderer: @a2ui/react, or the Flutter, Lit, or Angular equivalent.

抱歉,您的浏览器不支持播放此视频。Sorry, your browser doesn't support playback for this video

构建双向 A2UI 界面Building bi-directional A2UI surfaces

大多数由智能体生成的 UI 都是一次性的。智能体画出某样东西,你读完后,只要有任何变化,它就立刻过时了。Most agent-generated UI is one-shot. The agent draws something, you read it, and it goes stale the moment anything changes.

A2UI 界面是双向的,组件也具有响应性,因此可以实现多步骤流程。用户在界面上执行的任何操作(选择日期、挑选航班、填写乘客信息)都会沿着同一数据流传回,随后智能体会根据这些值重新发出界面。A2UI surfaces are bi-directional and the components are reactive, which makes multi-step flows possible. Any action the user takes on the interface (picking dates, choosing a flight, entering passenger details) travels back along the same stream, and the agent re-emits the surface from there using those values.

下面是一个端到端预订流程的高层架构示例:AG-UI 代理运行在 Cloud Run 上,并向 CopilotKit 前端流式传输 A2UI 界面。Here is a high-level architecture example of an end-to-end booking flow, with an AG-UI agent on Cloud Run streaming A2UI surfaces to a CopilotKit frontend.

bi-directional surfaces

有两点让往返流程得以实现:绑定到数据路径的输入控件,以及一个携带操作的按钮,该操作指定要发送回去的路径。Two things make the round trip work: inputs bound to a data path, and a button carrying an action that names which paths to send back.

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

验证在客户端运行,因此无效的电子邮件地址会直接显示行内错误,而不会调用模型。只有点击按钮后,内容才会发送给代理。Validation runs on the client, so a bad email shows an error inline without a model call. Nothing reaches the agent until the button fires.

然后,客户端发送绑定的值,代理再针对同一个 surfaceId 重新发出内容。这样,整个流程就都运行在同一个界面上:航班搜索、搜索结果、乘客信息和确认。Then the client sends the bound values, and the agent re-emits against the same surfaceId. That is how the whole flow lives on one surface: flight search, results, passenger details, and confirmation.

抱歉,您的浏览器不支持播放此视频。Sorry, your browser doesn't support playback for this video

相较于 AG-UI,运行 A2UI 的优势Benefits of running A2UI over AG-UI

每个 AG-UI 集成都能享有这些优势,因此你无需自行构建:Every AG-UI integration inherets these benefits, so you don't have to build them yourself:

  • 最简的服务端配置:目录会在设置时发送给代理,因此只需在客户端注册即可。
    Minimal server-side setup: the catalog reaches the agent on setup, so registering it on the client is all it takes.
  • 由专用子代理生成:目录和协议规则不会占用主代理的上下文窗口,子代理生成内容时,界面会将其流式传输给客户端。
    Generation in a dedicated sub-agent: the catalog and protocol rules stay out of your main agent's context window, and the surface streams to the client as the sub-agent produces it.
  • 自我修复输出:系统会捕获无效生成结果,并将具体错误反馈回去进行修正,因此有问题的内容不会显示在屏幕上。
    Self-healing output: invalid generations are caught and the specific errors go back for a correction, so nothing broken reaches the screen.
  • 优雅失败:重试次数耗尽时,界面会显示一条简短消息,对话也会继续,而不会陷入错误状态。
    Graceful failure: when retries are exhausted, the surface resolves to a short message and the conversation continues instead of dying in an error state.


开始使用Get Started

创建一个完整的 A2UI + CopilotKit 应用程序。此操作会创建一个集成了 Copilotkit Agent 的 A2UI 入门应用程序。Create a complete A2UI + CopilotKit application. This creates a starter A2UI application with Copilotkit Agent integration.

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

CopilotKit Dojo 提供可运行的 A2UI 演示:固定的服务器端 schema、针对自定义目录的动态 schema,以及一个错误恢复示例,其中无效的首次渲染会修复为有效渲染。The CopilotKit Dojo has runnable A2UI demos: fixed server-side schema, dynamic schema against a custom catalog, and an error-recovery example where an invalid first render heals into a valid one.

探索如何使用 CopilotKit 构建生成式 UI 代理,或深入阅读 A2UI 文档,了解如何将 A2UI 集成到你选择的任意框架中。Explore how to build Generative UI Agents with CopilotKit, or dive into A2UI documentation to learn how to integrate A2UI with any framework of your choice.

值得记下

  1. 智能体与用户的交互如今正从文本交流演进为丰富的 UI。
  2. A2UI 是一种声明式数据格式,而非可执行代码。
  3. 客户端维护着一份受信任组件的目录,因此智能体在该集合之外编造的任何内容都会在到达屏幕之前被拦截。
  4. A2UI 界面是双向且响应式的,这使得多步骤流程成为可能。

← 回到本期 · 第 14 条