过去,我们习惯把界面看成产品逻辑的终点:数据准备完毕,前端把它渲染出来,用户再进行操作。生成式界面改变的并不只是“谁来写 UI”,而是界面在整个系统里的位置。它开始成为智能体与人共同推进任务的中间语言。

这意味着界面不再是一次性生成的静态结果。它可以随着任务上下文被创建、补充、局部替换,也可以在用户作出选择后继续演化。真正值得讨论的,不是模型能不能画一个表单,而是这条持续变化的链路如何保持可理解、可控制和可信。

页面正在变成“表面”

页面通常暗示一个稳定的信息架构;Surface 更像任务在某个时刻需要的一块交互表面。它可能出现在工作区,也可能嵌在一条消息里。它有独立的数据模型、组件树与生命周期,但仍然属于同一个任务上下文。

生成式界面的基本单位,不是模型画出的页面,而是一个可以被验证、更新和回收的交互表面。

这个变化会直接影响设计。我们不能再假设所有状态都在页面加载前确定,也不能把每一次模型输出都当成完整重绘。稳定的部分应该被保留,变化的部分需要有明确边界,用户刚刚完成的输入更不能被下一次流式更新轻易覆盖。

一次交互的真实路径

把链路缩小到一次点击,会更容易看清它的职责分工。用户先在本地改变选择状态;当他确认操作时,Renderer 才构造一个 Action,并携带当前表面的必要上下文交给宿主环境。

选择选项
  ↓ 本地更新 dataModel
点击“确认”
  ↓ Renderer 构造 Action
宿主校验 capability + action
  ↓ 通过允许的通道发送
智能体继续任务

这里最重要的细节是:选择变化和任务提交不是同一件事。前者应该快速、可撤销,并且大多数时候只发生在本地;后者才跨越信任边界。把两者混在一起,会让每次点选都触发模型请求,体验和成本都会失控。

Renderer 是一条信任边界

模型表达的是界面意图,而不是任意代码。客户端通过受信任的组件注册表理解这种意图,通过 Schema 验证属性,再用 Action allowlist 决定什么操作可以离开本地。模型能提出请求,但不能绕过宿主的权限与运行时规则。

所以,A2UI 的价值不在于让前端消失。恰恰相反,它让前端最重要的工作变得更清晰:定义组件语义,保护交互边界,管理持续变化的状态,并让每一次生成都仍然像产品的一部分。