从聊天框到动态界面:一文看懂生成式 UI 与 Google A2UI

本文系统介绍生成式UI的核心理念及其典型实现——Google开源的A2UI协议。重点阐述A2UI作为声明式、跨平台、安全优先的Agent-to-User界面协议,如何通过组件目录机制、扁平化ID引用结构和框架无关设计,解决AI动态生成界面时的安全、一致性与可移植难题;并涵盖A2UI Express、决策模型等最新优化方案,及其在健康助手、理财模拟等场景的适用性分析。

本文是对生成式 UI 概念和 Google 开源项目 A2UI 的入门介绍。资料主要来自 Google Developers Blog 的 A2UI 系列文章(文末附链接),内容由笔者重新组织和改写,并加入了个人理解。文中代码为简化的示意代码,具体字段和接口以 a2ui.org 官方文档为准。


一、先看一个场景:订餐厅的尴尬对话

假设你让 AI 助手帮忙订一张明晚的两人桌。纯文字的对话大概是这样的:

你:帮我订一张两人桌。
AI:好的,哪一天?
你:明天。
AI:几点?
你:7 点左右吧。
AI:7 点没有空位了,其他时间可以吗?
你:那你们什么时候有位?
AI:5:00、5:30、6:00、8:30、9:00、9:30、10:00 有空位,您看哪个合适?

来回七八轮,用户一直在打字。其实这件事用一个小表单就能解决:一个日期选择器、一排可选时间段、一个"确认预订"按钮,点三下就完事。

问题是:这个表单从哪来?

  • 如果由开发者提前写好,那 AI 只能处理开发者预想到的场景;
  • 如果能让 AI 根据当前对话,现场"拼"出最合适的界面,体验就完全不一样了。

后一种思路就叫生成式 UI(Generative UI)。


二、什么是生成式 UI?

1. 一句话定义

生成式 UI:由 AI 根据用户的意图和上下文,实时决定展示什么界面,而不是只回复一段文字。

大模型已经很擅长生成文字、图片和代码,生成式 UI 是把"生成"的对象扩展到了交互界面。

2. 和传统 UI 的区别

维度传统 UI聊天式 AI生成式 UI
界面由谁决定开发者提前设计基本只有聊天框AI 按需组合
适应新需求要改代码、发版只能用文字回答现场生成合适的界面
交互方式点击、表单打字点击、表单、图表,加上对话
典型例子普通 App 页面早期聊天机器人AI 助手直接弹出预订卡片、数据图表

可以这样理解:传统 UI 是"套餐",聊天式 AI 是"只能口述的菜",生成式 UI 是"现点现做的菜"。

3. 生成式 UI 要解决的难题

想法很美好,落地却有几个绕不开的问题:

  1. 安全:AI 生成的东西能直接在用户设备上运行吗?如果 AI 输出一段 JavaScript,被提示词注入攻击了怎么办?
  2. 风格一致:AI 生成的界面能不能和 App 原有的设计风格保持一致,而不是看起来像"外来的"?
  3. 跨平台:同一个 AI,能不能同时给 Web、iOS、Android、Flutter 应用生成界面?
  4. 远程 Agent:在多 Agent 协作的场景里,干活的 Agent 可能运行在另一台服务器上,甚至属于另一家公司。它根本碰不到你的前端代码,只能"发消息"。

三、常见的几种实现思路

在 A2UI 出现之前,业界大致有以下几种做法:

思路 A:让 AI 直接生成 HTML/JS,放进 iframe 沙箱

  • 优点:自由度极高,想画什么画什么。
  • 缺点:iframe 比较重;样式很难和宿主 App 统一,容易出现双滚动条、风格突兀;执行 AI 生成的代码存在安全隐患;而且原生 App(比如 Flutter、SwiftUI)没法直接用。

MCP Apps 走的就是"把 UI 当成资源、在沙箱 iframe 里渲染"的路线,适合需要复杂前端逻辑的场景。

思路 B:预先写好模板,AI 只负责填数据

  • 优点:安全、稳定。
  • 缺点:灵活性差,AI 只能在开发者准备好的几个模板里选。

思路 C:声明式 UI 描述(A2UI 的路线)

AI 不输出代码,而是输出一份**“界面说明书”**:用哪些组件、怎么排列、显示什么数据。客户端拿到说明书后,用自己的原生组件去渲染。

Google 在介绍 A2UI 时有一句话概括得很到位,笔者意译为:

像数据一样安全,像代码一样有表达力。


四、A2UI 是什么?

1. 基本信息

  • 全称:Agent-to-User Interface,可以理解为"Agent 与用户之间的界面协议";
  • 发布:Google 于 2025 年 12 月开源,后续经历了 v0.9(2026 年 4 月)、与 MCP 结合(2026 年 6 月)、推理格式可替换和 Express 格式(2026 年 10 月)等更新;
  • 定位:一种面向 Agent 优化的、跨平台的声明式 UI 协议,加上一套配套的渲染器和 Agent SDK;
  • 官方渲染器:Lit、Angular、Flutter、React 等,社区也在贡献更多实现。

2. 核心机制:用"点菜"来理解

A2UI 的工作方式可以类比为餐厅点菜:

┌──────────────┐  ① 公布菜单(组件目录 Catalog)   ┌──────────────┐
│              │ ───────────────────────────────▶ │              │
│   客户端      │                                  │    Agent     │
│ (Web/App)    │  ② 按菜单点菜(A2UI 消息)         │  (大模型)     │
│              │ ◀─────────────────────────────── │              │
│  ③ 用自家     │                                  │              │
│  原生组件上菜  │  ④ 用户点击按钮 → 事件回传         │              │
│              │ ───────────────────────────────▶ │              │
└──────────────┘                                  └──────────────┘
  1. 客户端公布"菜单":也就是组件目录(Catalog),列出它信任、能渲染的组件,比如 Card、Text、Button、TextField、Row、Column,也可以是自定义的图表、地图组件;
  2. Agent 按菜单"点菜":根据对话内容,用目录里的组件组合出界面,以 A2UI 消息的形式发出;
  3. 客户端"上菜":渲染器把消息映射成自己的原生组件,比如 React 组件或 Flutter Widget,样式完全沿用 App 自己的设计系统;
  4. 交互回传:用户点击按钮、提交表单时,事件被发回给 Agent,Agent 可以继续更新界面。

关键点在于:Agent 只能点菜单上有的菜。 菜单之外的东西它没法要求客户端渲染,这就是 A2UI 安全性的基础。

3. 三条设计原则

根据官方介绍,A2UI 围绕三条原则设计:

① 安全优先

A2UI 是声明式的数据格式,不是可执行代码。客户端只渲染目录里预先批准的组件,降低了 UI 注入等风险。

笔者理解:这相当于把"信任边界"放在了客户端。无论 Agent 是自家的还是第三方的,无论它有没有被提示词注入攻击,它最多只能"点错菜",没法"往厨房里塞东西"。

② 对大模型友好,支持增量更新

界面被表示为一个扁平的组件列表,组件之间通过 ID 引用,而不是一棵层层嵌套的树。这样做有两个好处:

  • 大模型可以一个组件一个组件地生成,客户端可以边收边渲染;
  • 后续对话中要修改界面时,只需要更新对应 ID 的组件,不用整页重来。
③ 与框架无关,可移植

A2UI 把"界面结构"和"界面实现"分开。Agent 只描述"要一个卡片,里面有标题和按钮",至于这个卡片在 Web 上是 <div>,在 Flutter 里是 Card Widget,由客户端决定。同一份 A2UI 消息可以在不同框架的客户端上渲染。


五、A2UI 消息长什么样?

在 v0.9 中,Agent 发给客户端的主要是几类消息,从官方文章中可以看到这几个名字:

消息作用
createSurface创建一块界面区域(Surface),可以理解为"开一张新画布"
updateComponents添加或更新这块界面上的组件
updateDataModel更新界面绑定的数据,比如标题文字、价格、状态

注意这里组件和数据是分开的:组件描述"长什么样",数据模型描述"显示什么内容"。组件通过路径(比如 /title)绑定到数据模型上。这样数据变化时,只需要发一条 updateDataModel,界面结构不用动。

下面是一个简化的示意,帮助理解扁平列表和 ID 引用的概念(字段名不代表真实规范,请以官方 Schema 为准):

[
  { "id": "root",    "component": "Card",   "child": "col" },
  { "id": "col",     "component": "Column", "children": ["title", "slots", "submit"] },
  { "id": "title",   "component": "Text",   "text": { "path": "/title" } },
  { "id": "slots",   "component": "Row",    "children": ["t1", "t2", "t3"] },
  { "id": "t1",      "component": "Button", "label": "18:00" },
  { "id": "t2",      "component": "Button", "label": "20:30" },
  { "id": "t3",      "component": "Button", "label": "21:00" },
  { "id": "submit",  "component": "Button", "label": "确认预订",
    "action": { "event": "book_table" } }
]

可以看到:

  • 每个组件都有唯一的 id;
  • 父组件通过 ID 引用子组件,而不是把子组件直接嵌套在自己内部;
  • title 的文字绑定到数据模型的 /title 路径;
  • 按钮声明了一个事件,用户点击后会通知 Agent。

开头那个订餐厅的例子,用这样一份消息就能变成一张可以点选的卡片。


六、A2UI 在生态中的位置

生成式 UI 领域的工具很多,容易混淆。下面这张表帮你理清关系:

技术解决什么问题与 A2UI 的关系
A2A(Agent-to-Agent 协议)Agent 之间如何通信可以作为 A2UI 消息的传输通道
AG-UI / CopilotKitAgent 后端和前端应用之间的连接、状态同步互补,AG-UI 负责"管道",A2UI 负责"界面内容"
MCP(模型上下文协议)Agent 如何调用工具和数据MCP 工具可以返回 A2UI 消息(MIME 类型 application/a2ui+json)
MCP Apps以资源形式提供交互界面,通常在 iframe 中渲染 HTML互补:标准界面用 A2UI 原生渲染,高度定制的复杂界面用 MCP Apps

一句话总结:A2A、AG-UI、MCP 管"怎么传",A2UI 管"传什么界面"。

v0.9 之后,A2UI 支持的传输方式包括 MCP、WebSocket、REST、AG-UI、A2A 等,基本不挑通道。


七、快速上手:给 Agent 加上 A2UI

以 Python SDK 为例,接入流程大致分为几步(示意代码,具体 API 以官方文档为准):

pip install a2ui-agent-sdk
# 第 1 步:定义组件目录(可用官方的 Basic 组件集,也可以用自己的)
catalog = CatalogConfig.from_path("catalog.json")

# 第 2 步:用目录生成系统提示词,告诉大模型"菜单上有哪些菜"
system_prompt = build_prompt_with_catalog(catalog)

# 第 3 步:用任意 Agent 框架调用大模型
reply = my_agent.respond(user_query, system_prompt=system_prompt)

# 第 4 步:SDK 解析模型输出,校验并修复成合法的 A2UI 消息
messages = parse_and_validate(reply, catalog)

# 第 5 步:通过 A2A / AG-UI / MCP 等通道发送给客户端渲染
send_to_client(messages)

如果你的前端用的是 CopilotKit,官方提供了现成的模板:

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

TypeScript 和 Dart 也有对应的 Agent SDK(@a2ui/agent、a2ui_agent)。


八、最新进展:解决"慢"的问题

生成式 UI 被吐槽最多的一点是慢:用户要等大模型把整个界面一个 Token 一个 Token 地"写"出来。

2026 年 10 月的更新给出了两个方案:

1. A2UI Express:更省 Token 的"简写语法"

不再让模型直接写冗长的 JSON,而是写一种类似 Python 的简洁语法,再由 SDK 编译成标准 A2UI 消息。示意:

root=Card(col)
col=Column([title, submit])
title=Text($/title)
submit=Button(submit_label, _, Event("book_table", {}))

据官方在 gemini-3.5-flash 上的评测,生成同类界面时,Express 的 Token 数大约只有直接写 JSON 的三分之一,有效率和 JSON 持平。

2. 决策模型:固定结构的界面"做选择题"

对于设置页、结账页这类结构固定的界面,可以用专门的决策模型从预定义布局中做选择,再由代码拼装界面,大模型只负责填文字。官方示例中,组件骨架在几百毫秒内就能上屏。

这部分内容的详细解读,可以参考笔者的另一篇文章《生成式 UI 太慢?Google A2UI 新版本让 Token 消耗降到三分之一》。


九、适合哪些场景?

结合官方案例和笔者的理解,以下场景比较适合尝试 A2UI:

场景举例
AI 助手中的结构化交互订餐、订票、预约,用表单代替多轮问答
数据展示根据问题动态生成图表、表格、指标卡片
个性化界面健康助手根据用户的检查结果展示相关卡片;理财助手根据人生目标生成模拟器
多 Agent 系统第三方远程 Agent 安全地把界面"送"到你的 App 里
跨端产品一个 Agent 同时服务 Web、iOS、Android、Flutter 客户端

官方博客中提到的案例包括:基于 Flutter 的个人健康助手(把分散的病历、可穿戴设备数据整合成按需生成的卡片),以及个人理财规划模拟器(用滑块、柱状图等组件生成实时界面)。

不太适合的场景

  • 需要大量复杂客户端逻辑的界面,比如在线编辑器、游戏。A2UI 受限于组件目录,这类需求更适合 MCP Apps 或传统开发;
  • 完全固定、几乎不变的页面。直接写死就好,没必要引入 AI。

十、笔者的几点思考

1. "组件目录"是整个设计的灵魂

A2UI 最聪明的地方,是把控制权交给了客户端。Agent 很强大,但它只能使用客户端公布的组件。这带来三个直接收益:

  • 安全:信任边界清晰;
  • 品牌一致:界面永远是自家设计系统的样子;
  • 复用:前端团队已有的组件库可以直接注册成目录,不用为 AI 另起炉灶。v0.9 把可选的官方组件集从 “Standard” 改名为 “Basic”,传递的也是这个意思:鼓励用你已有的组件,而不是用官方的。

2. 对前端开发者意味着什么?

有人担心"AI 都能生成界面了,前端还有饭吃吗"。笔者的看法是,前端的工作重心会发生转移:

  • 从"写一个个页面"转向**“设计和维护高质量的组件目录”**;
  • 组件的命名、属性设计、文档描述会直接影响 AI 的使用效果。组件设计得越清晰,AI 拼出来的界面越好;
  • 渲染器、交互事件处理、性能优化依然需要专业的前端能力。

换句话说,前端从"做菜的人"变成了"设计菜单和厨房的人"。

3. 落地前需要想清楚的问题

  • 可预测性:同一个问题,AI 每次生成的界面可能不一样。对于需要一致体验的核心流程,要考虑用 few-shot 示例或固定模板约束;
  • 测试:动态生成的界面怎么做 UI 测试和回归测试,目前还没有成熟方案;
  • 可访问性:原生组件天然继承了 App 的无障碍能力,这是 A2UI 相比 iframe 方案的优势,但组件目录本身要先做好无障碍支持;
  • 版本演进:A2UI 仍处于 0.x 阶段,规范还在变化,生产使用要留意版本兼容。

4. 生成式 UI 是交互方式的一次升级

过去两年,AI 应用的主流交互几乎都是聊天框。但并不是所有任务都适合用文字完成,选日期、比价格、看趋势,图形界面的效率远高于打字。

生成式 UI 让 AI 应用可以在对话和图形界面之间自由切换:需要理解意图时用对话,需要操作时直接给你一个界面。笔者认为,这会是下一代 AI 应用的标配能力,而 A2UI 提供了一套开放、跨平台的标准,值得持续关注。


总结

要点内容
生成式 UIAI 根据上下文实时生成交互界面,而不只是回复文字
核心难题安全、风格一致、跨平台、远程 Agent 无法直接操作前端
A2UI 的方案声明式消息 + 客户端组件目录 + 原生渲染
三条原则安全优先;对大模型友好、可增量更新;与框架无关
生态关系A2A / AG-UI / MCP 负责传输,A2UI 负责界面内容,MCP Apps 负责复杂定制界面
最新进展Express 格式减少约三分之二的 Token;决策模型加速固定结构界面

参考资料

声明:本文为学习笔记和个人观点,内容基于上述公开资料重新组织和改写,示例代码为笔者编写的简化示意。如有理解偏差,欢迎评论区指正。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值