万益资讯网

让 Agent 直接生成可交互界面,A2UI 协议在 Covonaut 中的实践

最近我在 Go Agent 框架 Covonaut 中集成了一个颇具前瞻性的协议 A2UI(Agent-to-UI),这
最近我在 Go Agent 框架 Covonaut 中集成了一个颇具前瞻性的协议 A2UI(Agent-to-UI),这个协议是为了解决当前 Agent 生态中的一个普遍性的痛点:大多数 Agent 的输出仍局限于文本或代码片段。许多复杂任务仅靠文字是难以表述清楚的,让用户手动复制代码运行的体验更是糟糕。
那能否让 Agent 可以直接交付一个可填写、可点击、可实时刷新的交互界面呢?A2UI 正是为解决这个问题而生的协议。与传统的“前端写页面”模式不同,A2UI 的核心在于 Agent 输出结构描述(组件树 + 数据模型),客户端则利用原生控件进行渲染。
在实际落地过程中,我认为 A2UI 的几个设计亮点尤为值得分享。
结构与状态分离,为流式生成而生A2UI 将界面清晰地划分为两层:UI 结构(组件及其布局)与 应用状态(数据模型)。组件通过绑定机制与数据关联,两者解耦并支持独立更新。
1、扁平化的组件组织
传统 UI 描述多采用嵌套结构(如 Column 套 Row,Row 套 Button),这对 LLM 极不友好,因为 LLM 必须一次性生成完美的嵌套树,任何嵌套错误都会导致整体渲染失败,还有难以修改某些深层节点。
A2UI 创新性地采用了扁平邻接表结构,即所有组件都被平铺在一个列表中,通过 ID 互相引用来表达父子关系(必须包含一个 ID 为 root 的根节点)。这种设计对 LLM 极其友好:
支持逐个组件流式输出,边生成边发送;单个组件出错只需重发该节点,无需推倒重来;组件定义即使乱序到达也没问题,客户端会缓冲等待 root 出现后再渲染。2、灵活的数据绑定与增量更新
数据层使用 JSON Pointer(RFC 6901)进行寻址。组件取值支持字面量、数据路径绑定或客户端函数动态求值。子组件列表也分为固定列表和模板两种模式,后者配合数据数组可批量渲染列表或表格,极大简化了界面的描述。
界面更新通过一组标准 Envelope 完成:
createSurface:创建画布updateComponents:更新结构updateDataModel:更新数据deleteSurface:销毁界面跨信任边界的安全性这是 A2UI 最关键的价值,协议全程只传递“组件描述”与“数据绑定”,而不传输任何可执行代码。
客户端仅根据自身维护的组件目录进行渲染,未注册的组件会被直接忽略。在生产环境中,我们可以将组件目录限定在企业设计系统范围内,既保证了 UI 风格的一致性,也从根源上杜绝了 Agent 注入恶意逻辑的风险。
此外,协议内置了结构校验机制。我在 Covonaut 中实现了双层校验:一层是消息级校验,验证每条 JSONL 的格式与字段完整性;另一层是全局树校验,检查 root 是否存在、有没有组件引用了不存在的父节点 ID,以及有无循环引用。
校验失败时返回标准的 VALIDATION_FAILED 格式,该格式可直接回传给 LLM 触发自动纠错。渲染前,Agent 与客户端还会进行能力协商,确保双方支持的组件集对齐。
表现力与跨端适配A2UI 的组件库覆盖了主流交互需求:
展示类:Text、Image、Icon、Divider布局类:Column、Row、List、Card交互类:Button、TextField、CheckBox、Slider(支持数据绑定与校验规则)用户操作(如点击按钮)会触发 Action 回传给 Agent,驱动下一步逻辑。由于传输的是抽象描述,同一份响应可在 Web(Lit/Angular/React)、移动端(Flutter/SwiftUI/Jetpack Compose)乃至桌面端原生渲染。Agent 专注描述“是什么”,各端负责决定“长什么样”。
实际场景体验以生成一个配置面板为例:
Agent 通过 createSurface 初始化画布,用 updateComponents 铺设 TextField、Slider 和 Button,再通过 updateDataModel 注入默认值。客户端即时渲染出原生控件,用户调整参数后点击提交,Action 回传 Agent,执行结果再通过 updateDataModel 实时渲染到面板上。
全程零代码、零复制粘贴,相比以往“请复制这段代码到终端运行”的割裂体验,这是绝对一种质的飞跃。
展望与思考A2UI 仍在快速演进中,v1.0 候选版已加入客户端到服务端的 RPC 及 Action ID 等特性,我在 Covonaut 中的实现是遵循的 v0.9.1 版本,后续会持续跟进。只有当 Agent 能直接提供可交互的界面时,才算真正嵌入了用户的工作流。