Google 最近开源了一个名为 A2UI 的项目,旨在解决一个实际问题:AI 智能体如何安全地生成丰富的用户界面?

传统上,智能体只能返回文本,用户需要通过多轮对话才能完成任务。而 A2UI 允许智能体直接生成表单、按钮、日期选择器等交互式组件,用户只需点击几下即可完成操作。
从固定界面到动态生成的转变
传统的智能体交互主要基于文字聊天——用户提问,AI 回答,往往需要多轮对话才能完成一个简单任务。以订餐为例:
用户:“我想订个桌子”
AI:“什么时间?”
用户:“明天晚上”
AI:“几点?”
用户:“7点”
AI:“几个人?”
...
此外,许多应用仍采用固定的界面设计,无论用户需求如何变化,界面都一成不变。这种“一刀切”的做法越来越难以满足用户的个性化需求。
真正的趋势是 AI 根据具体场景动态生成交互界面。如今的 AI 能力已远超简单的问答,它们能够理解复杂的业务逻辑、处理多步骤工作流,甚至协调多个子任务。但如果仍局限于文本交互,就如同让建筑师只能用语言描述设计图,而无法将其绘制出来。
场景驱动的界面生成正成为刚需:
- 个性化体验:根据用户历史行为和偏好设置动态调整界面元素。
- 上下文感知:同一功能在不同场景下展现不同复杂度的界面。
- 任务导向:界面结构完全服务于当前任务,去除无关元素。
- 实时适配:随着对话进展,界面可以动态增减字段和选项。
同样是订餐,如果用户说“给我家老人订个桌子”,AI 可能会生成一个更简化的表单,突出无障碍选项;如果是商务聚餐,则可能增加预算范围、菜系偏好等字段。
在此之前,业界已有一些让 AI 自动生成 UI 的尝试。A2UI 正是加速这一趋势的关键协议。它让智能体能够“看图说话”,根据对话上下文、用户偏好和任务复杂度,实时生成最合适的交互界面。
核心思路
A2UI 的协议设计非常周到。它并非让智能体直接生成 HTML 或 JavaScript 代码(这存在安全风险),而是生成一种声明式的 JSON 格式,用于描述界面应有的样子。客户端收到后,使用自己的原生组件进行渲染。
例如,智能体要生成一个订餐表单,它会发送如下消息:
json
{
"surfaceUpdate": {
"surfaceId": "booking",
"components": [
{"id": "title", "component": {"Text": {"text": {"literalString": "预订餐桌"}, "usageHint": "h1"}}},
{"id": "datetime", "component": {"DateTimeInput": {"value": {"path": "/booking/date"}, "enableDate": true}}},
{"id": "submit-btn", "component": {"Button": {"action": {"name": "confirm_booking"}}}}
]
}
}
客户端收到此消息后,会使用其 Angular、Flutter 或 React 组件来渲染对应的标题、日期选择器和按钮。同时,A2UI 采用了一种对大型语言模型(LLM)友好的“邻接表”模型来描述界面结构,使智能体能够增量式地构建界面,无需一次性生成完美的 JSON。目前,A2UI 支持 Web(Lit、Angular)和 Flutter 渲染器,并计划加入 React、SwiftUI、Jetpack Compose 等更多平台。其传输层兼容 A2A 协议、AG-UI 等。
三个关键优势
安全性:智能体只能请求客户端预先定义好的组件类型,无法执行任意代码。这避免了传统方案中通过 iframe 嵌入第三方代码所带来的安全隐患。
原生体验:生成的界面能够完全融入应用的设计系统,不会像 iframe 那样显得突兀。用户无法区分界面是由智能体生成还是由开发者编写。
跨平台兼容:同一个 JSON 消息可以在 Web、移动端和桌面端渲染,因为每个平台都使用自己的原生组件实现。
为什么现在需要动态界面
如今的 AI 能力已远超简单的问答。它们能够理解复杂的业务逻辑、处理多步骤工作流,甚至协调多个子任务。但如果仍局限于文本交互,就如同让建筑师只能用语言描述设计图,而无法将其绘制出来。
场景驱动的界面生成正成为刚需:
- 个性化体验:根据用户历史行为和偏好设置动态调整界面元素。
- 上下文感知:同一功能在不同场景下展现不同复杂度的界面。
- 任务导向:界面结构完全服务于当前任务,去除无关元素。
- 实时适配:随着对话进展,界面可以动态增减字段和选项。
这种变化并非技术炫技,而是用户体验的自然演进。就像从命令行到图形界面,从静态网页到动态应用,智能体界面也在从固定模式向生成式模式转变。
智能体 UI 生态中的定位
智能体 UI 领域发展迅速,各种工具都在解决不同层面的问题。A2UI 并非要替代现有框架,而是专门解决跨平台、可互操作的生成式 UI 响应这一特定问题。
与 MCP Apps 的差异
MCP (Model Context Protocol) 最近推出了 MCP Apps,将 UI 视为一种资源来处理。智能体可以返回一个 ui:// URI,客户端获取后在沙盒 iframe 中渲染预构建的 HTML 内容。
A2UI 的不同之处:A2UI 采用“原生优先”的方法。它不是获取一个不透明的 HTML 包来显示,而是发送原生组件的蓝图。这使得 UI 能够完美继承宿主应用的样式和无障碍功能。在多智能体系统中,编排智能体可以轻松理解子智能体发送的轻量级 A2UI 消息内容,从而实现更流畅的智能体间协作。
简而言之:
- MCP Apps:智能体发送完整的 HTML 页面,客户端在 iframe 中显示。
- A2UI:智能体发送组件描述,客户端使用自己的原生组件渲染。
与 AG-UI 的关系
AG-UI 是处理智能体与用户交互的协议,负责状态同步、聊天历史、输入处理等“管道”工作。

A2UI 可以与 AG-UI 很好地协同工作。如果你使用 AG-UI 构建宿主应用,它可以利用 A2UI 作为数据格式来渲染来自宿主智能体和第三方智能体的响应。这实现了两全其美的效果:一个丰富、有状态的宿主应用,同时能够安全地渲染来自其无法控制的外部智能体的内容。

智能体 UI 生态正在快速发展,不同的协议和框架各有专长:MCP 处理工具和数据连接,AG-UI 处理智能体交互,A2UI 专注于跨平台的原生 UI 渲染。它们并非竞争关系,而是互补的,共同构建了一个完整的智能体应用开发栈。

实际开发体验
快速开始
首先克隆启动模板:
bash
git clone https://github.com/copilotkit/with-a2a-a2ui.git
echo "GEMINI_API_KEY=your_api_key_here" > .env
pnpm install
pnpm dev
后端:定义 A2UI 组件
智能体需要在提示中包含 A2UI 的 JSON Schema 和组件模板。例如,一个餐厅列表的模板定义如下:
“`python
RESTAURANT_UI_EXAMPLES = “””
{
“surfaceUpdate”: {
“surfaceId”: “default”,
“components”: [
{“id”: “root-column”, “component”: {“Column”: {“children”: {“explicitList”: [“title-heading”, “item-list”]}}}},
{“id”: “title-heading”, “component”: {“Text”: {“usageHint”: “h1”, “text”: {“literalString”: “Top Restaurants”}}}},
{“id”: “item-list”, “component”: {“List”: {“direction”: “vertical”, “children”: {“template”: {“componentId”: “item-card-template”, “dataBinding”: “/items”}}}}},
{“id”: “item-card-template”, “component”: {“Card”: {“child”: “card-layout”}}},
{“id”: “template-book-button”, “component”: {“Button”: {“child”: “book-now-text”, “primary”: true, “action”: {“name”: “book_restaurant”, “context”: [{“key”: “restaurantName”, “value”: {“path”: “name”}}]}}}}
]
}
}
“””
def get_ui_prompt(base_url: str, examples: str) -> str:
return f”””
You are a helpful restaurant finding assistant. Your final output MUST be a A2UI UI JSON response.
To generate the response, you MUST follow these rules:
1. Your response MUST be in two parts, separated by the delimiter: `---a2ui_JSON---`.
2. The first part is your conversational text response.
3. The second part is a single, raw JSON object that is a list of A2UI messages.
{examples}
"""
“`
智能体配置
接下来,配置智能体以处理 A2UI 响应和用户交互:
“`python
class RestaurantAgent:
def init(self, base_url: str, use_ui: bool = False):
self.base_url = base_url
self.use_ui = use_ui
self._agent = self._build_agent(use_ui)
def _build_agent(self, use_ui: bool) -> LlmAgent:
if use_ui:
instruction = AGENT_INSTRUCTION + get_ui_prompt(self.base_url, RESTAURANT_UI_EXAMPLES)
else:
instruction = get_text_prompt()
return LlmAgent(
model=LiteLlm(model="gemini/gemini-2.5-flash"),
name="restaurant_agent",
description="An agent that finds restaurants and helps book tables.",
instruction=instruction,
tools=[get_restaurants],
)
“`
处理用户交互
当用户点击按钮时,A2UI 会自动将 UI 事件转换为智能体能理解的查询:
“`python
在 AgentExecutor 中处理 UI 事件
if ui_event_part:
action = ui_event_part.get(“actionName”)
ctx = ui_event_part.get(“context”, {})
if action == "book_restaurant":
restaurant_name = ctx.get("restaurantName", "Unknown Restaurant")
address = ctx.get("address", "Address not provided")
# 转换为智能体理解的查询
query = f"USER_WANTS_TO_BOOK: {restaurant_name}, Address: {address}"
elif action == "submit_booking":
# 处理预订表单提交
restaurant_name = ctx.get("restaurantName", "Unknown Restaurant")
party_size = ctx.get("partySize", "Unknown Size")
reservation_time = ctx.get("reservationTime", "Unknown Time")
query = f"User submitted a booking for {restaurant_name} for {party_size} people at {reservation_time}"
“`
前端:集成渲染器
前端集成非常简单,使用 CopilotKit 的 A2UI 渲染器:
“`javascript
// 创建 A2UI 消息渲染器
import { createA2UIMessageRenderer } from “@copilotkitnext/a2ui-renderer”;
const A2UIMessageRenderer = createA2UIMessageRenderer({ theme });
// 配置 CopilotKit 提供者
<CopilotKitProvider
runtimeUrl=”/api/copilotkit”
renderActivityMessages={[A2UIMessageRenderer]}
“`
API 路由配置
连接前后端的 API 路由:
“`javascript
import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from “@copilotkitnext/runtime”;
import { A2AAgent } from “@ag-ui/a2a”;
import { A2AClient } from “@a2a-js/sdk/client”;
// 创建 A2A 客户端连接到智能体服务器
const a2aClient = new A2AClient(“http://localhost:10002”);
const agent = new A2AAgent({ a2aClient, debug: true });
// 创建 CopilotKit 运行时
const runtime = new CopilotRuntime({
agents: { default: agent },
runner: new InMemoryAgentRunner(),
});
// 创建 HTTP 端点
const app = createCopilotEndpoint({
runtime,
basePath: “/api/copilotkit”,
});
export const GET = handle(app);
export const POST = handle(app);
“`
使用 A2UI Composer

Google 还提供了一个在线工具 A2UI Composer,让你可以用自然语言描述想要的界面,自动生成对应的 A2UI JSON 规范:
- 访问 https://a2ui-editor.ag-ui.com/
- 描述你想要的组件,比如“创建一个餐厅卡片,包含图片、名称、评分和预订按钮”
- 点击创建,系统会生成完整的 A2UI JSON
- 复制生成的 JSON 到你的智能体提示中
这大大降低了学习和使用门槛。
运行效果
运行后,用户问“找一些纽约的中餐厅”,智能体会:
- 调用
get_restaurants工具获取数据 - 根据餐厅数量选择合适的模板(≤5个用单列,>5个用双列)
- 生成包含餐厅卡片、图片、评分、预订按钮的界面
- 用户点击“Book Now”按钮时,自动跳转到预订表单
- 提交预订后显示确认界面
整个过程中,界面都是智能体根据上下文动态生成的,不是预先写好的静态页面。
以下是一个来自 Yasin Ertan 更复杂的例子。
应用现状
A2UI 已经在 Google 内部大规模使用。Google Opal 让数十万人用自然语言构建 AI 小程序,Gemini Enterprise 用它为企业生成定制界面。Flutter GenUI SDK 和 CopilotKit 也都集成了 A2UI 支持。
使用方式很灵活:前端开发者可以集成渲染器(支持 Angular、Flutter,React 即将推出),智能体开发者可以用 Python 或 Node.js 框架生成 A2UI 响应,平台构建者可以通过现有框架快速接入。
典型场景包括动态表单生成、专业工具界面和数据可视化。比如景观设计师智能体根据用户上传的照片,生成定制化的设计需求表单。
小结
图文聊天已经成了 AI 与人类交流的范式,而 A2UI 将颠覆交互体验,面向不同场景不同人产生不同的交互形式,将个性化体验再往前推进一步。我们正在从“适应机器的交互方式”转向“机器适应人的交互需求”。以前是用户学习如何使用固定的界面,现在是界面学习如何适应用户的场景。A2UI 提供了一个标准化的方案,让智能体能够“说 UI”,同时保持安全性和原生体验。从 Google 内部的大规模应用到合作伙伴的积极集成,都说明这个协议正在成为智能体 UI 领域的重要标准。
关注“鲸栖”小程序,掌握最新AI资讯
本文来自网络搜集,不代表鲸林向海立场,如有侵权,联系删除。转载请注明出处:http://www.itsolotime.com/archives/15204
