A2UI — Agent to UI
A2UI 让专家用一段声明式 JSON 描述界面,前端把它渲染成原生 React 组件直接嵌在对话里——不是 iframe,不是 HTML 字符串,所以视觉上和产品本身完全一致。 由profy-visualize 插件提供,工具名 render_ui。它与 visualize(自由 HTML / Canvas / WebGL)是两条并行的路:要「数据 + 布局」走 A2UI,要「自定义渲染逻辑」走 visualize。
协议结构
render_ui 接收组件数组,返回一个 a2ui 载荷;前端 StageGroup 检测到该字段后用 A2uiSurfaceCard 渲染。
组件节点的形状
这是最容易写错的一点——属性必须放在props 里,不能平铺在节点上:
props(属性字典)、children(子组件数组)、actions(动作定义数组)。
唯一的入参校验
render_ui 只做一件事的校验:递归检查每个组件都有 type 字段。缺了就整体拒绝:
组件目录(16 个)
以下属性名以渲染器实际读取的字段为准。布局
gap 只认 0 / 1 / 2 / 3 / 4 / 6 / 8 这几个值(对应 Tailwind 间距档位),其余任意数字一律回落到 3。所以 gap: 16 不会得到 16px,而是默认间距。
align 认 center / end(或 bottom)/ stretch,其余回落 start。
内容
Text 的 weight 认 bold / semibold / medium,其余不加粗。注意 variant 没有 code 这一档——传了会当正文渲染。
交互
变体只认
secondary / destructive / outline;传 primary 或 ghost 都会落到默认样式(视觉上等同 primary)。按钮尺寸固定为 sm,不可调。
Profy 业务组件
PricingTable 没有「高亮推荐档」的能力,也不会把 features 数组渲染成条目列表——数组会被 String() 成 a,b,c 一行文本。要漂亮的功能对比,用 Table 自己排版更可控。不存在的组件会怎样
渲染器找不到该类型时,会渲染一个虚线框写着Unknown component: <类型名>,并继续渲染它的子组件,不会整块崩掉。所以看到虚线框,就是类型名拼错或用了不存在的组件(例如 ProgressBar —— 目录里没有这个组件)。
完整示例
账户状态面板
数据表格
注意headers / rows 的形状——这是最常写错的地方:
列表
关键数值
失败与对策
最佳实践
- 属性一律放
props,这是所有静默失败的第一来源。 - 用 Card 做顶层容器,逻辑相关的组件放进同一个 Card 形成视觉单元。
- 嵌套别超过 3 层,深层布局既脆弱又难读。
- 只用它呈现,不依赖它交互——需要用户决策时用文字提问。
- 要图表 / 3D / 动画走
visualize,A2UI 只有这 16 个预定义组件。 - 面板之后补一句话总结,A2UI 是叠加的展示层,不替代解释。
核对日期 2026-08-12。来源:
apps/web/src/lib/a2ui/{definitions.ts,renderers.tsx}、apps/web/src/components/agent/chat-area/card/A2uiSurfaceCard.tsx、packages/types/src/a2ui.ts、services/agent-runtime/src/plugins/builtin/visualize/tools/render_ui.py。相关
可视化插件
自由 HTML / Canvas / WebGL 渲染面
插件全表
28 个内置插件的完整清单

