A2UI 协议深度解析:让 AI Agent 动态生成可视化界面的新范式
一、问题:Agent 只会"说"不会"画"
传统 AI Agent 的输出方式有一个根本局限:它只会返回文本。
用户问"这个月的销售数据怎么样",Agent 返回一段 JSON 或 Markdown 文字——用户得自己去解读。哪怕 Agent 调了工具拿到了结构化数据,最终展示给用户的仍然是一坨文本。
这就像一个分析师写了一份完美的报告,但只能用电话念给你听。
Generative UI(生成式 UI) 就是解决这个问题的方向:让 Agent 不仅返回文本,还能返回可交互的界面——图表、表单、卡片、仪表盘。
2026 年,这个领域已经形成了清晰的协议生态。Google 主导的 A2UI(Agent to UI)是其中最系统化、跨平台能力最强的方案,此外还有 CopilotKit 的 AG-UI、Vercel AI SDK 的 Generative UI(streamUI)、OpenAI 的 Open-JSON-UI、以及基于 MCP 扩展的 MCP-UI。
本文从 A2UI 切入,全面解析这些协议如何让 Agent 把数据变成可视化界面。
二、A2UI:Agent 的通用 UI 语言
2.1 核心思想
A2UI 由 Google 创建,Apache 2.0 开源,CopilotKit 作为联合发布伙伴。它的核心命题是:
如何让 AI Agent 安全地跨越信任边界发送富 UI?
答案是:不让 Agent 发送可执行代码(HTML/JS/React),而是发送声明式的组件描述(JSON),由客户端用原生组件渲染。
传统方式: Agent → HTML/JS 代码 → 客户端执行 → 安全风险高
A2UI 方式: Agent → JSON 组件蓝图 → 客户端原生渲染 → 安全且跨平台这就像 Agent 说的是一种"UI 通用语言"——它描述"我要一个按钮,文字是'提交',点击时触发 submit 动作",而具体长什么样、用什么框架渲染,完全由客户端决定。
2.2 协议架构:三层分离
A2UI 的架构设计有三个关键分离:
| 层 | 职责 | 消息类型 |
|---|---|---|
| UI 结构层 | 定义组件树(按钮、卡片、列表的布局) | createSurface / updateComponents |
| 应用状态层 | 管理数据模型(组件引用的数据) | updateDataModel |
| 客户端渲染层 | 原生组件映射和渲染 | 各渲染器自行实现 |
这种分离意味着:UI 结构和数据可以独立更新。当数据变了,只需要发一条 updateDataModel 消息,绑定了该数据路径的组件会自动刷新——不需要重新生成整个 UI 树。
2.3 四种核心消息
A2UI v1.0(候选版)定义了四种消息类型,构成完整的 UI 生命周期:
// 1. 创建 Surface — 初始化一个 UI 画布
{
"createSurface": {
"surfaceId": "dashboard-1",
"root": "main-column",
"catalogId": "standard"
}
}
// 2. 更新组件 — 在 Surface 上放置/更新组件
{
"updateComponents": {
"surfaceId": "dashboard-1",
"components": [
{
"componentId": "title",
"type": "Text",
"parentId": "main-column",
"properties": {
"text": { "literalString": "销售仪表盘" },
"usageHint": "h1"
}
},
{
"componentId": "sales-chart",
"type": "Chart",
"parentId": "main-column",
"properties": {
"dataRef": "/data/sales",
"chartType": "bar"
}
}
]
}
}
// 3. 更新数据模型 — 填充/更新数据
{
"updateDataModel": {
"surfaceId": "dashboard-1",
"path": "/data/sales",
"contents": [
{ "key": "Q1", "valueNumber": 125000 },
{ "key": "Q2", "valueNumber": 180000 },
{ "key": "Q3", "valueNumber": 210000 }
]
}
}
// 4. 删除 Surface — 清理 UI
{
"deleteSurface": {
"surfaceId": "dashboard-1"
}
}2.4 邻接表模型:为 LLM 而生
A2UI 没有使用传统的嵌套 JSON 树来描述 UI 结构,而是用了邻接表模型(Adjacency List)——所有组件是平面列表,通过 parentId 和 children 引用建立关系。
这个设计不是偶然的,而是专门为 LLM 优化的:
传统嵌套 JSON:
{
"type": "Column",
"children": [
{ "type": "Text", "text": "标题" },
{ "type": "Button", "label": "提交" }
]
}
→ 必须一次性生成完整结构,无法增量更新
A2UI 邻接表:
[
{ "id": "root", "type": "Column", "children": ["title", "btn"] },
{ "id": "title", "type": "Text", "text": "标题" },
{ "id": "btn", "type": "Button", "label": "提交" }
]
→ 可以逐条流式发送,LLM 不需要完美的 JSONLLM 生成嵌套 JSON 容易出错(括号不匹配、层级混乱),但生成扁平的键值对列表非常稳定。这是 A2UI "LLM-Friendly" 设计的核心。
2.5 数据绑定:响应式更新的关键
组件属性有两种取值方式:
// 字面值 — 固定不变
{
"text": { "literalString": "欢迎" }
}
// 数据引用 — 指向数据模型中的路径,数据变了自动更新
{
"text": { "path": "/data/userName" }
}当 updateDataModel 更新了 /data/userName 的值,所有引用了这个路径的组件会自动刷新。这就是 A2UI 的响应式机制——组件树不用重新生成,只需要更新数据模型。
对于数据可视化场景,这至关重要:Agent 可以先建好图表结构,然后持续推送新数据,图表实时刷新。
2.6 可信组件目录:安全的边界
客户端维护一个组件目录(Component Catalog),定义了 Agent 允许使用的组件类型。如果 Agent 发了一个不在目录里的组件类型,客户端直接忽略或降级渲染。
// 客户端组件目录(React 示例)
const COMPONENT_CATALOG = {
'Text': TextComponent,
'Button': ButtonComponent,
'Chart': ChartComponent, // 自定义:图表
'DataTable': TableComponent, // 自定义:数据表
'Map': MapComponent, // 自定义:地图
'FlightCard': FlightCardComponent // 自定义:航班卡片
};
function renderA2UIComponent(descriptor) {
const Component = COMPONENT_CATALOG[descriptor.type];
if (!Component) return ;
return ;
}函数注册表机制进一步保障了交互安全——按钮点击等事件只能调用客户端预注册的命名函数,Agent 不能定义新函数:
{
"componentId": "submit-btn",
"type": "Button",
"properties": {
"label": "提交订单",
"action": {
"functionName": "submitOrder",
"args": {
"orderId": { "$dataRef": "/data/orderId" }
}
}
}
}submitOrder 函数由客户端开发者实现和审计,Agent 只能调用它并传数据引用参数,不能定义它的行为。
三、动态数据可视化的完整流程
将 A2UI 用于数据可视化,典型流程如下:
sequenceDiagram
participant U as 用户
participant C as 客户端
participant A as Agent
participant T as 数据源
U->>C: "分析下季度销售趋势"
C->>A: 用户消息 + 组件目录声明
A->>T: get_sales_data(Q="Q3")
T-->>A: 返回销售数据
A->>C: createSurface("sales-dashboard")
A->>C: updateComponents(图表+表格+筛选器)
A->>C: updateDataModel("/data/sales", [...])
C->>U: 渲染交互式仪表盘
U->>C: 点击"按地区筛选" → 选"华东"
C->>A: action("filter", {region: "华东"})
A->>T: get_sales_data(region="华东")
T-->>A: 返回筛选后数据
A->>C: updateDataModel("/data/sales", [filtered])
C->>U: 图表实时刷新关键点:
- Agent 先拿数据再画 UI — 不是凭空生成,而是调工具获取真实数据后,根据数据特征决定用什么图表
- 结构只建一次,数据持续更新 — 首次
updateComponents建好布局,后续只需updateDataModel - 用户交互回流到 Agent — 点击、筛选等操作通过 action 事件回到 Agent,Agent 决定如何响应
四、代码实现:用 ADK + A2UI 构建可视化 Agent
以下是基于 Google ADK + A2UI 的关键实现代码:
4.1 Agent 端:生成 A2UI 消息
import json
from google.adk.agents.llm_agent import Agent
from google.adk.tools.tool_context import ToolContext
def get_sales_data(tool_context: ToolContext) -> str:
"""获取销售数据,返回结构化 JSON"""
# 实际场景中调用数据库或 API
sales = [
{"quarter": "Q1", "revenue": 125000, "region": "华东"},
{"quarter": "Q2", "revenue": 180000, "region": "华东"},
{"quarter": "Q3", "revenue": 210000, "region": "华东"},
{"quarter": "Q1", "revenue": 95000, "region": "华北"},
{"quarter": "Q2", "revenue": 130000, "region": "华北"},
{"quarter": "Q3", "revenue": 165000, "region": "华北"},
]
return json.dumps(sales)
AGENT_INSTRUCTION = """
你是一个销售数据分析助手。当用户请求分析数据时:
1. 调用 get_sales_data 工具获取数据
2. 生成 A2UI 消息:
a. createSurface: 创建 "sales-dashboard" 画布
b. updateComponents: 放置标题、柱状图、数据表
c. updateDataModel: 填充销售数据到 /data/sales
组件结构(邻接表格式):
- root (Column) → [title, chart, table]
- title (Text): "销售趋势分析"
- chart (Chart): dataRef="/data/sales", chartType="bar"
- table (DataTable): dataRef="/data/sales"
数据路径绑定:所有组件引用 /data/sales,数据更新时自动刷新。
"""
root_agent = Agent(
model='gemini-2.5-flash',
name="sales_visualization_agent",
instruction=AGENT_INSTRUCTION,
tools=[get_sales_data],
)4.2 客户端:注册渲染器和组件目录
// React 渲染器 — 注册自定义可视化组件
import { A2UIProvider, Surface } from '@a2ui/react-renderer';
const componentCatalog = {
Text: ({ text, usageHint }) => {
const Tag = usageHint === 'h1' ? 'h1' : 'p';
return {text} ;
},
Chart: ({ dataRef, chartType }) => {
const data = useDataModel(dataRef); // 响应式读取数据模型
return ;
},
DataTable: ({ dataRef }) => {
const data = useDataModel(dataRef);
return
;
},
Button: ({ label, action }) => (
),
};
function App() {
return (
);
}4.3 传输层:通过 A2A 协议传输
# A2A 传输 — A2UI 消息通过 A2A 扩展自动传输
from a2a.server import A2AServer
server = A2AServer(agent=root_agent)
# A2A 扩展会自动:
# 1. 检测 agent 输出中的 A2UI JSON
# 2. 包装为 application/a2ui+json MIME 类型
# 3. 通过 SSE 流式推送给客户端
server.start(port=10002)4.4 流式渲染体验
A2UI 的流式特性意味着用户能看到界面"逐步构建":
[0.1s] createSurface → 空白画布出现
[0.3s] updateComponents(title) → 标题出现
[0.5s] updateComponents(chart) → 图表骨架出现
[0.8s] updateDataModel → 数据填充,图表渲染完成
[1.0s] updateComponents(table) → 数据表格出现对比传统方式(等 Agent 生成完整 JSON 再一次性渲染),用户感知延迟从"等待 N 秒看到完整结果"变成"界面实时生长"。
五、协议生态全景:A2UI 不是唯一选择
5.1 三种 Generative UI 模式
2026 年的 Generative UI 领域存在三种模式,从"更多控制"到"更多灵活性":
| 模式 | 代表 | 原理 | 安全性 | 灵活性 |
|---|---|---|---|---|
| 受控模式 | Vercel AI SDK (streamUI) | 预建组件,Agent 选择渲染哪个 | 高 | 低 |
| 声明式模式 | A2UI、Open-JSON-UI | Agent 输出组件 schema,客户端映射 | 高 | 中 |
| 开放模式 | MCP-UI | Agent 输出 HTML,沙箱 iframe 渲染 | 中 | 高 |
5.2 五大协议对比
| 维度 | A2UI | AG-UI | Vercel AI SDK | MCP-UI | Open-JSON-UI |
|---|---|---|---|---|---|
| 发起方 | CopilotKit | Vercel | Microsoft + Shopify | OpenAI | |
| 定位 | UI 格式(内容) | 传输协议(管道) | 全栈 SDK | MCP 扩展 | UI 格式 |
| 渲染方式 | 原生组件 | 任意框架 | React Server Components | 沙箱 iframe | 原生组件 |
| 跨平台 | Web + Mobile + Desktop | Web 优先 | 仅 React/Web | Web(iframe) | Web |
| LLM 友好 | 流式 JSONL,邻接表 | 不涉及 UI 生成 | 工具调用路由 | HTML 预构建 | JSON Schema |
| 安全模型 | 可信目录 + 函数注册表 | 信任代码 | 服务端执行 | 沙箱隔离 | 可信目录 |
| 多 Agent | 跨信任边界 | 单 Agent 为主 | 单 Agent | 多 MCP Server | 单 Agent |
| 开源 | Apache 2.0 | 开源 | Apache 2.0 | MCP 扩展 | 开源 |
5.3 A2UI + AG-UI:黄金组合
A2UI 和 AG-UI 不是竞争关系,而是互补:
AG-UI = 管道(transport)— 负责 Agent 和前端之间的双向通信、状态同步
A2UI = 内容(content) — 负责 UI 组件的描述格式最佳实践是组合使用:AG-UI 作为传输层,A2UI 作为 UI 格式。CopilotKit 已经实现了这个组合的零配置集成。
六、A2UI 的版本演进
| 版本 | 状态 | 核心变化 |
|---|---|---|
| v0.8 | Legacy | 结构化输出优先,基线组件 + 数据绑定 + 邻接表 |
| v0.9 | Stable | 哲学转向 Prompt-First,引入 createSurface、客户端函数、自定义目录、模块化 Schema |
| v0.9.1 | Current | 标准化 application/a2ui+json MIME 类型,放宽 surfaceId 约束 |
| v1.0 | Candidate | 双向 RPC(actionResponse)、单消息 UI 实例化、surfaceProperties 替代 theme |
从 v0.8 到 v1.0 的演进方向很清晰:
- 从结构化输出到 Prompt-First — 不再依赖解码层约束 JSON,而是把 Schema 嵌入系统提示,让 LLM 自由生成后验证
- 从单向到双向 — v1.0 新增 actionResponse,支持客户端→服务器的同步 RPC 调用
- 从硬编码到可扩展 — theme 被替换为 surfaceProperties,视觉样式完全交给客户端原生主题
七、渲染器生态
A2UI 的跨平台能力依赖于多端渲染器:
| 渲染器 | 平台 | 状态 | 包名 |
|---|---|---|---|
| Lit | Web | ✅ 稳定 | @a2ui/web-lib |
| Angular | Web | ✅ 稳定 | @a2ui/angular |
| React | Web | ✅ 官方 | @a2ui/react-renderer |
| Flutter | Mobile + Desktop | ✅ 稳定 | flutter_genui |
| SwiftUI | iOS / macOS | 🔜 2026 Q2 | — |
| Jetpack Compose | Android | 🔜 2026 Q2 | — |
v0.9 引入的 @anthropic-ai/a2ui-web-core 共享库统一了 Web 渲染器的核心逻辑——JSON Pointer 解析、组件树 diff/patch、Schema 验证——React/Lit/Angular 渲染器只是薄封装层。
八、实际应用场景
8.1 数据分析仪表盘
Agent 接收"分析销售数据"的请求 → 调工具获取数据 → 生成包含图表 + 筛选器 + 数据表的 A2UI 界面。用户点击筛选器,action 事件回到 Agent,Agent 重新获取数据并更新数据模型,图表实时刷新。
8.2 表单生成
Agent 根据上下文动态生成表单——不同场景的表单字段不同。通过 A2UI 的数据绑定,表单提交后数据自动写入数据模型,Agent 收到结构化数据而非文本。
8.3 多 Agent 协作 UI
多个 Agent 各自负责不同 UI 区域(一个管图表,一个管地图,一个管表单),通过 A2A 协议将各自的 A2UI 消息发送到同一个 Surface。这是 Google 内部多 Agent 工作流的典型模式。
8.4 自定义组件目录扩展
标准目录提供 18 个组件(Text、Button、Card、List 等),但真实场景需要领域组件:
// 金融仪表盘:注册 K 线图组件
const financialCatalog = {
...standardCatalog,
'CandlestickChart': CandlestickChartComponent,
'StockTicker': StockTickerComponent,
'OrderBook': OrderBookComponent,
};
// 医疗应用:注册医疗时间线
const medicalCatalog = {
...standardCatalog,
'MedicalTimeline': MedicalTimelineComponent,
'PatientVitals': PatientVitalsComponent,
};客户端声明支持哪些目录,Agent 就知道可以用哪些组件来构建 UI。
九、A2UI 的局限与思考
A2UI 解决的是"最后一英里"——从 Agent 到屏幕的 UI 传输。但完整的可视化工作流还需要:
- 数据理解 — 解析 CSV/Excel/JSON,推断 Schema,检测列类型
- 数据清洗 — 标准化日期,处理空值,处理异常值
- 统计分析 — 分布、相关性、趋势、异常检测,决定什么值得展示
- 图表选择 — 匹配图表类型与分析意图,调色板,视觉层次
- 交互生成 — 筛选器、下钻、提示
- 导出展示 — PPT、PDF、PNG
A2UI 只覆盖第 5 步的传输环节。步骤 1-4 的"智能层"和步骤 6 的"导出层"需要额外的 Agent 或工具完成。
这也是为什么 A2UI 的定位是协议而非产品——它定义了"怎么传",不定义"传什么"和"为什么传"。
十、总结:Generative UI 的范式转移
A2UI 代表了一个正在发生的范式转移:
从"Agent 描述界面"到"Agent 生成界面"
- 传统:Agent 返回文本 → 用户自己理解 → 自己操作
- Generative UI:Agent 返回可交互的界面 → 用户直接探索
对于数据可视化场景,这意味着:
| 传统 Agent | A2UI 驱动的 Agent |
|---|---|
| "销售数据如下:Q1: 12.5万, Q2: 18万..." | 直接渲染柱状图,可点击下钻 |
| "建议填写以下信息" | 直接生成表单,带验证和联动 |
| "已为您预订航班" | 直接渲染航班卡片,可改签/取消 |
A2UI + AG-UI 的组合正在成为 2026 年 Agent 应用的事实标准:AG-UI 负责管道和状态同步,A2UI 负责 UI 内容描述。加上 A2A 协议处理 Agent 间通信,三者构成了完整的 Agent 驱动界面协议栈。
随着 v1.0 候选版的发布和 SwiftUI/Compose 渲染器即将上线,A2UI 正在从"实验性协议"走向"生产级标准"。对于需要跨平台、高安全、多 Agent 协作的企业级 Agent 应用,A2UI 值得认真评估。
参考链接: