A2UI 初想:Agent 想画 UI,先得有一块画板

0 阅读3分钟

A2UI初想

起因是一个问题:LLM 能不能读用户所处的 context,直接生成贴合业务的 UI?从一个 text2SQL demo 出发,我一度以为答案是"让 LLM 输出 HTML"——哪怕只做 dashboard 也要 LLM 知道整个故事、生成 HTML、再照 API 文档接后端。可这本质上不就是在用 LLM 做一个 Web App?那如果限定在 chatbox 内、按情境渲染不同组件,是不是该落到 React 的动态加载上?

A2UI

喝着咖啡跟Deepseek等模型聊了一下,就发现我之前的理解太肤浅了,架构师们并不这样设计的,它们会考虑不是什么component都能被render ... 于是我让Grok 4.5 写了个小demo看看 BTW Grok 写后端似乎真不太行,之前让它写flutter解决了一些GLM 5.2也没法解决的问题。

1)A2UI 是一套协议(protocol) ,不是某个具体的库、框架或产品。定义了服务端(agent)和客户端(renderer)之间 怎么用消息描述界面 。

2)它规定的是 消息契约 :server→client 只有 4 种消息( createSurface / updateComponents / updateDataModel / deleteSurface )

3)一个 surface = 一块画板,里面装着一棵树(forest of components)。 这块画板(surface)是稳定的容器,而里面的 components 可以千变万化。

Jsonl

Json line

JSONL(JSON Lines)是每行一个独立、完整的 JSON 值、行与行用 \n 分隔的格式。它通常由多个 JSON 值逐个紧凑序列化(每个值压成一行、内部不留裸换行)后拼接而成,而不是把一个 JSON array join 成一行。

对 A2UI 来说,一条消息(如 createSurface)就是一个 JSON 对象,紧凑序列化为一行 JSONL。这条 JSONL 行可以通过 SSE 的 data 字段传输,也可以走纯 JSONL 流(NDJSON)。

todo list

概念

后文都会简单用todo list作为案例看如何使用A2UI

从消息契约上看,Surface生命周期挺明显的:

createSurface / updateComponents / updateDataModel / deleteSurface

其中 只要还没执行deleteSurface,就可以updateComponents & updateDataModel

而一个session里面可能会同时管理多个Surface,可以想象:

  • 某个场景,弹出window是一个Surface,弹出window后面的page可能有多个Surface
  • 一般来说例如做一个dashboard,一个component对应一个图表,而整个page就是一个Surface
  • Catalog-白名单:所有渲染的component都必须在这个Catalog里面,它完全没有任何样式/布局字段,但它会规定例如是不是必填,必选之类的

下面这个是default的Catalog :

a2ui.org/specificati… 是 A2UI 官方 v0.9.1 版本的 basic(基础)组件目录 ,它声明了某个 Surface 被允许渲染哪些组件以及各自支持的属性,developer可以自定义。

用hy3生成了一段复杂的component,它可以让我们脑补一下todo APP里面复杂组件大概是怎样的

Column (root)
├── Tabs            // 全部/进行中/已完成
│   ├── List (进行中)
│   │   ├── Card (item_0)  → Row[ CheckBox, Text, Icon(star), Icon(delete) ]
│   │   ├── Card (item_1)  → ...
│   └── ...
├── Row (底部操作栏)
│   ├── Button(添加)
│   ├── Button(筛选) → Modal(筛选表单: Dropdown优先级 + DatePicker)
│   └── ProgressBar(今日完成度)
└── Modal (编辑) → Column[ TextField(标题), DatePicker, Button(保存) ]