🎯 核心要点(TL;DR)
- A2UI(Agent to UI)是一种声明式协议,使 AI 代理能够使用 JSON 消息生成丰富的交互式界面
- A2A 协议 (Agent to Agent)为多代理系统提供安全、标准化的通信,内置 A2UI 支持
- A2UI 协议将 UI 结构与应用程序状态分离,实现响应式更新和跨平台渲染
- A2UI 可与任何传输机制配合使用,包括 A2A 协议、AG UI、SSE 和 WebSockets
- 使用 A2UI 和 A2A 协议构建可在 Web、移动和桌面平台上运行的、具有原生感觉的安全 UI
目录
- [什么是 A2UI 和 A2A 协议?](#什么是 A2UI 和 A2A 协议?)
- [理解 A2UI 架构](#理解 A2UI 架构)
- 设置客户端应用
- [构建 A2UI 代理](#构建 A2UI 代理)
- [实现 A2UI 渲染器](#实现 A2UI 渲染器)
- [使用 A2A 协议传输](#使用 A2A 协议传输)
- 创建自定义组件
- [A2UI 应用的主题和样式](#A2UI 应用的主题和样式)
- [A2UI 开发最佳实践](#A2UI 开发最佳实践)
- [关于 A2UI 和 A2A 协议的常见问题](#关于 A2UI 和 A2A 协议的常见问题)
- 结论和下一步
什么是 A2UI 和 A2A 协议?
理解 A2UI 协议
A2UI (Agent to UI)是一种专门为代理驱动界面设计的声明式 UI 协议。A2UI 协议 使 AI 代理能够生成丰富的交互式用户界面,这些界面可以在多个平台(Web、移动和桌面)上原生渲染,而无需执行任意代码。与依赖纯文本交互或嵌入式 HTML/JavaScript 的传统方法不同,A2UI 以结构化 JSON 数据的形式传输 UI 描述。
A2UI 协议 解决了多代理系统中的一个关键挑战:如何使远程代理能够生成感觉原生、安全且与应用程序集成的用户界面。当代理在不同服务器和组织之间运行时,它们无法直接操作应用程序的 UI------它们必须通过消息进行通信。A2UI 协议为代理提供了一种标准化的方式来描述 UI 组件,客户端可以使用其原生框架进行渲染。
理解 A2A 协议
A2A 协议 (Agent to Agent)是一种安全、标准化的代理通信协议。A2A 协议 提供内置安全性、身份验证以及多种消息格式和传输协议的绑定。在构建多代理系统时,A2A 协议使代理能够跨信任边界安全通信。
A2A 协议 包含一个扩展,可轻松集成 A2UI 。这意味着当您使用 A2A 协议 进行代理通信时,A2UI 支持几乎是自动的。A2UI 和 A2A 协议的结合为构建安全、可互操作的代理驱动应用程序提供了强大的基础。
A2A 协议的关键特性:
- 用于代理通信的标准化消息格式
- 内置安全性和身份验证机制
- 支持多种传输协议(HTTP、WebSockets、gRPC)
- 扩展实现无缝的 A2UI 消息传输
- 专为企业网格和多代理编排而设计
当开发者为代理基础设施选择 A2A 协议 时,他们通过扩展自动获得 A2UI 支持。这使得 A2A 协议 成为企业环境中 A2UI 应用的推荐传输选项。
A2UI 和 A2A 协议如何协同工作
A2UI 协议 和 A2A 协议设计为无缝协同工作:
- A2A 协议处理安全的代理到代理通信
- A2UI 协议 消息通过 A2A 协议传输
- 代理生成描述 UI 组件的 A2UI JSON 消息
- 客户端通过 A2A 协议 接收 A2UI 消息并原生渲染它们
这种集成使 A2UI 和 A2A 协议成为安全性和互操作性至关重要的企业网格和多代理系统的理想选择。
💡 关键洞察
A2UI 协议 是传输无关的,这意味着 A2UI 消息可以通过 A2A 协议 、AG UI、SSE、WebSockets 或任何其他传输机制传输。A2A 协议 为多代理系统提供了内置安全性和 A2UI 支持的强大解决方案。
理解 A2UI 架构
三层架构
A2UI 协议将关注点分离为三个不同的层:
- UI 结构层 - 通过 A2UI 协议 中的
surfaceUpdate消息定义组件 - 应用程序状态层 - 通过 A2UI 协议 中的
dataModelUpdate消息定义数据模型 - 客户端渲染层 - A2UI 消息的原生组件映射和渲染
这种架构分离实现了:
- 数据绑定 - 在 A2UI 中无需组件重新生成的响应式更新
- 可重用模板 - 一个模板,多个数据实例(使用 A2UI 协议)
- 清晰的架构 - A2UI 系统中代理和客户端之间的清晰边界
A2UI 协议中的核心消息类型
A2UI 协议定义了四种主要消息类型:
| 消息类型 | 目的 | 示例用例 |
|---|---|---|
surfaceUpdate |
定义或更新 UI 组件 | 创建包含输入字段的表单 |
dataModelUpdate |
更新应用程序状态 | 填充表单值或更新显示的数据 |
beginRendering |
向客户端发出渲染信号 | 在组件准备就绪后触发 UI 显示 |
deleteSurface |
删除 UI 表面 | 工作流完成后清理 |
邻接表模型
与传统的嵌套 JSON 树不同,A2UI 使用邻接表模型 ------组件存储为带有 ID 引用的平面列表。这种设计使 A2UI 协议特别适合 LLM:
传统嵌套方法:
- 需要一次性完美嵌套
- 难以更新深度嵌套的组件
- 难以增量流式传输
A2UI 邻接表:
- ✅ 平面结构,易于 LLM 生成------这就是为什么 A2UI 协议如此适合 LLM
- ✅ 增量发送组件------A2UI 支持渐进式渲染
- ✅ 通过 ID 更新任何组件------A2UI 协议实现高效更新
- ✅ 结构和数据的清晰分离------A2UI 架构促进清晰设计
示例:A2UI 组件定义
json
{
"surfaceUpdate": {
"surfaceId": "booking",
"components": [
{"id": "root", "component": {"Column": {"children": {"explicitList": ["greeting", "buttons"]}}}},
{"id": "greeting", "component": {"Text": {"text": {"literalString": "Hello"}}}},
{"id": "buttons", "component": {"Row": {"children": {"explicitList": ["cancel-btn", "ok-btn"]}}}},
{"id": "cancel-btn", "component": {"Button": {"child": "cancel-text", "action": {"name": "cancel"}}}}
]
}
}
A2UI 协议中的数据绑定
数据绑定是 A2UI 协议 的核心功能。A2UI 使用 JSON Pointer 路径(RFC 6901)将 UI 结构与应用程序状态分离。这种分离是 A2UI 协议 实现响应式更新的基础。当将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展确保 A2UI 数据绑定更新通过 A2A 协议传输高效传输。
字面值(固定):
json
{"text": {"literalString": "Welcome"}}
数据绑定值(响应式):
json
{"text": {"path": "/user/name"}}
当 /user/name 更改时,A2UI 组件会自动更新------无需组件重新生成。这种响应式绑定是 A2UI 协议 的核心优势,展示了为什么 A2UI 对动态、数据驱动的界面如此高效。
设置客户端应用
选择渲染器
A2UI 协议支持跨不同平台的多种渲染器:
| 渲染器 | 平台 | 状态 |
|---|---|---|
| Lit(Web 组件) | Web | ✅ 稳定 |
| Angular | Web | ✅ 稳定 |
| Flutter(GenUI SDK) | 移动/桌面/Web | ✅ 稳定 |
| React | Web | 🚧 2026 年 Q1 推出 |
| SwiftUI | iOS/macOS | 🚧 计划 2026 年 Q2 |
| Jetpack Compose | Android | 🚧 计划 2026 年 Q2 |
Web 组件(Lit)设置
⚠️ 注意
Lit 客户端库尚未发布到 NPM。请在未来几天内查看。
Lit 渲染器使用 Web 组件来渲染 A2UI 消息:
bash
npm install @a2ui/web-lib lit @lit-labs/signals
Lit 渲染器提供:
- 消息处理器 :管理 A2UI 状态并处理传入的 A2UI 消息
<a2ui-surface>组件 :在应用中渲染 A2UI 表面- Lit Signals :为自动 A2UI UI 更新提供响应式状态管理
Lit 渲染器可与包括 A2A 协议 、SSE 和 WebSockets 在内的各种传输机制配合使用,用于 A2UI 消息传递。
查看工作示例: Lit shell 示例
Angular 设置
⚠️ 注意
Angular 客户端库尚未发布到 NPM。请在未来几天内查看。
Angular 渲染器提供与 Angular 的依赖注入和变更检测的完整集成:
bash
npm install @a2ui/angular @a2ui/web-lib
Angular 渲染器提供:
provideA2UI()函数 :在应用配置中配置 A2UISurface组件 :在 Angular 应用中渲染 A2UI 表面MessageProcessor服务 :处理传入的 A2UI 消息
Angular 渲染器支持包括用于安全代理通信的 A2A 协议在内的各种传输机制。
查看工作示例: Angular 餐厅示例
Flutter(GenUI SDK)设置
Flutter 使用提供原生 A2UI 渲染的 GenUI SDK:
bash
flutter pub add flutter_genui
GenUI SDK 支持包括用于 A2UI 消息传输的 A2A 协议在内的各种传输机制。
连接到代理
您的客户端应用需要:
- 接收 A2UI 消息(通过传输从代理)
- 处理消息(使用消息处理器)
- 发送用户操作(返回给代理)
常见的传输选项:
- A2A 协议 :具有 A2UI 支持的标准化代理到代理通信
- 服务器发送事件(SSE) :从服务器到客户端的单向流式传输,用于 A2UI 消息
- WebSockets :用于 A2UI 应用的双向实时通信
- AG UI :具有 A2UI 渲染的全栈 React 框架
⚠️ 重要
使用 A2A 协议 时,A2UI 支持通过扩展内置,该扩展自动处理 A2UI 消息序列化和反序列化。
处理用户操作
当用户与 A2UI 组件交互(点击按钮、提交表单等)时,客户端:
- 从 A2UI 组件捕获操作事件
- 使用 A2UI 数据绑定解析操作所需的任何数据上下文
- 将操作发送给代理(通过 A2A 协议或其他传输)
- 处理代理的响应 A2UI 消息
错误处理
在 A2UI 应用中需要处理的常见错误:
- 无效的表面 ID :在 A2UI 消息流中收到
beginRendering之前引用了表面 - 无效的组件 ID :组件 ID 在 A2UI 协议的表面内必须唯一
- 无效的数据路径 :检查数据模型结构和 A2UI 数据绑定的 JSON Pointer 语法
- 架构验证失败 :验证消息格式是否匹配 A2UI 规范
将 A2A 协议 与 A2UI 一起使用时,扩展可以帮助验证 A2UI 消息并提供错误报告机制。
构建 A2UI 代理
快速概述
构建 A2UI 代理涉及:
- 理解用户意图 → 决定显示什么 UI
- 生成 A2UI JSON → 使用 LLM 结构化输出或提示
- 验证和流式传输 → 检查架构,发送给客户端
- 处理操作 → 响应用户交互
从简单代理开始
我们将使用 ADK(代理开发工具包)构建一个生成 A2UI 消息的简单代理:
bash
pip install google-adk
adk create my_agent
然后编辑 my_agent/agent.py 文件:
python
import json
from google.adk.agents.llm_agent import Agent
from google.adk.tools.tool_context import ToolContext
def get_restaurants(tool_context: ToolContext) -> str:
"""调用此工具以获取餐厅列表。"""
return json.dumps([
{
"name": "Xi'an Famous Foods",
"detail": "辛辣可口的拉面。",
"imageUrl": "http://localhost:10002/static/shrimpchowmein.jpeg",
"rating": "★★★★☆",
"infoLink": "[更多信息](https://www.xianfoods.com/)",
"address": "81 St Marks Pl, New York, NY 10003"
},
# ... 更多餐厅
])
AGENT_INSTRUCTION="""
你是一个有用的餐厅查找助手。你的目标是帮助用户使用丰富的 UI 查找和预订餐厅。
为了实现这一点,你必须遵循以下逻辑:
1. **对于查找餐厅:**
a. 你必须调用 `get_restaurants` 工具。从用户查询中提取菜系、位置和特定数量(`count`)的餐厅。
b. 收到数据后,你必须严格按照说明生成最终的 a2ui UI JSON,根据餐厅数量使用 `prompt_builder.py` 中相应的 UI 示例。"""
root_agent = Agent(
model='gemini-2.5-flash',
name="restaurant_agent",
description="一个查找餐厅并帮助预订桌位的代理。",
instruction=AGENT_INSTRUCTION,
tools=[get_restaurants],
)
不要忘记设置 GOOGLE_API_KEY 环境变量来运行此示例:
bash
echo 'GOOGLE_API_KEY="YOUR_API_KEY"' > .env
您可以使用 ADK Web 界面测试此代理:
bash
adk web
从列表中选择 my_agent,并询问有关纽约餐厅的问题。您应该在 UI 中看到餐厅列表(纯文本形式)。
生成 A2UI 消息
让 LLM 生成 A2UI 消息需要一些提示工程。A2UI 协议 设计为 LLM 友好,使代理更容易生成有效的 A2UI JSON 消息。
⚠️ 注意
这是我们仍在设计的领域。这方面的开发者体验尚未最终确定。
目前,让我们从联系人查找示例中复制 a2ui_schema.py。这是为代理获取 A2UI 架构和示例的最简单方法(可能会更改):
bash
cp samples/agent/adk/contact_lookup/a2ui_schema.py my_agent/
首先,将新导入添加到 agent.py 文件:
python
# 任何 A2UI 消息的架构。这永远不会改变。
from .a2ui_schema import A2UI_SCHEMA
现在修改代理指令以生成 A2UI 消息:
python
# 最终您可以在这里复制和粘贴一些 UI 示例,用于上下文学习中的少样本学习
RESTAURANT_UI_EXAMPLES = """
"""
# 使用 UI 指令、示例和架构构建完整提示
A2UI_AND_AGENT_INSTRUCTION = AGENT_INSTRUCTION + f"""
你的最终输出必须是 a2ui UI JSON 响应。
要生成响应,你必须遵循以下规则:
1. 你的响应必须分为两部分,由分隔符分隔:`---a2ui_JSON---`。
2. 第一部分是你的对话文本响应。
3. 第二部分是一个单独的原始 JSON 对象,它是 A2UI 消息的列表。
4. JSON 部分必须针对下面提供的 A2UI JSON 架构进行验证。
--- UI 模板规则 ---
- 如果查询是餐厅列表,请使用你已从 `get_restaurants` 工具收到的餐厅数据填充 `dataModelUpdate.contents` 数组(例如,作为 "items" 键的 `valueMap`)。
- 如果餐厅数量为 5 个或更少,你必须使用 `SINGLE_COLUMN_LIST_EXAMPLE` 模板。
- 如果餐厅数量超过 5 个,你必须使用 `TWO_COLUMN_LIST_EXAMPLE` 模板。
- 如果查询是预订餐厅(例如,"USER_WANTS_TO_BOOK..."),你必须使用 `BOOKING_FORM_EXAMPLE` 模板。
- 如果查询是预订提交(例如,"用户提交了预订..."),你必须使用 `CONFIRMATION_EXAMPLE` 模板。
{RESTAURANT_UI_EXAMPLES}
---开始 A2UI JSON 架构---
{A2UI_SCHEMA}
---结束 A2UI JSON 架构---
"""
root_agent = Agent(
model='gemini-2.5-flash',
name="restaurant_agent",
description="一个查找餐厅并帮助预订桌位的代理。",
instruction=A2UI_AND_AGENT_INSTRUCTION,
tools=[get_restaurants],
)
理解输出
您的代理将输出文本和 A2UI 消息的 JSON 列表 。A2UI 协议 以 LLM 易于生成的结构化格式定义这些消息。A2UI_SCHEMA 定义了有效操作,例如:
render(使用 A2UI 协议显示 UI)update(使用 A2UI 消息更改现有 UI 中的数据)
因为输出是遵循 A2UI 协议的结构化 JSON,您可以在将其发送给客户端之前解析和验证它:
python
# 1. 解析 JSON
# 警告:将输出解析为 JSON 是一个脆弱的实现,对文档很有用。
# LLM 经常在 JSON 输出周围放置 Markdown 围栏,并可能犯其他错误。
# 依赖框架为您解析 JSON。
parsed_json_data = json.loads(json_string_cleaned)
# 2. 针对 A2UI_SCHEMA 进行验证
# 这确保 LLM 生成了有效的 A2UI 命令
jsonschema.validate(
instance=parsed_json_data, schema=self.a2ui_schema_object
)
⚠️ 重要
将 LLM 输出解析为 JSON 可能很脆弱。LLM 经常在 JSON 输出周围放置 Markdown 围栏,并可能犯其他错误。建议依赖框架为您解析 JSON。
通过针对 A2UI_SCHEMA 验证输出,您可以确保客户端永远不会收到格式错误的 A2UI 指令。A2UI 协议 验证确保所有 A2UI 消息符合规范。将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展可以执行额外验证以确保 A2UI 消息完整性。
实现 A2UI 渲染器
核心协议实现清单
符合规范的 A2UI 渲染器必须实现这些系统,以成功解析服务器流、管理状态并处理用户交互。
消息处理和状态管理
- JSONL 流解析:实现一个解析器,可以逐行读取流式响应,将每一行解码为不同的 JSON 对象。
- 消息分发器 :创建一个分发器来识别消息类型(
beginRendering、surfaceUpdate、dataModelUpdate、deleteSurface)并将其路由到正确的处理器。 - 表面管理 :
- 实现一个数据结构来管理多个 UI 表面,每个表面由其
surfaceId键控。 - 处理
surfaceUpdate:在指定表面的组件缓冲区中添加或更新组件。 - 处理
deleteSurface:删除指定表面及其所有关联数据和组件。
- 实现一个数据结构来管理多个 UI 表面,每个表面由其
- 组件缓冲(邻接表) :
- 对于每个表面,维护一个组件缓冲区(例如,
Map<String, Component>)以按id存储所有组件定义。 - 能够通过在容器组件(
children.explicitList、child、contentChild等)中解析id引用来在渲染时重建 UI 树。
- 对于每个表面,维护一个组件缓冲区(例如,
- 数据模型存储 :
- 对于每个表面,维护一个单独的数据模型存储(例如,JSON 对象或
Map<String, any>)。 - 处理
dataModelUpdate:在指定的path更新数据模型。contents将采用邻接表格式(例如,[{ "key": "name", "valueString": "Bob" }])。
- 对于每个表面,维护一个单独的数据模型存储(例如,JSON 对象或
渲染逻辑
- 渐进式渲染控制 :
- 缓冲所有传入的
surfaceUpdate和dataModelUpdate消息,不立即渲染。 - 处理
beginRendering:此消息作为执行表面初始渲染并设置根组件 ID 的显式信号。- 从指定的
root组件 ID 开始渲染。 - 如果提供了
catalogId,确保使用相应的组件目录(如果省略,则默认为标准目录)。 - 应用此消息中提供的任何全局
styles(例如,font、primaryColor)。
- 从指定的
- 缓冲所有传入的
- 数据绑定解析 :
- 实现组件属性中找到的
BoundValue对象的解析器。 - 如果仅存在
literal*值(literalString、literalNumber等),直接使用它。 - 如果仅存在
path,针对表面的数据模型解析它。 - 如果同时存在
path和literal*,首先使用字面值更新path处的数据模型,然后将组件属性绑定到该path。
- 实现组件属性中找到的
- 动态列表渲染 :
- 对于具有
children.template的容器,迭代在template.dataBinding找到的数据列表(它解析为数据模型中的列表)。 - 对于数据列表中的每个项目,渲染由
template.componentId指定的组件,使项目的数据可用于模板内的相对数据绑定。
- 对于具有
客户端到服务器通信
- 事件处理 :
- 当用户与定义了
action的组件交互时,构建userAction负载。 - 针对数据模型解析
action.context内的所有数据绑定。 - 将完整的
userAction对象发送到服务器的事件处理端点(通过 A2A 协议或其他传输)。
- 当用户与定义了
- 客户端能力报告 :
- 在发送到服务器的每个 A2A 消息中(作为元数据的一部分),包含一个
a2uiClientCapabilities对象。 - 此对象应通过
supportedCatalogIds声明客户端支持的组件目录(例如,包括标准 0.8 目录的 URI)。 - 可选地,如果服务器支持,为自定义的、即时的组件定义提供
inlineCatalogs。
- 在发送到服务器的每个 A2A 消息中(作为元数据的一部分),包含一个
- 错误报告 :实现一种机制,向服务器发送
error消息以报告任何客户端错误(例如,数据绑定失败、未知组件类型)。
标准组件目录清单
为了确保跨平台的一致用户体验,A2UI 定义了一组标准组件。您的客户端应该将这些抽象定义映射到其相应的原生 UI 小部件。
基本内容:
- Text :渲染文本内容。必须支持
text上的数据绑定和用于样式的usageHint(h1-h5、body、caption)。 - Image :从 URL 渲染图像。必须支持
fit(cover、contain 等)和usageHint(avatar、hero 等)属性。 - Icon:从目录中指定的标准集渲染预定义图标。
- Video:为给定 URL 渲染视频播放器。
- AudioPlayer:为给定 URL 渲染音频播放器,可选地带有描述。
- Divider :渲染视觉分隔符,支持
horizontal和vertical轴。
布局和容器:
- Row :水平排列子元素。必须支持
distribution(justify-content)和alignment(align-items)。子元素可以具有weight属性来控制 flex-grow 行为。 - Column :垂直排列子元素。必须支持
distribution和alignment。子元素可以具有weight属性来控制 flex-grow 行为。 - List :渲染可滚动项目列表。必须支持
direction(horizontal/vertical)和alignment。 - Card :一个容器,在视觉上分组其子内容,通常带有边框、圆角和/或阴影。具有单个
child。 - Tabs :显示一组标签的容器。包括
tabItems,其中每个项目都有一个title和一个child。 - Modal :出现在主内容顶部的对话框。它由
entryPointChild(例如按钮)触发,并在激活时显示contentChild。
交互式和输入组件:
- Button :触发
userAction的可点击元素。必须能够包含child组件(通常是 Text 或 Icon),并且可以根据primary布尔值改变样式。 - CheckBox:可以切换的复选框,反映布尔值。
- TextField :文本输入字段。必须支持
label、text(值)、textFieldType(shortText、longText、number、obscured、date)和validationRegexp。 - DateTimeInput :用于选择日期和/或时间的专用输入。必须支持
enableDate和enableTime。 - MultipleChoice :用于从列表(
options)中选择一个或多个选项的组件。必须支持maxAllowedSelections并将selections绑定到列表或单个值。 - Slider :用于从定义范围(
minValue、maxValue)中选择数值(value)的滑块。
使用 A2A 协议传输
理解 A2A 协议集成
A2A 协议 提供安全、标准化的代理通信,内置 A2UI 支持。当您使用 A2A 协议 进行代理通信时,A2UI 支持几乎是自动的。A2A 协议 专门设计为与 A2UI 无缝协作,使其成为生产环境中 A2UI 应用的首选传输机制。
将 A2A 协议与 A2UI 一起使用的好处:
- A2A 协议处理安全代理到代理通信的所有复杂性
- A2A 协议 扩展自动序列化和反序列化 A2UI 消息
- A2A 协议 为 A2UI 消息交换提供身份验证和授权
- A2A 协议 支持多种传输层,都与 A2UI 兼容
- A2A 协议 使编排代理能够协调跨多个代理的 A2UI 生成
- 内置安全性和身份验证
- 多种消息格式、身份验证和传输协议的绑定
- 关注点清晰分离
- 自动 A2UI 消息序列化和反序列化
A2UI 的 A2A 协议扩展
A2A 协议 包含一个扩展,可轻松集成 A2UI 。此 A2A 协议 扩展使 A2UI 集成无缝且自动。A2A 协议扩展处理:
- A2UI 消息在 A2A 协议格式中的序列化
- A2UI 消息从 A2A 协议消息的反序列化
- 通过 A2A 协议元数据报告客户端能力
- 通过 A2A 协议传输转发用户操作
- A2A 协议 消息流中的 A2UI 消息验证
- A2A 协议 传输中 A2UI 消息的错误处理
A2UI 的 A2A 协议 扩展设计为对开发者透明。当您使用 A2A 协议 进行代理通信时,A2A 协议 扩展自动处理所有 A2UI 消息格式化和传输。这使得 A2A 协议 成为 A2UI 应用的理想传输。
使用 A2UI 设置 A2A 协议
使用 A2A 协议时,您需要:
- 配置 A2A 协议 :设置 A2A 协议 身份验证和传输。A2A 协议 配置确定 A2UI 消息如何在代理和客户端之间传输。
- 启用 A2UI 扩展 :A2UI 的 A2A 协议 扩展应该自动可用。此 A2A 协议 扩展处理 A2UI 消息序列化和反序列化。
- 报告客户端能力 :在 A2A 协议 元数据中包含
a2uiClientCapabilities。这告诉使用 A2A 协议 的代理支持哪些 A2UI 组件。 - 处理 A2UI 消息 :处理通过 A2A 协议 传输接收的 A2UI 消息。A2A 协议 确保 A2UI 消息安全可靠地传递。
A2UI 的 A2A 协议 设置很简单,因为 A2A 协议 扩展处理了大部分复杂性。将 A2A 协议 与 A2UI 一起使用的开发者受益于 A2A 协议提供的自动消息处理、安全性和身份验证。
A2A 协议中的客户端能力
在发送到服务器的每个 A2A 消息中(作为元数据的一部分),包含一个 a2uiClientCapabilities 对象:
json
{
"a2uiClientCapabilities": {
"supportedCatalogIds": [
"https://a2ui.dev/catalog/standard/0.8"
],
"inlineCatalogs": []
}
}
这告诉代理您的客户端支持哪些 A2UI 组件目录,使代理能够生成适当的 A2UI 消息。A2A 协议 元数据系统使向使用 A2A 协议 进行通信的代理传达 A2UI 能力变得容易。
A2A 协议如何处理 A2UI 能力:
- A2A 协议 元数据在每个消息中包含
a2uiClientCapabilities - 使用 A2A 协议 的代理可以自动发现 A2UI 支持
- A2A 协议 确保 A2UI 能力信息始终可用
- A2A 协议 扩展在消息传输之前验证 A2UI 能力
✅ 最佳实践
始终在您的 A2A 协议 消息中包含
a2uiClientCapabilities。这确保代理知道哪些 A2UI 组件可用,并可以生成适当的界面。
创建自定义组件
为什么需要自定义目录?
A2UI 标准目录提供常见的 UI 元素(按钮、文本字段等),但您的应用可能需要专门的组件:
- 领域特定小部件:股票行情、医疗图表、CAD 查看器
- 第三方集成:Google Maps、支付表单、聊天小部件
- 品牌特定组件:自定义日期选择器、产品卡片、仪表板
自定义目录是可以包含以下内容的组件集合:
- 标准 A2UI 组件(Text、Button、TextField 等)
- 您的自定义组件(GoogleMap、StockTicker 等)
- 第三方组件
您向客户端应用注册整个目录,而不是单个组件。这允许代理和客户端就共享的扩展组件集达成一致,同时保持安全性和类型安全。
自定义目录如何工作
- 客户端定义目录 :您创建一个目录定义,列出 A2UI 应用的标准和自定义组件。
- 客户端注册目录 :您将目录(及其组件实现)注册到支持 A2UI 协议的客户端应用。
- 客户端宣布支持 :客户端通知代理它支持哪些目录(通过 A2A 协议 或其他传输)。使用 A2A 协议 时,A2A 协议 元数据自动包含 A2UI 目录信息。A2A 协议 扩展无缝处理 A2UI 目录宣布。
- 代理选择目录 :代理为给定的 A2UI 表面选择目录。使用 A2A 协议 的代理可以通过 A2A 协议 元数据发现可用的 A2UI 目录。
- 代理生成 UI :代理使用该 A2UI 目录中的组件按名称生成
surfaceUpdate消息。使用 A2A 协议 时,A2A 协议 扩展确保 A2UI 消息引用有效的目录组件。
定义自定义目录
Web(Lit / Angular):
- 如何定义包含标准和自定义组件的目录
- 如何将目录注册到 A2UI 客户端
- 如何实现自定义组件类
Flutter:
- 如何使用 GenUI 定义自定义目录
- 如何注册自定义组件渲染器
查看工作示例:
代理端:使用自定义目录中的组件
一旦在客户端注册了目录,代理就可以在 A2UI 应用的 surfaceUpdate 消息中使用其中的组件。代理通过 beginRendering 消息中的 catalogId 指定要使用的目录。当代理使用 A2A 协议 进行通信时,A2A 协议 扩展自动验证客户端支持 A2UI 目录 ID。A2A 协议 确保 A2UI 消息引用有效的自定义目录,A2A 协议 扩展处理 A2UI 组件的目录解析。
数据绑定和操作
自定义组件支持与标准 A2UI 组件相同的数据绑定和操作机制:
- 数据绑定 :自定义 A2UI 组件可以使用 A2UI 协议中定义的 JSON Pointer 语法将属性绑定到数据模型路径
- 操作 :自定义 A2UI 组件可以发出代理接收和处理的操作(通过 A2A 协议 或其他传输)。使用 A2A 协议 时,A2A 协议 扩展自动格式化 A2UI 用户操作以进行传输。A2A 协议 确保来自自定义组件的 A2UI 操作安全地传递给代理。
安全考虑
创建自定义目录和组件时:
- 允许列表组件:仅在目录中注册您信任的组件
- 验证属性:始终验证来自代理消息的组件属性
- 清理用户输入:如果组件接受用户输入,在处理之前清理它
- 限制 API 访问:不要向自定义组件公开敏感 API 或凭据
A2UI 应用的主题和样式
A2UI 样式哲学
A2UI 遵循客户端控制的样式方法:
- 代理描述显示什么(组件和结构)
- 客户端决定外观如何(颜色、字体、间距)
这确保了:
- ✅ 品牌一致性:所有 UI 都匹配应用的设计系统
- ✅ 安全性:代理无法注入任意 CSS 或样式
- ✅ 可访问性:您控制对比度、焦点状态和 ARIA 属性
- ✅ 平台原生感觉:Web 应用看起来像 Web,移动应用看起来像移动应用
样式层
A2UI 样式在层中工作:
1. 语义提示(代理提供提示,例如,usageHint: 'h1')
↓
2. 主题配置(您配置颜色、字体、间距)
↓
3. 组件覆盖(您为特定组件自定义 CSS/样式)
↓
4. 渲染输出(原生平台小部件)
第 1 层:语义提示
代理提供语义提示(不是视觉样式)来指导客户端渲染:
json
{
"id": "title",
"component": {
"Text": {
"text": {"literalString": "Welcome"},
"usageHint": "h1"
}
}
}
常见的 usageHint 值:
- Text:
h1、h2、h3、h4、h5、body、caption - 其他组件有自己的提示(请参阅组件参考)
客户端渲染器根据您的主题和设计系统将这些语义提示映射到实际的视觉样式。
第 2 层:主题配置
每个渲染器都提供一种全局配置设计系统的方法,包括:
- 颜色:主色、次色、背景、表面、错误、成功等
- 排版:字体系列、大小、粗细、行高
- 间距:基本单位和比例(xs、sm、md、lg、xl)
- 形状:边框半径值
- 高度:深度的阴影样式
查看工作示例:
第 3 层:组件覆盖
除了全局主题之外,您还可以覆盖特定组件的样式:
Web 渲染器:
- CSS 自定义属性(CSS 变量)用于细粒度控制
- 标准 CSS 选择器用于组件特定覆盖
Flutter:
- 通过
ThemeData进行小部件特定主题覆盖
常见样式功能
深色模式:
- 自动检测系统主题(
prefers-color-scheme) - 手动浅色/深色主题选择
- 自定义深色主题配置
响应式设计:
- A2UI 组件默认响应式
- 用于不同屏幕尺寸的媒体查询
- 用于组件级响应式的容器查询
- 响应式间距和排版比例
自定义字体:
- Web 字体(Google Fonts 等)
- 自托管字体
- 平台特定字体加载
最佳实践
- 使用语义提示,而不是视觉属性 :代理应提供语义提示(
usageHint),永远不要提供视觉样式。 - 保持可访问性:确保足够的颜色对比度(WCAG AA:正常文本 4.5:1,大文本 3:1),使用屏幕阅读器测试,支持键盘导航。
- 使用设计令牌:定义可重用的设计令牌(颜色、间距等),并在整个样式中引用它们以保持一致性。
- 跨平台测试:在所有目标平台(Web、移动、桌面)上测试您的主题,验证浅色和深色模式,检查不同的屏幕尺寸和方向。
A2UI 开发最佳实践
1. 组件设计
✅ 应该:
- 使用描述性 ID:
"user-profile-card"而不是"c1" - 保持层次结构浅
- 使用数据绑定将结构与内容分离
- 使用模板重用组件
❌ 不应该:
- 使用深度嵌套的组件结构
- 硬编码应该数据绑定的值
- 创建过于特定于一个用例的组件
2. 数据绑定
✅ 应该:
- 使用细粒度更新------仅更新更改的路径
- 按域组织数据(user、cart、ui)
- 在发送之前预计算显示值(货币、日期)
❌ 不应该:
- 当只有一个字段更改时更新整个数据模型
- 在同一路径中混合不相关的数据
- 发送需要格式化的原始数据
3. 消息流式传输
✅ 应该:
- 增量流式传输组件以实现渐进式渲染
- 在
dataModelUpdate之前发送surfaceUpdate - 使用
beginRendering发出 UI 准备就绪的信号
❌ 不应该:
- 在发送任何消息之前等待完整响应
- 在组件定义之前发送数据更新
- 忘记发出渲染完成信号
4. 错误处理
✅ 应该:
- 跳过格式错误的消息并继续处理
- 为网络中断显示错误状态
- 允许代理在错误后重新发送或恢复
❌ 不应该:
- 因单个格式错误的消息而崩溃
- 在重新连接期间丢失用户上下文
- 忽略来自客户端的错误反馈
5. 性能优化
✅ 应该:
- 为 16ms 渲染周期批量更新
- 使用差异仅更新更改的属性
- 进行细粒度的数据模型更新
❌ 不应该:
- 发送冗余的组件更新
- 当一个组件更改时更新整个表面
- 忽略客户端渲染能力
6. A2A 协议集成
✅ 应该:
- 始终在 A2A 协议 消息中包含
a2uiClientCapabilities - 使用 A2A 协议进行安全的多代理通信
- 利用 A2A 协议 扩展实现自动 A2UI 支持
- 正确配置 A2A 协议 身份验证以确保 A2UI 消息安全
- 监控 A2A 协议 消息流以确保 A2UI 消息正确传递
❌ 不应该:
- 忘记在 A2A 协议元数据中报告客户端能力
- 在传输 A2UI 消息时忽略 A2A 协议安全功能
- 当 A2A 协议可用时不必要地混合传输协议
- 跳过 A2UI 消息完整性的 A2A 协议验证
关于 A2UI 和 A2A 协议的常见问题
Q: 什么是 A2UI 协议?
A: A2UI 协议 是一种声明式 UI 协议,使 AI 代理能够生成丰富的交互式用户界面。代理发送描述 UI 组件的 JSON 消息,客户端使用其原生 UI 框架渲染这些消息。A2UI 专为多代理系统而设计,其中代理需要跨信任边界生成 UI,同时保持安全性和原生性能。
Q: 什么是 A2A 协议,它与 A2UI 有什么关系?
A: A2A 协议 (Agent to Agent)是一种安全、标准化的代理通信协议。A2A 协议 包含一个扩展,可轻松集成 A2UI 。当您使用 A2A 协议 进行代理通信时,A2UI 支持几乎是自动的。A2A 协议 处理安全传输、身份验证和 A2UI 消息序列化/反序列化。A2A 协议 扩展通过自动处理 A2A 协议 消息中的 A2UI 消息格式化,使 A2UI 集成无缝。当开发者为代理基础设施选择 A2A 协议 时,他们通过 A2A 协议 扩展自动获得 A2UI 支持。这使得 A2A 协议 成为企业环境中 A2UI 应用的推荐传输。
Q: A2UI 与发送 HTML 有何不同?
A: 与 HTML/JavaScript 方法不同,A2UI 协议 传输声明式组件描述,而不是可执行代码。客户端使用自己的受信任组件渲染 A2UI 消息,消除了安全风险。A2UI 还提供原生样式集成、跨平台可移植性,以及比基于 iframe 的 HTML 解决方案更好的性能。
Q: A2UI 仅适用于 Web 应用吗?
A: 不是。A2UI 专为跨平台使用而设计。相同的 A2UI 消息可以在 Web(Lit、Angular、React)、移动(Flutter、SwiftUI、Jetpack Compose)和桌面平台上渲染。这种可移植性是 A2UI 协议的核心优势。
Q: 我可以将自定义组件与 A2UI 一起使用吗?
A: 可以。A2UI 支持超出标准目录的自定义组件。客户端在其渲染器中注册自定义组件类型,代理可以将它们与标准 A2UI 组件一起使用。自定义 A2UI 组件通过成为客户端受信任目录的一部分来保持安全性。将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展自动处理自定义 A2UI 组件目录宣布。A2A 协议 确保代理通过 A2A 协议 元数据知道哪些自定义 A2UI 组件可用。
Q: A2UI 如何处理实时更新?
A: A2UI 协议 使用带有 JSON Pointer 路径的数据绑定。当应用程序状态通过 A2UI 消息中的 dataModelUpdate 更改时,绑定到这些路径的组件会自动更新,无需组件重新生成。这种响应式绑定在 A2UI 应用中实现高效的实时更新。将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展确保 A2UI 数据模型更新高效传输。A2A 协议 支持流式传输 A2UI 消息,通过 A2A 协议传输实现实时 UI 更新。
Q: A2UI 支持哪些传输协议?
A: A2UI 消息可以通过任何传输协议传输:
- A2A 协议 - 用于多代理系统(推荐用于企业使用)。A2A 协议 为 A2UI 消息传输提供最强大的解决方案。当您将 A2A 协议 与 A2UI 一起使用时,您通过 A2A 协议 扩展获得自动 A2UI 支持。A2A 协议 专门设计为与 A2UI 无缝协作,使 A2A 协议 成为生产 A2UI 应用的首选。
- AG UI - 用于 A2UI 应用的双向实时通信
- SSE(服务器发送事件) - 用于 A2UI 消息的单向流式传输
- WebSockets - 用于 A2UI 应用的全双工通信
- REST - 请求-响应(可行但尚未用于 A2UI)
对于企业 A2UI 部署,强烈推荐 A2A 协议 ,因为 A2A 协议 提供内置安全性、身份验证和 A2UI 消息处理。A2A 协议 扩展确保所有 A2UI 消息都经过正确格式化并安全传输。
Q: A2UI 是开源的吗?
A: 是的。A2UI 在 Apache 2.0 许可下开源。Google 一直是核心贡献者,该项目欢迎社区贡献。您可以在 GitHub 上找到源代码并做出贡献。A2A 协议 也是开源的,并与 A2UI 无缝协作。当您将 A2A 协议 与 A2UI 一起使用时,您可以从两个开源协议中受益。A2UI 的 A2A 协议 扩展是 A2A 协议 规范的一部分,确保 A2UI 和 A2A 协议之间的兼容性。
Q: Google 如何使用 A2UI?
A: Google 在以下生产系统中使用 A2UI:
- Opal - 为数十万用户提供服务的 AI 迷你应用平台
- Gemini Enterprise - 具有丰富 UI 的自定义业务代理
- Flutter GenUI SDK - 跨平台生成式 UI 框架
- 内部代理系统 - Google 团队之间的标准化 UI 协议
Q: 我可以在现有的 React 应用中使用 A2UI 吗?
A: 可以,有两种方式:
- AG UI / CopilotKit - 具有内置 A2UI 支持的全栈 React 框架。AG UI 可以与 A2A 协议 配合使用,用于 A2UI 消息传输。
- React 渲染器 - 原生 React 渲染器将于 2026 年 Q1 推出。React 渲染器将支持 A2UI 消息的 A2A 协议 传输,实现与 A2A 协议代理通信的无缝集成。
使用 A2UI 构建 React 应用时,您可以使用 A2A 协议 进行安全代理通信。A2A 协议 扩展确保 A2UI 消息在使用 A2A 协议传输的 React 应用中无缝工作。
Q: 是什么使 A2UI 适合 LLM?
A: A2UI 协议 使用平面邻接表模型而不是嵌套树,使 LLM 更容易增量生成。A2UI 组件由简单的 ID 标识,错误易于纠正,A2UI 格式支持渐进式渲染的流式传输。将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展支持流式传输 A2UI 消息,使 LLM 能够渐进式生成 A2UI 界面。A2A 协议 确保 A2UI 消息可以高效流式传输,使 A2UI 在与 A2A 协议结合时更加适合 LLM。
Q: 我需要将 A2A 协议与 A2UI 一起使用吗?
A: 不需要,A2UI 是传输无关的,可与任何传输机制配合使用。但是,A2A 协议 为多代理系统提供了最强大的解决方案,具有内置安全性、身份验证和 A2UI 支持。对于企业网格和跨信任边界通信,强烈推荐 A2A 协议 。A2A 协议 扩展使 A2UI 集成无缝,A2A 协议 为 A2UI 消息传输提供企业级安全性。构建生产 A2UI 应用时,A2A 协议是推荐的传输机制。
Q: A2A 协议如何增强 A2UI 安全性?
A: A2A 协议 为 A2UI 应用提供多层安全性。A2A 协议 包括内置的身份验证和授权机制,保护 A2UI 消息传输。A2A 协议 还提供消息完整性验证,确保 A2UI 消息在传输过程中不被篡改。将 A2A 协议 与 A2UI 一起使用时,开发者无需额外配置即可受益于企业级安全性。A2UI 的 A2A 协议 扩展自动将安全最佳实践应用于所有 A2UI 消息交换。
结论和下一步
A2UI 协议 和 A2A 协议 共同为构建安全、可互操作的代理驱动应用程序提供了强大的基础。A2UI 协议 使代理能够生成在平台上原生渲染的丰富交互式 UI,而 A2A 协议 为多代理系统提供安全、标准化的通信。当开发者将 A2UI 协议 与 A2A 协议 结合时,他们获得了代理驱动 UI 生成的完整解决方案。A2A 协议 扩展使 A2UI 协议 集成无缝,A2A 协议 为 A2UI 协议 消息传输提供企业级安全性。A2UI 协议 和 A2A 协议的这种组合是生产代理应用的推荐方法。
A2UI 和 A2A 协议的关键优势
- 安全性 - 使用 A2UI 协议 的声明式数据,不执行代码;使用 A2A 协议 的内置安全性。A2A 协议 为 A2UI 消息传输提供企业级安全性,A2A 协议 扩展确保 A2UI 消息在传输过程中受到保护。
- 原生性能 - 通过 A2UI 使用客户端的 UI 框架渲染。将 A2A 协议 与 A2UI 一起使用时,A2A 协议 扩展优化 A2UI 消息传递以实现性能。
- 跨平台 - 一个 A2UI 协议 ,多个平台。A2A 协议 在所有支持 A2UI 的平台上工作,使 A2A 协议 成为 A2UI 应用的通用传输。
- 适合 LLM - 使用 A2UI 针对 AI 代理生成进行优化。A2A 协议 扩展支持流式传输 A2UI 消息,使 A2UI 在与 A2A 协议结合时更加适合 LLM。
- 生产验证 - 使用 A2UI 协议 为 Google 的 Opal、Gemini Enterprise 和 Flutter GenUI 提供支持。Google 在生产中使用 A2A 协议 和 A2UI ,证明了 A2A 协议 对 A2UI 应用的可靠性。
- 企业就绪 - A2A 协议 为多代理系统提供安全、标准化的通信。A2A 协议 扩展通过为 A2UI 消息提供身份验证、授权和安全传输,使 A2UI 企业就绪。
入门
对于前端开发者:
- 选择支持 A2UI 协议的渲染器(Lit、Angular 或 Flutter GenUI)
- 为您的框架安装 A2UI 渲染器包
- 通过 A2A 协议或其他传输连接到代理消息
- 自定义样式以匹配您的品牌
对于代理开发者:
- 选择支持 A2UI 协议 的框架(Python ADK、Node.js A2A SDK)。使用 A2A 协议 SDK 时,A2UI 支持通过 A2A 协议扩展内置。
- 在 LLM 提示中包含 A2UI 架构,以生成遵循 A2UI 协议 规范的 A2UI 消息
- 使用 A2UI 协议 生成 JSONL 消息,并通过 A2A 协议 流式传输给客户端。A2A 协议 扩展自动处理 A2UI 消息序列化和传输。当您使用 A2A 协议 进行代理通信时,A2UI 消息无缝集成到 A2A 协议消息流中。
- 在发送之前验证 A2UI 消息。使用 A2A 协议 传输时,A2A 协议 扩展可以执行额外验证以确保 A2UI 消息完整性。
对于平台构建者:
- 探索 A2UI 规范以了解 A2UI 协议 详细信息以及 A2UI 如何与 A2A 协议集成
- 为 A2UI 协议 构建自定义渲染器或扩展现有渲染器。构建渲染器时,考虑 A2A 协议 集成以实现安全的 A2UI 消息传输。
- 集成 A2A 协议 以实现具有 A2UI 支持的安全代理通信。A2A 协议 扩展提供了一种在自定义平台中处理 A2UI 消息的标准方法。当您实现 A2A 协议 支持时,您通过 A2A 协议 扩展自动获得 A2UI 兼容性。
- 为开源 A2UI 社区和 A2A 协议生态系统做出贡献
资源
- 文档 :A2UI 文档
- A2A 协议 :A2A 协议文档
- GitHub :google/A2UI
- 快速入门:尝试交互式演示
- 社区:加入讨论并分享您的项目
A2UI 和 A2A 协议的未来
随着 AI 代理变得更加智能和广泛,对标准化 UI 生成协议的需求也在增长。A2UI 协议 有望成为代理驱动界面的标准,而 A2A 协议 为多代理系统提供安全通信层。A2UI 和 A2A 协议 共同实现新一代应用,其中 AI 代理无缝生成丰富的交互式 UI,在每个平台上都感觉原生。A2A 协议 扩展确保 A2UI 将继续与 A2A 协议 无缝协作,因为两个协议都在发展。A2UI 协议 和 A2A 协议的组合代表了安全、可互操作的代理驱动应用的未来。
无论您是在构建下一代 AI 驱动的应用、将代理集成到现有平台,还是创建新的代理编排系统,A2UI 和 A2A 协议 都提供了使代理驱动 UI 成为现实的协议、工具和社区。A2A 协议 扩展使 A2UI 集成自动化,A2A 协议 提供 A2UI 应用所需的企业级基础设施。当您选择 A2UI 和 A2A 协议时,您正在选择代理驱动界面的未来。
准备好使用 A2UI 和 A2A 协议构建了吗? 从快速入门指南开始,或探索组件库以查看 A2UI 的实际应用。A2UI 协议 已准备好用于生产,Google 在 A2UI 方面的成功证明了其价值。当您将 A2UI 与 A2A 协议 结合时,您将获得企业级安全性和无缝集成。A2A 协议 扩展使 A2UI 集成自动化,A2A 协议 提供 A2UI 应用所需的安全传输层。加入 A2UI 和 A2A 协议社区,立即开始构建下一代代理驱动应用。