Skip to content

消息类型

本参考文档提供了所有 A2UI 消息类型的详细文档。

消息格式

所有 A2UI 消息都是作为 JSON Lines (JSONL) 发送的 JSON 对象。每行只包含一条消息,每条消息只包含以下四个键之一:

  • beginRendering
  • surfaceUpdate
  • dataModelUpdate
  • deleteSurface

beginRendering

向客户端发出信号,表明它有足够的信息来执行 Surface 的初始渲染。

Schema

{
  beginRendering: {
    surfaceId: string;      // Required: Unique surface identifier
    root: string;           // Required: The ID of the root component to render
    catalogId?: string;     // Optional: URL of component catalog
    styles?: object;        // Optional: Styling information
  }
}

属性

属性 类型 必需 描述
surfaceId string 此 Surface 的唯一标识符。
root string 此 Surface 的 UI 树根组件的 id
catalogId string 组件目录的标识符。如果省略,默认为 v0.8 标准目录。
styles object 目录定义的 UI 样式信息。

示例

基本渲染信号:

{
  "beginRendering": {
    "surfaceId": "main",
    "root": "root-component"
  }
}

带有自定义目录:

{
  "beginRendering": {
    "surfaceId": "custom-ui",
    "root": "root-custom",
    "catalogId": "https://my-company.com/a2ui/v0.8/my_custom_catalog.json"
  }
}

使用说明

  • 必须在客户端接收到根组件及其初始子组件的组件定义后发送。
  • 客户端应缓冲 surfaceUpdatedataModelUpdate 消息,并在收到相应的 beginRendering 消息后才渲染 Surface 的 UI。

surfaceUpdate

在 Surface 中添加或更新组件。

Schema

{
  surfaceUpdate: {
    surfaceId: string;        // Required: Target surface
    components: Array<{       // Required: List of components
      id: string;             // Required: Component ID
      component: {            // Required: Wrapper for component data
        [ComponentType]: {    // Required: Exactly one component type
          ...properties       // Component-specific properties
        }
      }
    }>
  }
}

属性

属性 类型 必需 描述
surfaceId string 要更新的 Surface ID
components array 组件定义数组

组件对象

components 数组中的每个对象必须具有:

  • id (string, 必需): Surface 内的唯一标识符
  • component (object, 必需): 包含且仅包含一个键(组件类型,例如 Text, Button)的包装对象。

示例

单个组件:

{
  "surfaceUpdate": {
    "surfaceId": "main",
    "components": [
      {
        "id": "greeting",
        "component": {
          "Text": {
            "text": {"literalString": "Hello, World!"},
            "usageHint": "h1"
          }
        }
      }
    ]
  }
}

多个组件(邻接表):

{
  "surfaceUpdate": {
    "surfaceId": "main",
    "components": [
      {
        "id": "root",
        "component": {
          "Column": {
            "children": {"explicitList": ["header", "body"]}
          }
        }
      },
      {
        "id": "header",
        "component": {
          "Text": {
            "text": {"literalString": "Welcome"}
          }
        }
      },
      {
        "id": "body",
        "component": {
          "Card": {
            "child": "content"
          }
        }
      },
      {
        "id": "content",
        "component": {
          "Text": {
            "text": {"path": "/message"}
          }
        }
      }
    ]
  }
}

更新现有组件:

{
  "surfaceUpdate": {
    "surfaceId": "main",
    "components": [
      {
        "id": "greeting",
        "component": {
          "Text": {
            "text": {"literalString": "Hello, Alice!"},
            "usageHint": "h1"
          }
        }
      }
    ]
  }
}

具有 id: "greeting" 的组件被更新(而不是复制)。

使用说明

  • 必须在 beginRendering 消息中指定一个组件作为 root,作为树的根。
  • 组件形成邻接表(带有 ID 引用的扁平结构)。
  • 发送具有现有 ID 的组件会更新该组件。
  • 子组件通过 ID 引用。
  • 组件可以增量添加(流式传输)。

错误

错误 原因 解决方案
Surface 未找到 surfaceId 不存在 确保对给定 Surface 始终使用唯一的 surfaceId。Surface 在首次更新时隐式创建。
无效的组件类型 未知的组件类型 检查协商的目录中是否存在该组件类型。
无效的属性 该类型不存在此属性 对照目录 Schema 进行验证。
循环引用 组件引用自身作为子组件 修复组件层次结构。

dataModelUpdate

更新组件绑定的数据模型。

Schema

{
  dataModelUpdate: {
    surfaceId: string;      // Required: Target surface
    path?: string;          // Optional: Path to a location in the model
    contents: Array<{       // Required: Data entries
      key: string;
      valueString?: string;
      valueNumber?: number;
      valueBoolean?: boolean;
      valueMap?: Array<{...}>;
    }>
  }
}

属性

属性 类型 必需 描述
surfaceId string 要更新的 Surface ID。
path string 数据模型中位置的路径(例如 'user')。如果省略,则更新应用于根。
contents array 作为邻接表的数据条目数组。每个条目都有一个 key 和一个类型的 value* 属性。

contents 邻接表

contents 数组是键值对列表。数组中的每个对象必须有一个 key 和且仅有一个 value* 属性(valueString, valueNumber, valueBoolean, 或 valueMap)。这种结构对 LLM 友好,避免了从泛型 value 字段推断类型的问题。

示例

初始化整个模型:

如果省略 pathcontents 将替换 Surface 的整个数据模型。

{
  "dataModelUpdate": {
    "surfaceId": "main",
    "contents": [
      {
        "key": "user",
        "valueMap": [
          { "key": "name", "valueString": "Alice" },
          { "key": "email", "valueString": "alice@example.com" }
        ]
      },
      { "key": "items", "valueMap": [] }
    ]
  }
}

更新嵌套属性:

如果提供了 pathcontents 将更新该位置的数据。

{
  "dataModelUpdate": {
    "surfaceId": "main",
    "path": "user",
    "contents": [
      { "key": "email", "valueString": "alice@newdomain.com" }
    ]
  }
}

这将更改 /user/email 而不影响 /user/name

使用说明

  • 数据模型是每个 Surface 独有的。
  • 组件在其绑定的数据更改时自动重新渲染。
  • 优先更新特定路径,而不是替换整个模型。
  • 数据模型是一个纯 JSON 对象。
  • 任何数据转换(例如,格式化日期)必须在发送 dataModelUpdate 消息之前由服务器完成。

deleteSurface

删除 Surface 及其所有组件和数据。

Schema

{
  deleteSurface: {
    surfaceId: string;        // Required: Surface to delete
  }
}

属性

属性 类型 必需 描述
surfaceId string 要删除的 Surface ID

示例

删除一个 Surface:

{
  "deleteSurface": {
    "surfaceId": "modal"
  }
}

删除多个 Surface:

{"deleteSurface": {"surfaceId": "sidebar"}}
{"deleteSurface": {"surfaceId": "content"}}

使用说明

  • 删除与 Surface 关联的所有组件
  • 清除 Surface 的数据模型
  • 客户端应从 UI 中移除 Surface
  • 删除不存在的 Surface 是安全的(无操作)
  • 在关闭模态框、对话框或导航离开时使用

错误

错误 原因 解决方案
(无 - 删除是幂等的)

消息顺序

要求

  1. beginRendering 必须在该 Surface 的初始 surfaceUpdate 消息之后。
  2. surfaceUpdate 可以在 dataModelUpdate 之前或之后。
  3. 不同 Surface 的消息是独立的。
  4. 多条消息可以增量更新同一个 Surface。

推荐顺序

{"surfaceUpdate": {"surfaceId": "main", "components": [...]}}
{"dataModelUpdate": {"surfaceId": "main", "contents": {...}}}
{"beginRendering": {"surfaceId": "main", "root": "root-id"}}

渐进式构建

{"surfaceUpdate": {"surfaceId": "main", "components": [...]}}  // Header
{"surfaceUpdate": {"surfaceId": "main", "components": [...]}}  // Body
{"beginRendering": {"surfaceId": "main", "root": "root-id"}} // Initial render
{"surfaceUpdate": {"surfaceId": "main", "components": [...]}}  // Footer (after initial render)
{"dataModelUpdate": {"surfaceId": "main", "contents": {...}}}   // Populate data

验证

所有消息都应根据以下内容进行验证:

延伸阅读