A2UI 与 A2A 协议扩展规范 v1.0:在 Agent 间传输流式交互 UI 的完整实现指南
【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui
本指南面向所有需要实现 A2UI A2A 扩展的开发者,系统讲解如何在 A2A(Agent-to-Agent)协议之上叠加 A2UI v1.0,让 Agent 能向渲染器(Renderer)发送流式的、可交互的用户界面,并接收来自渲染器的用户动作事件。读完本文,你将掌握扩展 URI 的约定、AgentCard 能力声明、HTTP/gRPC 两种传输下的扩展激活方式、双向元数据协商,以及 A2UI 消息的DataPart数据编码与逐条处理规则,并能在 Python Agent SDK 的源码与规范 JSON Schema 中找到每一步的落点与验证依据。
A2UI A2A 扩展是什么
A2UI(Agent-to-Agent UI)是 A2A 协议的一个官方扩展,它定义了一种数据格式,让 Agent 能够把流式的、可交互的用户界面直接发送给渲染器显示。与传统的一次性渲染整页 UI 不同,A2UI 允许 Agent 通过消息流(例如createSurface、updateComponents、action)渐进式地构建和更新界面,同时把用户的交互动作实时回传给 Agent。
该扩展的激活是可选的:渲染器与 Agent 可以通过 A2A 消息中的message.metadata["a2uiRendererCapabilities"]自行协商 A2UI 支持能力——这条元数据由渲染器附加在每条发往 Agent 的 A2A 消息上,包含其支持的协议版本与目录(Catalog)。规范同时鼓励 Agent 在其 AgentCard 中主动宣告 A2UI 能力,因为渲染器可能依赖该宣告来决定是否发送a2uiRendererCapabilities,但这一宣告并非强制要求。
该扩展规范对应 A2UI v1.0(草案阶段曾称 v0.10),基础协议部分请参阅 v1.0 Protocol Specification。
扩展 URI:版本协商的规范锚点
本扩展的规范 URI 为:
https://a2ui.org/a2a-extension/a2ui/v1.0该 URI 是渲染器与 Agent 之间传达协议版本的方式,版本号(v1.0)被显式编码在 URI 中。渲染器请求这个特定 URI,即表示它支持 v1.0 的 schema 格式。
在 Python SDK 的 extension.py 中,可以看到该约定的实现:A2UI_EXTENSION_BASE_URI = "https://a2ui.org/a2a-extension/a2ui",get_a2ui_extension_uri(version)将其与/v{version}拼接生成完整 URI,get_a2ui_extension_uri_version()则反向从 URI 中剥离出版本字符串。由于版本被编码在 URI 里,SDK 可以通过 版本协商逻辑(_select_newest_a2ui_extension,基于packaging.version对匹配到的扩展 URI 取版本号最大者)在渲染器请求与 Agent 宣告的扩展之间自动选择最新可用版本,从而支持多版本共存的平滑演进。
在 AgentCard 中声明 A2UI 能力
Agent 被鼓励在 AgentCard 的AgentCapabilities.extensions列表中宣告其 A2UI 能力。该宣告是可选的,作用是通知渲染器是否应向该 Agent 发送message.metadata["a2uiRendererCapabilities"]。params对象定义了 Agent 具体的 UI 支持范围,其结构直接对应 Agent Capabilities Schema。
规范的 AgentCard 示例:
{ "name": "Dashboard Agent", "description": "Agent capable of generating dynamic UI dashboards.", "capabilities": { "extensions": [ { "uri": "https://a2ui.org/a2a-extension/a2ui/v1.0", "description": "Ability to render A2UI v1.0", "required": false, "params": { "supportedCatalogIds": [ "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json", "https://my-company.com/a2ui/v1.0/my_custom_catalog.json" ], "acceptsInlineCatalogs": true } } ] } }params对象对应agent_capabilities.jsonschema 中的v1.0对象,包含两个可选字段:
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
supportedCatalogIds | string[] | 每个字符串是一个标识 Agent 能够为其生成内容的 Catalog Definition Schema 的 ID。注意:它不一定是一个可解析的 URI,只是目录标识符 | 无(可选) |
acceptsInlineCatalogs | boolean | 表示 Agent 是否接受渲染器a2uiRendererCapabilities中的inlineCatalogs数组 | false(省略即默认) |
从 schema 可见,v1.0是required字段,且整个对象结构中多个目录可以在同一个 surface 中混合使用。在 extension.py 中,get_a2ui_agent_extension()帮助函数会按此结构构造AgentExtension:仅当accepts_inline_catalogs为真时才写入该字段(保持省略即默认false的语义),仅当提供了supported_catalog_ids时才写入目录列表,保证声明的精简与规范一致。
A2A 扩展激活
激活 A2UI 扩展是可选的,渲染器与 Agent 的协商通道是:
- 渲染器在
message.metadata["a2uiRendererCapabilities"]中携带能力对象,Agent 据此确定受支持的 A2UI 协议版本与目录; - Agent 在返回的 A2A
DataPart.data.metadata["mimeType"] = "application/a2ui+json"中表明载荷包含 A2UI 消息,渲染器据此识别。
不强制显式激活,但渲染器仍可使用传输层定义的 A2A 扩展激活机制来显式激活该扩展。注意:不要使用accepted_output_modes: ['a2ui']来触发 A2UI,那并非 A2UI 标准。
HTTP/JSON-RPC 传输
在 JSON-RPC/HTTP 传输下,通过X-A2A-ExtensionsHTTP 头携带扩展 URI 激活扩展:
POST /v1/messages HTTP/1.1 Host: agent.example.com X-A2A-Extensions: https://a2ui.org/a2a-extension/a2ui/v1.0 Content-Type: application/json { "message": { "parts": [ { "text": "Hello, show me the dashboard" } ] } }Agent 端解析该扩展 URI 的完整流程见 extension.py:try_activate_a2ui_extension()先从RequestContext.requested_extensions与message.extensions两个来源收集以A2UI_EXTENSION_BASE_URI开头的请求扩展,再与 AgentCard 中宣告的扩展求交集,最后通过_select_newest_a2ui_extension()选出最新版本调用context.add_activated_extension(selected_uri)完成激活并返回版本字符串;任一环节不匹配则返回None(未激活)。
gRPC 传输
在 gRPC 传输下,渲染器将扩展 URI 放入 A2AsendMessageParams.metadata["X-A2A-Extensions"]:
{ "metadata": { "X-A2A-Extensions": "https://a2ui.org/a2a-extension/a2ui/v1.0" }, "message": { "parts": [ { "text": "Hello, show me the dashboard" } ] } }Renderer 到 Agent 的元数据
渲染器通过 A2A 消息附加a2uiRendererCapabilities和a2uiRendererDataModel两条元数据,向 Agent 传达其状态与支持的目录。
a2uiRendererCapabilities
渲染器在sendMessageRequest.message["a2uiRendererCapabilities"]中携带 Renderer Capabilities Schema,用于宣告自身支持的目录。此外,渲染器在运行时通过读取活动目录定义中的配置,来确定某个函数的执行边界(例如rendererOnly状态——该函数只能在渲染器本地执行还是需要回传 Agent)。
{ "message": { "parts": [ { "text": "Show me the dashboard." } ], "metadata": { "a2uiRendererCapabilities": { "v1.0": { "supportedCatalogIds": [ "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json", "https://my-company.com/a2ui/v1.0/my_custom_catalog.json" ] } } } } }对照 renderer_capabilities.json 可知:v1.0.supportedCatalogIds是必填字段,每个字符串标识渲染器支持的组件/函数目录,多个目录可在同一 surface 中混用;v1.0.inlineCatalogs是可选字段,为内联目录定义数组(可同时包含组件与函数),且仅当 Agent 宣告acceptsInlineCatalogs: true时才应提供。
a2uiRendererDataModel
当某个 surface 启用了 Data Model Sync 时,渲染器会在每一条消息上附加sendMessageRequest.message["a2uiRendererDataModel"],其结构遵循 Renderer Data Model Schema。该数据模型为 Agent 提供最新的 UI 状态,用于双向数据同步。更详细的机制见 Actions Guide。
{ "message": { "parts": [ { "text": "Submit the form." } ], "metadata": { "a2uiRendererDataModel": { "version": "v1.0", "surfaces": { "main_surface_id": { "user_id": "12345", "email": "user@example.com" } } } } } }从 renderer_data_model.json 的 schema 定义看:version被约束为常量"v1.0",surfaces是一个 surfaceId 到其当前数据模型的映射(值为任意标准 JSON 对象),二者皆为必填,且additionalProperties被禁止,结构非常严格。
数据编码:DataPart与application/a2ui+json
Agent 与渲染器将 A2UI 消息编码为 A2A 的DataPart。标识一个DataPart包含 A2UI 数据的关键元数据是:
DataPart.data.metadata["mimeType"] = "application/a2ui+json"DataPart的data字段是一个A2UI JSON 消息数组(如createSurface、updateComponents、action),必须是数组形式,不能是单个对象。
处理规则
data中的消息列表不是事务单元。接收方(渲染器与 Agent)必须按顺序逐条处理该列表中的消息:
- 若列表中某条消息校验或应用失败(如 schema 违规、无效引用),接收方应该针对该条消息记录/上报错误,并必须继续处理列表中剩余的其余消息;
- 原子性仅保证到单条消息级别;
- 为了更好的用户体验,渲染器不应在列表内所有消息处理完成前重绘 UI,以避免中间状态闪烁。
Agent 到渲染器的消息
当 Agent 向渲染器(或作为渲染器角色的其他 Agent)发送消息时,data载荷必须通过 Agent-to-Renderer Message List Schema 校验——该列表 schema 的每一项都引用 Agent-to-Renderer 消息 schema。
{ "data": [ { "version": "v1.0", "createSurface": { "surfaceId": "example_surface", "catalogId": "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json" } }, { "version": "v1.0", "updateComponents": { "surfaceId": "example_surface", "components": [ { "id": "root", "component": "Text", "text": "Hello!" } ] } } ], "kind": "data", "metadata": { "mimeType": "application/a2ui+json" } }从 agent_to_renderer.json 的oneOf定义看,Agent 到渲染器的消息共有6 种类型:
| 消息类型 | 核心字段 | 语义要点 |
|---|---|---|
createSurface | surfaceId(必填)、catalogId、sendDataModel、components、dataModel、metadata | 创建并开始渲染新 surface;隐式实例化规范Surface容器组件(child: "root");surfaceId 在渲染器生命周期内必须全局唯一,创建已有 ID 是错误;默认sendDataModel为false,设为true时渲染器将在后续每条 A2A 消息元数据中回传该 surface 的完整数据模型 |
updateComponents | surfaceId、components(均必填) | 用新组件集更新已有 surface,可多次发送;组件列表中必须有一个id为root的组件作为组件树根;发送前必须已createSurface |
updateDataModel | surfaceId、value(均必填)、path(可选) | 更新已有 surface 的数据模型;path形如/user/name,省略或为/表示整个数据模型;将value显式设为null表示删除该路径的键/值 |
deleteSurface | surfaceId(必填) | 删除指定 surface;发送前必须已createSurface |
callRendererFunction | functionCallId、callFunction(均必填,且callFunction内catalogId必填) | 请渲染器在本地代表 Agent 执行函数;渲染器必须将functionCallId原样复制进响应 |
agentFunctionResponse | agentFunctionResponse(必填) | 向渲染器返回FunctionResponse |
Renderer 到 Agent 的事件
渲染器(或转发事件的 Agent)向 Agent 发送消息时,同样使用application/a2ui+jsonMIME 类型的DataPart,但data载荷必须通过 Renderer-to-Agent Message List Schema 校验(其每一项引用 Renderer-to-Agent 消息 schema)。
{ "data": [ { "version": "v1.0", "action": { "name": "submit_form", "surfaceId": "contact_form_1", "sourceComponentId": "submit_button", "timestamp": "2026-01-15T12:00:00Z", "context": { "email": "user@example.com" } } } ], "kind": "data", "metadata": { "mimeType": "application/a2ui+json" } }renderer_to_agent.json 定义渲染器到 Agent 的消息共有4 种类型(version均必填且恒为"v1.0",每条消息恰好两个属性):
| 消息类型 | 核心字段 | 语义要点 |
|---|---|---|
action | name、surfaceId、sourceComponentId、timestamp(ISO 8601)、context(均必填);userMessage、metadata可选 | 上报组件触发的用户动作;name取自组件action.event.name;context为解析所有数据绑定后的键值对;timestamp为事件发生时刻 |
callAgentFunction | surfaceId、functionCallId、callFunction(均必填) | 请求 Agent远程代表渲染器执行函数;Agent 必须将functionCallId原样复制进响应 |
rendererFunctionResponse | rendererFunctionResponse(必填) | 渲染器返回函数执行结果 |
error | 视类型而定 | 上报渲染器侧错误。Validation Failed 类错误code限定为VALIDATION_FAILED、UNALLOWED_PARENT、UNALLOWED_CHILD之一,并要求path(JSON Pointer,如/components/0/text)、message、surfaceId;Generic 类错误code不得为上述三个值,且surfaceId与functionCallId二选一必填 |
相关规范资源
- 基础协议:A2UI Protocol v1.0
- 扩展规范原始源文件:specification/v1_0/extensions/a2a/docs/a2ui_extension_specification.md
- 能力与数据模型 Schema:agent_capabilities.json、renderer_capabilities.json、renderer_data_model.json
- 消息列表 Schema:agent_to_renderer_list.json、renderer_to_agent_list.json(及各自的单条消息 Schema agent_to_renderer.json、renderer_to_agent.json)
- 基础目录定义:basic 目录(v1.0)
- SDK 实现参考:extension.py(扩展 URI 与激活协商)、parts.py(DataPart 编码)、sdks_spec.md
- 概念延伸:Actions Guide、Data Binding 概念
【免费下载链接】a2ui项目地址: https://gitcode.com/GitHub_Trending/a2/a2ui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考