A2UI(Agent-to-User Interface)用声明式数据表达界面意图,由客户端受信任的组件实现负责呈现。它不是让模型生成一段 JavaScript 再交给浏览器执行,也不等同于消息传输协议。本文讨论宿主运行时的设计方式;具体消息名称和字段需要与所选协议版本对齐。
先把四种职责分开
| 层次 | 负责什么 | 不应承担什么 |
|---|---|---|
| 传输适配 | 接收消息、连接状态、恢复策略 | 直接操作页面组件 |
| 协议适配 | 校验版本、解析消息、归一化更新 | 放行任意脚本 |
| Surface 状态 | 组件引用、数据模型、生命周期 | 持有全站权限 |
| Renderer 与宿主动作 | 映射组件、绑定事件、提交意图 | 替代服务端鉴权 |
同一套业务组件可以被 React 或 Vue Renderer 包装,但这不意味着任意现有渲染器支持所有协议版本。组件目录、属性约束和事件语义需要配套验证。
用一个选餐场景理解更新
智能体先给出候选菜谱,用户选择一项并填写人数,点击确认后系统才创建计划。候选列表来自任务数据,选中值与人数是正在编辑的草稿。下一条候选列表更新不应无条件覆盖用户输入。
任务消息 → 协议校验 → 指定 Surface 的组件与数据更新
用户选餐 → 本地草稿变化 → 当前 Surface 重绘
用户确认 → 宿主校验动作 → 服务端授权与业务处理
处理结果 → 新消息 → 更新结果区域
这是宿主链路示意,不是可以直接发送的 A2UI 协议报文。接入时应使用对应版本的官方示例和 Schema,避免把内部封装字段写成标准协议。
流式界面需要中间状态
组件引用可能尚未到齐,数据可能仍在加载,网络也可能在一半时中断。可以短暂保留待解析节点,但必须限制数量、等待时长和嵌套深度。接收到完整更新后再提交一组相互依赖的节点,避免用户看到一半新数据、一半旧组件。
为每个 Surface 建立加载、可交互、失败与销毁状态。断线恢复时,根据后端能力选择重放或获取快照;没有服务端重放契约时,不应假设重新连接就能补齐所有消息。
Action 只携带完成任务所需的信息
宿主可以给业务提交增加请求 ID,并由服务端按用户和操作范围实现幂等。这是应用层设计,不能假设协议本身保证“恰好一次”。按钮禁用只能改善体验,挡不住重试、重放和直接请求接口。
服务端需要从可信会话获得用户身份,再检查任务和资源归属。模型传来的 ownerId、价格、权限标记都不能直接作为授权依据。URL、图片源、富文本以及组件自带的副作用同样要校验,声明式 JSON 也可能携带危险输入。
从最小闭环开始验收
先只支持文本、选择器和确认按钮,跑通一次“生成—编辑—提交—结果”。随后注入未知组件、缺失引用、重复提交、过期任务和断线场景,检查当前表面能否降级、旧输入是否保留、服务端是否拒绝越权。
继续阅读:A2UI 的交互观、Renderer 信任边界、LowCode Engine 架构。