From 4b6062f82f4c79475529eca8562b3264e5dc3f76 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Mon, 24 Nov 2025 13:41:38 +1030 Subject: [PATCH 01/12] Update v0.8 spec with updated catalog negotiation style --- .../0.8/docs/a2ui_extension_specification.md | 130 ++++++---- specification/0.8/docs/a2ui_protocol.md | 225 ++++++++++++------ specification/0.8/json/README.md | 6 +- .../0.8/json/a2ui_client_capabilities.json | 22 ++ .../agent_card_a2ui_extension_params.json | 21 ++ specification/0.8/json/client_to_server.json | 41 +--- 6 files changed, 290 insertions(+), 155 deletions(-) create mode 100644 specification/0.8/json/a2ui_client_capabilities.json create mode 100644 specification/0.8/json/agent_card_a2ui_extension_params.json diff --git a/specification/0.8/docs/a2ui_extension_specification.md b/specification/0.8/docs/a2ui_extension_specification.md index 91cd39636..d9504482e 100644 --- a/specification/0.8/docs/a2ui_extension_specification.md +++ b/specification/0.8/docs/a2ui_extension_specification.md @@ -1,55 +1,97 @@ -# A2UI (Agent-to-Agent UI) Extension Spec +# A2UI (Agent to UI) Extension Specification ## Overview -This extension implements the A2UI (Agent-to-Agent UI) spec, a format for agents to send streaming, interactive user interfaces to clients. +This document specifies the A2UI extension for the Agent-to-Agent (A2A) protocol. This extension allows agents to send streaming, interactive user interfaces to clients that can render them. ## Extension URI -The URI of this extension is https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md - -This is the only URI accepted for this extension. +The URI for this version of the extension is: `https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md` ## Core Concepts The A2UI extension is built on three main concepts: -Surfaces: A "Surface" is a distinct, controllable region of the client's UI. The spec uses a surfaceId to direct updates to specific surfaces (e.g., a main content area, a side panel, or a new chat bubble). This allows a single agent stream to manage multiple UI areas independently. - -Catalog Definition Document: The a2ui extension is component-agnostic. All UI components (e.g., Text, Row, Button) and their stylings are defined in a separate Catalog Definition Schema. This allows clients and servers to negotiate which catalog to use. - -Schemas: The a2ui extension is defined by three primary JSON schemas: - -Catalog Definition Schema: A standard format for defining a library of components and styles. - -Server-to-Client Message Schema: The core wire format for messages sent from the agent to the client (e.g., surfaceUpdate, dataModelUpdate). - -Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., userAction, clientUiCapabilities). - -Agent Capability Declaration -Agents advertise their A2UI capabilities in their AgentCard within the AgentCapabilities.extensions list. The params object defines the agent's specific UI support, including which component catalogs it can generate and whether it accepts dynamic catalogs from the client. - -Example AgentExtension block: - -Parameter Definitions -params.supportedSchemas: (REQUIRED) An array of strings, where each string is a URI pointing to a component Catalog Definition Schema that the agent can generate. This could include the default catalog or custom catalogs or both. - -params.acceptsDynamicSchemas: (OPTIONAL) A boolean indicating if the agent can accept a clientUiCapabilities message containing a dynamicCatalog. If omitted, this defaults to false. - -Client Capability Declaration -The client-to-server spec includes a clientUiCapabilities message. If a client wishes to use a specific catalog (other than the server's default) or provide its own dynamic catalog, it MUST send this message after the connection is established and before the first user prompt. - -This message allows the client to specify either: - -A catalogUri: A URI for a known, shared catalog (which must be one of the supportedSchemas from the agent). - -A dynamicCatalog: An inline Catalog Definition Schema object. This is only allowed if the agent's acceptsDynamicSchemas capability is true. - -Extension Activation -Clients indicate their desire to use the A2UI extension by specifying it via the transport-defined A2A extension activation mechanism. - -For JSON-RPC and HTTP transports, this is indicated via the X-A2A-Extensions HTTP header. - -For gRPC, this is indicated via the X-A2A-Extensions metadata value. - -Activating this extension implies that the server can send A2UI-specific messages (like surfaceUpdate) and the client is expected to send A2UI-specific events (like userAction). +- **Surfaces**: A "Surface" is a distinct, controllable region of the client's UI. The protocol uses a `surfaceId` to direct updates to specific surfaces (e.g., a main content area, a side panel, or a new chat bubble). This allows a single agent stream to manage multiple UI areas independently. + +- **Catalog**: The A2UI extension is component-agnostic. All UI components (e.g., `Text`, `Row`, `Button`) and their properties are defined in a separate **Catalog**. This allows clients and servers to negotiate which set of components to use for rendering a UI. + +- **Schemas**: The A2UI protocol is formally defined by a set of JSON schemas, which describe the structure of catalogs, server-to-client messages, and client-to-server event payloads. + +## Agent Capability Declaration + +An agent advertises its ability to serve A2UI content by including an extension object in its A2A Agent Card. The `params` object within this extension defines the agent's specific UI generation capabilities. + +### Extension Parameters (`params`) + +- `supportedCatalogUris` (array of strings, required): A list of URIs that identify the component catalogs the agent can generate. These URIs are stable identifiers and should not be fetched at runtime. +- `acceptsInlineCatalog` (boolean, required): A flag indicating whether the agent can accept a complete, inline catalog definition from the client. + +**Example Agent Card Snippet:** + +```json +{ + "name": "My A2UI Agent", + "capabilities": { + "extensions": [ + { + "uri": "https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md", + "description": "Provides interactive UIs via the A2UI protocol.", + "required": false, + "params": { + "supportedCatalogUris": [ + "https://a2ui.org/catalogs/standard/0.8", + "https://my-company.com/a2ui/catalogs/custom/1.2" + ], + "acceptsInlineCatalog": true + } + } + ] + } +} +``` + +## Client Catalog Selection + +The A2UI protocol is **stateless** regarding catalog selection. The client **must** inform the server which catalog to use in **every** A2A `Message` it sends. This is done by including an `a2uiClientCapabilities` object in the `metadata` field of the A2A `Message`. + +This object must contain exactly one of the following properties: + +1. `catalogUri` (string): The URI of a catalog that the server has advertised in its `supportedCatalogUris` list. +2. `inlineCatalog` (object): A complete, inline catalog definition. This is only permitted if the agent's `acceptsInlineCatalog` capability is `true`. An inline catalog **replaces** the standard catalog; it is not additive. + +**Example A2A Message with Client Capabilities:** + +```json +{ + "messageId": "msg-123", + "metadata": { + "a2uiClientCapabilities": { + "catalogUri": "https://a2ui.org/catalogs/standard/0.8" + } + }, + "parts": [ + { + "data": { + "data": { + "userAction": { + "name": "find_restaurants", + "surfaceId": "s1", + "sourceComponentId": "c1", + "timestamp": "2025-11-24T09:59:58Z", + "context": { + "location": "Mountain View, CA" + } + } + } + } + } + ] +} +``` + +## Extension Activation + +Clients indicate their desire to use the A2UI extension by specifying its URI via the transport-defined A2A extension activation mechanism (e.g., the `X-A2A-Extensions` HTTP header). + +Activating this extension implies that the server can send A2UI-specific messages (like `surfaceUpdate`) in its response stream and the client is expected to send A2UI-specific event payloads (like `userAction`) in its requests. diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index dce19c02e..1a34181a5 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -68,7 +68,6 @@ Communication occurs via a JSON Lines (JSONL) stream. The client parses each lin Client-to-server communication for user interactions is handled separately via a JSON payload sent to a REST API. This message can be one of several types: - `userAction`: Reports a user-initiated action from a component. -- `clientUiCapabilities`: Informs the server about the client's capabilities, such as the component catalog it supports. - `error`: Reports a client-side error. This keeps the primary data stream unidirectional. @@ -84,11 +83,132 @@ The central philosophy of A2UI is the decoupling of three key elements: 2. **The Data Model (The State):** A server-provided JSON object containing the dynamic values that populate the UI, such as text, booleans, or lists. This is managed via `dataModelUpdate` messages. 3. **The Widget Registry (The "Catalog"):** A client-defined mapping of component types (e.g., "Row", "Text") to concrete, native widget implementations. This registry is **part of the client application**, not the protocol stream. The server must generate components that the target client's registry understands. -### 1.2. The JSONL Stream: The Unit of Communication +### 1.2. Catalog Negotiation + +A central concept in A2UI is the **Catalog**, which defines the contract between the server and client for what UI components can be rendered. Each client must select a single catalog to use for all UI surfaces, and it must inform the server of this choice with every request. + +#### 1.2.1. Principles of Catalog Negotiation + +- **Statelessness**: The server does not remember which catalog the client is using across different requests. The client must specify its chosen catalog in every A2A message it sends. +- **Client-Driven**: The client is in control of which catalog is used. +- **Immutability**: Catalogs are identified by URIs and are considered immutable. If a catalog definition changes, it must be given a new URI. +- **URIs as Identifiers**: Catalog URIs (e.g., `https://a2ui.org/catalogs/standard/0.8`) are stable identifiers. Neither the client nor the server should fetch catalog definitions from these URIs at runtime. + +#### 1.2.2. Server Catalog Advertisement + +The server advertises which catalogs it supports within its A2A **Agent Card**. This is done using the A2A extension mechanism. The server adds an A2UI extension object to its `capabilities` which lists the URIs of supported catalogs and indicates whether it accepts custom, inline catalogs. + +**Example Agent Card Snippet:** + +```json +{ + "name": "Restaurant Finder Agent", + "capabilities": { + "extensions": [ + { + "uri": "https://a2ui.org/ext/a2a-ui/v0.8", + "description": "This agent can render UIs using the A2UI protocol.", + "required": false, + "params": { + "supportedCatalogUris": [ + "https://a2ui.org/catalogs/standard/0.8", + "https://my-company.com/a2ui/catalogs/custom-internal/1.2" + ], + "acceptsInlineCatalog": true + } + } + ] + } +} +``` + +- `supportedCatalogUris`: A list of catalog identifier URIs that the server can generate UI for. +- `acceptsInlineCatalog`: A boolean indicating if the server allows the client to provide a complete catalog definition directly in a message. + +#### 1.2.3. Client Catalog Selection + +With every A2A `Message` sent to the server, the client must include an `a2uiClientCapabilities` object in the `metadata` field. This object tells the server which catalog to use when generating the UI response for that specific request. + +The `a2uiClientCapabilities` object must contain exactly one of the following: + +1. `catalogUri`: The URI of a catalog previously advertised by the server. +2. `inlineCatalog`: A complete catalog definition, which can only be used if the server advertised `acceptsInlineCatalog: true`. An inline catalog **replaces** the standard catalog; it is not additive. + +**Example A2A Message with `catalogUri`:** + +```json +{ + "messageId": "msg-123", + "metadata": { + "a2uiClientCapabilities": { + "catalogUri": "https://a2ui.org/catalogs/standard/0.8" + } + }, + "parts": [ + { + "data": { + "data": { + "userAction": { + "name": "find_restaurants", + "surfaceId": "s1", + "sourceComponentId": "c1", + "timestamp": "2025-11-24T09:59:58Z", + "context": { + "location": "Mountain View, CA" + } + } + } + } + } + ] +} +``` + +**Example A2A Message with `inlineCatalog`:** + +```json +{ + "messageId": "msg-124", + "metadata": { + "a2uiClientCapabilities": { + "inlineCatalog": { + "components": { + "SignaturePad": { + "type": "object", + "description": "A custom area for user signatures.", + "properties": { + "penColor": { "type": "string" }, + "required": { "type": "boolean" } + }, + "required": ["required"] + } + } + } + } + }, + "parts": [ + { + "data": { + "data": { + "userAction": { + "name": "sign_document", + "surfaceId": "s2", + "sourceComponentId": "c5", + "timestamp": "2025-11-24T10:04:00Z", + "context": {} + } + } + } + } + ] +} +``` + +### 1.3. The JSONL Stream: The Unit of Communication All UI descriptions are transmitted from the server to the client as a stream of JSON objects, formatted as JSON Lines (JSONL). Each line is a separate, compact JSON object representing a single message. This allows the client to parse and process each part of the UI definition as it arrives, enabling progressive rendering. -### 1.3. Surfaces: Managing Multiple UI Regions +### 1.4. Surfaces: Managing Multiple UI Regions A **Surface** is a contiguous portion of screen real estate into which a A2UI UI can be rendered. The protocol introduces the concept of a `surfaceId` to uniquely identify and manage these areas. This allows a single A2UI stream to control multiple, independent UI regions simultaneously. Each surface has a separate root component and a separate hierarchy of components. Each surface has a separate data model, to avoid collision of keys when working with a large number of surfaces. @@ -96,7 +216,7 @@ For example, in a chat application, each AI-generated response could be rendered The `surfaceId` is a property within each server-to-client message that directs changes to the correct area. It is used with messages like `beginRendering`, `surfaceUpdate`, `dataModelUpdate`, and `deleteSurface` to target a specific surface. -### 1.4. Data Flow Model +### 1.5. Data Flow Model The A2UI protocol is composed of a server-to-client stream describing UI and individual events sent to the server. The client consumes the stream, builds the UI, and renders it. Communication occurs via a JSON Lines (JSONL) stream, typically transported over **Server-Sent Events (SSE)**. @@ -108,7 +228,7 @@ The A2UI protocol is composed of a server-to-client stream describing UI and ind 3. **Render Signal:** The server sends a `beginRendering` message with the `root` component's ID. This prevents a "flash of incomplete content." The client buffers incoming components and data but waits for this explicit signal before attempting the first render, ensuring the initial view is coherent. 4. **Client-Side Rendering:** The client, now in a "ready" state, starts at the `root` component. It recursively walks the component tree by looking up component IDs in its buffer. It resolves any data bindings against the data model and uses its `WidgetRegistry` to instantiate native widgets. -5. **User Interaction and Event Handling:** The user interacts with a rendered widget (e.g., taps a button). The client constructs a `userAction` JSON payload, resolving any data bindings from the component's `action.context`. It sends this payload to the server via an A2A message. +5. **User Interaction and Event Handling:** The user interacts with a rendered widget (e.g., taps a button). The client constructs a `userAction` JSON payload, resolving any data bindings from the component's `action.context`. It sends this payload to the server via an A2A message, including the required `a2uiClientCapabilities` in the metadata. 6. **Dynamic Updates:** The server processes the `userAction`. If the UI needs to change in response, the server sends new `surfaceUpdate` and `dataModelUpdate` messages over the original SSE stream. As these arrive, the client updates its component buffer and data model, and the UI re-renders to reflect the changes. The server can also send `deleteSurface` to remove a UI region. ```mermaid @@ -131,7 +251,7 @@ sequenceDiagram Note over Client: 8. User interacts with UI (e.g., clicks button) Client->>Client: 9. Construct userAction payload - Client->>+Server: 10. A2A Message sent to server (Client Event JSON with userAction) + Client->>+Server: 10. A2A Message sent to server (with a2uiClientCapabilities in metadata) Server-->>-Client: 11. OK loop Dynamic Updates in Response to Event @@ -142,7 +262,7 @@ sequenceDiagram end ``` -### 1.5. Full Stream Example +### 1.6. Full Stream Example The following is a complete, minimal example of a JSONL stream that renders a user profile card. @@ -169,7 +289,7 @@ A2UI's component model is designed for flexibility, separating the protocol from ### 2.1. The Catalog: Defining Components -Unlike previous versions with a fixed component set, A2UI now defines components in a **Catalog**. A catalog is a schema that defines the available component types (e.g., `Row`, `Text`) and their supported properties. This allows for different clients to support different sets of components, including custom ones. The server must generate `surfaceUpdate` messages that conform to the component catalog understood by the client. Clients can inform the server of the catalog they support using the `clientUiCapabilities` message. +Unlike previous versions with a fixed component set, A2UI now defines components in a **Catalog**. A catalog is a schema that defines the available component types (e.g., `Row`, `Text`) and their supported properties. This allows for different clients to support different sets of components, including custom ones. The server must generate `surfaceUpdate` messages that conform to the component catalog selected by the client. The mechanism for this is detailed in the **Catalog Negotiation** section. #### Schemas for Developers @@ -414,7 +534,7 @@ While the server-to-client UI definition is a one-way stream (e.g., over SSE), u ### 5.1. The Client Event Message -The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction`, `clientUiCapabilities`, or `error`. +The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction` or `error`. ### 5.2. The `userAction` Message @@ -430,60 +550,11 @@ The `userAction` object has the following structure: The process for resolving the `action.context` remains the same: the client iterates over the `context` array, resolves all literal or data-bound values, and constructs the `context` object. -### 5.3. The `clientUiCapabilities` Message - -This message is sent by the client to inform the server about its capabilities. This is crucial for supporting different component sets, allowing the server to generate UI that is compatible with the client. The message must contain exactly one of the following properties: `catalogUri` or `dynamicCatalog`. - -- `catalogUri`: A URI pointing to a predefined component catalog schema that the client supports. -- `dynamicCatalog`: An inline JSON object, conforming to the Catalog Schema, that defines the client's supported components. This is useful for development or for clients with highly custom component sets. - -```mermaid -sequenceDiagram - participant Client - participant Server - Client->>+Server: POST /event (clientUiCapabilities with catalog) - Server-->>-Client: HTTP 200 OK - Note over Server: Server now knows which catalog to use. - Server->>+Client: SSE Connection (JSONL Stream using client's catalog) - Client-->>-Server: (Renders UI based on custom/specified catalog) -``` - -#### `dynamicCatalog` - -The `dynamicCatalog` property allows the client to send an inline JSON object that defines its entire supported component set. This is especially useful for development or for clients with highly custom components. The object must conform to the Catalog Schema, containing `components`. - -- `components`: An object where each key is the name of a component (e.g., `"MyCustomCard"`) and the value is a valid JSON object schema defining the properties for that component. - -**Example of a `clientUiCapabilities` message:** - -```json -{ - "clientUiCapabilities": { - "dynamicCatalog": { - "components": { - "MyCustomCard": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "child": { - "type": "string" - } - }, - "required": ["title", "child"] - } - } - } - } -} -``` - -### 5.4. The `error` Message +### 5.3. The `error` Message This message provides a feedback mechanism for the server. It is sent when the client encounters an error, for instance, during UI rendering or data binding. The content of the object is flexible and can contain any relevant error information. -### 5.5. Event Flow Example (`userAction`) +### 5.4. Event Flow Example (`userAction`) 1. **Component Definition** (from `surfaceUpdate`): @@ -537,20 +608,34 @@ This message provides a feedback mechanism for the server. It is sent when the c 3. **User Action:** The user taps the "submit_btn" button. 4. **Client-Side Resolution:** The client resolves the `action.context`. -5. **Client-to-Server Request:** The client sends a `POST` request to `https://api.example.com/handle_event` with the following JSON body: +5. **Client-to-Server Request:** The client sends an A2A `Message` to the server. The `userAction` is placed inside the `data` object of a `Part`, and the `metadata` contains the required `a2uiClientCapabilities`. ```json { - "userAction": { - "name": "submit_form", - "surfaceId": "main_content_area", - "sourceComponentId": "submit_btn", - "timestamp": "2025-09-19T17:05:00Z", - "context": { - "userInput": "User input text", - "formId": "f-123" + "messageId": "msg-125", + "metadata": { + "a2uiClientCapabilities": { + "catalogUri": "https://a2ui.org/catalogs/standard/0.8" } - } + }, + "parts": [ + { + "data": { + "data": { + "userAction": { + "name": "submit_form", + "surfaceId": "main_content_area", + "sourceComponentId": "submit_btn", + "timestamp": "2025-09-19T17:05:00Z", + "context": { + "userInput": "User input text", + "formId": "f-123" + } + } + } + } + } + ] } ``` diff --git a/specification/0.8/json/README.md b/specification/0.8/json/README.md index 75d0d7c34..dbcdc7203 100644 --- a/specification/0.8/json/README.md +++ b/specification/0.8/json/README.md @@ -6,10 +6,14 @@ This directory contains the formal JSON Schema definitions for the A2UI protocol - `server_to_client.json`: This is the core, catalog-agnostic schema for messages sent from the server to the client. It defines the four main message types (`beginRendering`, `surfaceUpdate`, `dataModelUpdate`, `deleteSurface`) and their structure. In this schema, the `component` object within a `surfaceUpdate` message is generic (`"additionalProperties": true`), allowing any component definitions to be passed. -- `client_to_server.json`: This schema defines the structure for event messages sent from the client to the server. This includes user-initiated actions (`userAction`), error reporting (`error`), and the crucial `clientUiCapabilities` message, which allows a client to inform the server about the component catalog it supports. +- `client_to_server.json`: This schema defines the structure for event message payloads sent from the client to the server within an A2A `Message`. This includes user-initiated actions (`userAction`) and error reporting (`error`). Note that catalog negotiation is no longer handled by a message in this payload. - `catalog_description_schema.json`: This is a meta-schema that defines the structure of an A2UI component catalog. A catalog consists of a `components` object and a `styles` object, where each key is a component/style name and the value is a JSON schema defining its properties. This allows for the creation of custom component sets. - `standard_catalog_definition.json`: This file is a concrete implementation of a catalog, conforming to the `catalog_description_schema.json`. It defines the standard set of components (e.g., `Text`, `Image`, `Row`, `Card`) and styles that are part of the baseline A2UI specification. - `server_to_client_with_standard_catalog.json`: This is a resolved, LLM-friendly version of the server-to-client schema. It is generated by combining `server_to_client.json` with the `standard_catalog_definition.json`. In this version, the generic `component` object is replaced with a strict `oneOf` definition that includes every component from the standard catalog. This provides a complete, strictly-typed schema that is ideal for LLMs to use for generating valid A2UI messages without ambiguity. + +- `agent_card_a2ui_extension_params.json`: Defines the schema for the `params` object within the A2UI extension in an A2A agent card. This is how a server advertises its supported catalog URIs and whether it accepts inline catalogs. + +- `a2ui_client_capabilities.json`: Defines the schema for the `a2uiClientCapabilities` object, which is included in the `metadata` field of every A2A message from the client. This is how the client informs the server which catalog to use for a given request. diff --git a/specification/0.8/json/a2ui_client_capabilities.json b/specification/0.8/json/a2ui_client_capabilities.json new file mode 100644 index 000000000..ee7e2295d --- /dev/null +++ b/specification/0.8/json/a2ui_client_capabilities.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A2UI Client Capabilities", + "description": "Schema for the 'a2uiClientCapabilities' object, which is included in the 'metadata' field of every A2A message from the client to the server.", + "type": "object", + "properties": { + "catalogUri": { + "type": "string", + "format": "uri", + "description": "The URI of the custom catalog to use. This must be one of the URIs advertised by the server in its agent card." + }, + "inlineCatalog": { + "$ref": "catalog_description_schema.json", + "description": "An inline catalog definition. This can only be provided if the server's agent card indicates it accepts inline catalogs." + } + }, + "oneOf": [ + { "required": ["catalogUri"] }, + { "required": ["inlineCatalog"] } + ], + "additionalProperties": false +} diff --git a/specification/0.8/json/agent_card_a2ui_extension_params.json b/specification/0.8/json/agent_card_a2ui_extension_params.json new file mode 100644 index 000000000..4d76245d0 --- /dev/null +++ b/specification/0.8/json/agent_card_a2ui_extension_params.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A2UI Agent Card Extension Parameters", + "description": "Schema for the 'params' object of the A2UI extension within an A2A agent card.", + "type": "object", + "properties": { + "supportedCatalogUris": { + "type": "array", + "description": "A list of URIs for the A2UI catalogs supported by this agent.", + "items": { + "type": "string", + "format": "uri" + } + }, + "acceptsInlineCatalog": { + "type": "boolean", + "description": "Whether the agent accepts inline catalog definitions from the client." + } + }, + "required": ["supportedCatalogUris", "acceptsInlineCatalog"] +} diff --git a/specification/0.8/json/client_to_server.json b/specification/0.8/json/client_to_server.json index db082c805..5bd95fbd2 100644 --- a/specification/0.8/json/client_to_server.json +++ b/specification/0.8/json/client_to_server.json @@ -1,6 +1,6 @@ { "title": "A2UI (Agent to UI) Client-to-Server Event Schema", - "description": "Describes a JSON payload for a client-to-server event message.", + "description": "Describes the JSON payload for a client-to-server event message. Note that these messages are payloads within an A2A `Message` object. Catalog negotiation is handled via the `a2uiClientCapabilities` object in the A2A `Message.metadata` field, not within this payload.", "type": "object", "minProperties": 1, "maxProperties": 1, @@ -40,44 +40,6 @@ "context" ] }, - "clientUiCapabilities": { - "type": "object", - "description": "Informs the server about the client's capabilities, such as the component catalog it supports. Exactly ONE of the properties in this object must be set.", - "properties": { - "catalogUri": { - "type": "string", - "format": "uri", - "description": "A URI pointing to a predefined component catalog schema that the server advertized, and the client supports." - }, - "dynamicCatalog": { - "type": "object", - "description": "An inline JSON object that defines the client's supported components.", - "properties": { - "components": { - "type": "object", - "title": "Components", - "description": "A map where each key is a component name and the value is a JSON Schema defining an object containing its properties.", - "additionalProperties": { - "$ref": "https://json-schema.org/draft/2020-12/schema" - } - }, - "styles": { - "title": "Styles", - "description": "A schema that defines a catalog of A2UI styles. Each key is a style name, and each value is the JSON schema for that style's properties.", - "type": "object", - "additionalProperties": { - "$ref": "https://json-schema.org/draft/2020-12/schema" - } - } - }, - "required": ["components"] - } - }, - "oneOf": [ - { "required": ["catalogUri"] }, - { "required": ["dynamicCatalog"] } - ] - }, "error": { "type": "object", "description": "Reports a client-side error. The content is flexible.", @@ -86,7 +48,6 @@ }, "oneOf": [ { "required": ["userAction"] }, - { "required": ["clientUiCapabilities"] }, { "required": ["error"] } ] } From 7d0afbf1f5f85ce765acc5a47ce2c75bbe07d4bf Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Mon, 24 Nov 2025 14:22:55 +1030 Subject: [PATCH 02/12] Minor fixes --- specification/0.8/json/agent_card_a2ui_extension_params.json | 3 +-- specification/0.8/json/client_to_server.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/specification/0.8/json/agent_card_a2ui_extension_params.json b/specification/0.8/json/agent_card_a2ui_extension_params.json index 4d76245d0..1dfd3c124 100644 --- a/specification/0.8/json/agent_card_a2ui_extension_params.json +++ b/specification/0.8/json/agent_card_a2ui_extension_params.json @@ -16,6 +16,5 @@ "type": "boolean", "description": "Whether the agent accepts inline catalog definitions from the client." } - }, - "required": ["supportedCatalogUris", "acceptsInlineCatalog"] + } } diff --git a/specification/0.8/json/client_to_server.json b/specification/0.8/json/client_to_server.json index 5bd95fbd2..52d374df7 100644 --- a/specification/0.8/json/client_to_server.json +++ b/specification/0.8/json/client_to_server.json @@ -1,6 +1,6 @@ { "title": "A2UI (Agent to UI) Client-to-Server Event Schema", - "description": "Describes the JSON payload for a client-to-server event message. Note that these messages are payloads within an A2A `Message` object. Catalog negotiation is handled via the `a2uiClientCapabilities` object in the A2A `Message.metadata` field, not within this payload.", + "description": "Describes the client-to-server event message. Note that these messages are JSON payloads within an A2A `Message` object.", "type": "object", "minProperties": 1, "maxProperties": 1, From f9a6c8f27561c550e0a798781062b7b207db3398 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 13:27:56 +1030 Subject: [PATCH 03/12] it reRevert "Minor fixes" This reverts commit 7d0afbf1f5f85ce765acc5a47ce2c75bbe07d4bf. --- specification/0.8/json/agent_card_a2ui_extension_params.json | 3 ++- specification/0.8/json/client_to_server.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/specification/0.8/json/agent_card_a2ui_extension_params.json b/specification/0.8/json/agent_card_a2ui_extension_params.json index 1dfd3c124..4d76245d0 100644 --- a/specification/0.8/json/agent_card_a2ui_extension_params.json +++ b/specification/0.8/json/agent_card_a2ui_extension_params.json @@ -16,5 +16,6 @@ "type": "boolean", "description": "Whether the agent accepts inline catalog definitions from the client." } - } + }, + "required": ["supportedCatalogUris", "acceptsInlineCatalog"] } diff --git a/specification/0.8/json/client_to_server.json b/specification/0.8/json/client_to_server.json index 52d374df7..5bd95fbd2 100644 --- a/specification/0.8/json/client_to_server.json +++ b/specification/0.8/json/client_to_server.json @@ -1,6 +1,6 @@ { "title": "A2UI (Agent to UI) Client-to-Server Event Schema", - "description": "Describes the client-to-server event message. Note that these messages are JSON payloads within an A2A `Message` object.", + "description": "Describes the JSON payload for a client-to-server event message. Note that these messages are payloads within an A2A `Message` object. Catalog negotiation is handled via the `a2uiClientCapabilities` object in the A2A `Message.metadata` field, not within this payload.", "type": "object", "minProperties": 1, "maxProperties": 1, From fcbb93f676e908c91c682b30b6246f007894967c Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 13:28:09 +1030 Subject: [PATCH 04/12] Revert "Update v0.8 spec with updated catalog negotiation style" This reverts commit 4b6062f82f4c79475529eca8562b3264e5dc3f76. --- .../0.8/docs/a2ui_extension_specification.md | 130 ++++------ specification/0.8/docs/a2ui_protocol.md | 225 ++++++------------ specification/0.8/json/README.md | 6 +- .../0.8/json/a2ui_client_capabilities.json | 22 -- .../agent_card_a2ui_extension_params.json | 21 -- specification/0.8/json/client_to_server.json | 41 +++- 6 files changed, 155 insertions(+), 290 deletions(-) delete mode 100644 specification/0.8/json/a2ui_client_capabilities.json delete mode 100644 specification/0.8/json/agent_card_a2ui_extension_params.json diff --git a/specification/0.8/docs/a2ui_extension_specification.md b/specification/0.8/docs/a2ui_extension_specification.md index d9504482e..91cd39636 100644 --- a/specification/0.8/docs/a2ui_extension_specification.md +++ b/specification/0.8/docs/a2ui_extension_specification.md @@ -1,97 +1,55 @@ -# A2UI (Agent to UI) Extension Specification +# A2UI (Agent-to-Agent UI) Extension Spec ## Overview -This document specifies the A2UI extension for the Agent-to-Agent (A2A) protocol. This extension allows agents to send streaming, interactive user interfaces to clients that can render them. +This extension implements the A2UI (Agent-to-Agent UI) spec, a format for agents to send streaming, interactive user interfaces to clients. ## Extension URI -The URI for this version of the extension is: `https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md` +The URI of this extension is https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md + +This is the only URI accepted for this extension. ## Core Concepts The A2UI extension is built on three main concepts: -- **Surfaces**: A "Surface" is a distinct, controllable region of the client's UI. The protocol uses a `surfaceId` to direct updates to specific surfaces (e.g., a main content area, a side panel, or a new chat bubble). This allows a single agent stream to manage multiple UI areas independently. - -- **Catalog**: The A2UI extension is component-agnostic. All UI components (e.g., `Text`, `Row`, `Button`) and their properties are defined in a separate **Catalog**. This allows clients and servers to negotiate which set of components to use for rendering a UI. - -- **Schemas**: The A2UI protocol is formally defined by a set of JSON schemas, which describe the structure of catalogs, server-to-client messages, and client-to-server event payloads. - -## Agent Capability Declaration - -An agent advertises its ability to serve A2UI content by including an extension object in its A2A Agent Card. The `params` object within this extension defines the agent's specific UI generation capabilities. - -### Extension Parameters (`params`) - -- `supportedCatalogUris` (array of strings, required): A list of URIs that identify the component catalogs the agent can generate. These URIs are stable identifiers and should not be fetched at runtime. -- `acceptsInlineCatalog` (boolean, required): A flag indicating whether the agent can accept a complete, inline catalog definition from the client. - -**Example Agent Card Snippet:** - -```json -{ - "name": "My A2UI Agent", - "capabilities": { - "extensions": [ - { - "uri": "https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md", - "description": "Provides interactive UIs via the A2UI protocol.", - "required": false, - "params": { - "supportedCatalogUris": [ - "https://a2ui.org/catalogs/standard/0.8", - "https://my-company.com/a2ui/catalogs/custom/1.2" - ], - "acceptsInlineCatalog": true - } - } - ] - } -} -``` - -## Client Catalog Selection - -The A2UI protocol is **stateless** regarding catalog selection. The client **must** inform the server which catalog to use in **every** A2A `Message` it sends. This is done by including an `a2uiClientCapabilities` object in the `metadata` field of the A2A `Message`. - -This object must contain exactly one of the following properties: - -1. `catalogUri` (string): The URI of a catalog that the server has advertised in its `supportedCatalogUris` list. -2. `inlineCatalog` (object): A complete, inline catalog definition. This is only permitted if the agent's `acceptsInlineCatalog` capability is `true`. An inline catalog **replaces** the standard catalog; it is not additive. - -**Example A2A Message with Client Capabilities:** - -```json -{ - "messageId": "msg-123", - "metadata": { - "a2uiClientCapabilities": { - "catalogUri": "https://a2ui.org/catalogs/standard/0.8" - } - }, - "parts": [ - { - "data": { - "data": { - "userAction": { - "name": "find_restaurants", - "surfaceId": "s1", - "sourceComponentId": "c1", - "timestamp": "2025-11-24T09:59:58Z", - "context": { - "location": "Mountain View, CA" - } - } - } - } - } - ] -} -``` - -## Extension Activation - -Clients indicate their desire to use the A2UI extension by specifying its URI via the transport-defined A2A extension activation mechanism (e.g., the `X-A2A-Extensions` HTTP header). - -Activating this extension implies that the server can send A2UI-specific messages (like `surfaceUpdate`) in its response stream and the client is expected to send A2UI-specific event payloads (like `userAction`) in its requests. +Surfaces: A "Surface" is a distinct, controllable region of the client's UI. The spec uses a surfaceId to direct updates to specific surfaces (e.g., a main content area, a side panel, or a new chat bubble). This allows a single agent stream to manage multiple UI areas independently. + +Catalog Definition Document: The a2ui extension is component-agnostic. All UI components (e.g., Text, Row, Button) and their stylings are defined in a separate Catalog Definition Schema. This allows clients and servers to negotiate which catalog to use. + +Schemas: The a2ui extension is defined by three primary JSON schemas: + +Catalog Definition Schema: A standard format for defining a library of components and styles. + +Server-to-Client Message Schema: The core wire format for messages sent from the agent to the client (e.g., surfaceUpdate, dataModelUpdate). + +Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., userAction, clientUiCapabilities). + +Agent Capability Declaration +Agents advertise their A2UI capabilities in their AgentCard within the AgentCapabilities.extensions list. The params object defines the agent's specific UI support, including which component catalogs it can generate and whether it accepts dynamic catalogs from the client. + +Example AgentExtension block: + +Parameter Definitions +params.supportedSchemas: (REQUIRED) An array of strings, where each string is a URI pointing to a component Catalog Definition Schema that the agent can generate. This could include the default catalog or custom catalogs or both. + +params.acceptsDynamicSchemas: (OPTIONAL) A boolean indicating if the agent can accept a clientUiCapabilities message containing a dynamicCatalog. If omitted, this defaults to false. + +Client Capability Declaration +The client-to-server spec includes a clientUiCapabilities message. If a client wishes to use a specific catalog (other than the server's default) or provide its own dynamic catalog, it MUST send this message after the connection is established and before the first user prompt. + +This message allows the client to specify either: + +A catalogUri: A URI for a known, shared catalog (which must be one of the supportedSchemas from the agent). + +A dynamicCatalog: An inline Catalog Definition Schema object. This is only allowed if the agent's acceptsDynamicSchemas capability is true. + +Extension Activation +Clients indicate their desire to use the A2UI extension by specifying it via the transport-defined A2A extension activation mechanism. + +For JSON-RPC and HTTP transports, this is indicated via the X-A2A-Extensions HTTP header. + +For gRPC, this is indicated via the X-A2A-Extensions metadata value. + +Activating this extension implies that the server can send A2UI-specific messages (like surfaceUpdate) and the client is expected to send A2UI-specific events (like userAction). diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index 1a34181a5..dce19c02e 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -68,6 +68,7 @@ Communication occurs via a JSON Lines (JSONL) stream. The client parses each lin Client-to-server communication for user interactions is handled separately via a JSON payload sent to a REST API. This message can be one of several types: - `userAction`: Reports a user-initiated action from a component. +- `clientUiCapabilities`: Informs the server about the client's capabilities, such as the component catalog it supports. - `error`: Reports a client-side error. This keeps the primary data stream unidirectional. @@ -83,132 +84,11 @@ The central philosophy of A2UI is the decoupling of three key elements: 2. **The Data Model (The State):** A server-provided JSON object containing the dynamic values that populate the UI, such as text, booleans, or lists. This is managed via `dataModelUpdate` messages. 3. **The Widget Registry (The "Catalog"):** A client-defined mapping of component types (e.g., "Row", "Text") to concrete, native widget implementations. This registry is **part of the client application**, not the protocol stream. The server must generate components that the target client's registry understands. -### 1.2. Catalog Negotiation - -A central concept in A2UI is the **Catalog**, which defines the contract between the server and client for what UI components can be rendered. Each client must select a single catalog to use for all UI surfaces, and it must inform the server of this choice with every request. - -#### 1.2.1. Principles of Catalog Negotiation - -- **Statelessness**: The server does not remember which catalog the client is using across different requests. The client must specify its chosen catalog in every A2A message it sends. -- **Client-Driven**: The client is in control of which catalog is used. -- **Immutability**: Catalogs are identified by URIs and are considered immutable. If a catalog definition changes, it must be given a new URI. -- **URIs as Identifiers**: Catalog URIs (e.g., `https://a2ui.org/catalogs/standard/0.8`) are stable identifiers. Neither the client nor the server should fetch catalog definitions from these URIs at runtime. - -#### 1.2.2. Server Catalog Advertisement - -The server advertises which catalogs it supports within its A2A **Agent Card**. This is done using the A2A extension mechanism. The server adds an A2UI extension object to its `capabilities` which lists the URIs of supported catalogs and indicates whether it accepts custom, inline catalogs. - -**Example Agent Card Snippet:** - -```json -{ - "name": "Restaurant Finder Agent", - "capabilities": { - "extensions": [ - { - "uri": "https://a2ui.org/ext/a2a-ui/v0.8", - "description": "This agent can render UIs using the A2UI protocol.", - "required": false, - "params": { - "supportedCatalogUris": [ - "https://a2ui.org/catalogs/standard/0.8", - "https://my-company.com/a2ui/catalogs/custom-internal/1.2" - ], - "acceptsInlineCatalog": true - } - } - ] - } -} -``` - -- `supportedCatalogUris`: A list of catalog identifier URIs that the server can generate UI for. -- `acceptsInlineCatalog`: A boolean indicating if the server allows the client to provide a complete catalog definition directly in a message. - -#### 1.2.3. Client Catalog Selection - -With every A2A `Message` sent to the server, the client must include an `a2uiClientCapabilities` object in the `metadata` field. This object tells the server which catalog to use when generating the UI response for that specific request. - -The `a2uiClientCapabilities` object must contain exactly one of the following: - -1. `catalogUri`: The URI of a catalog previously advertised by the server. -2. `inlineCatalog`: A complete catalog definition, which can only be used if the server advertised `acceptsInlineCatalog: true`. An inline catalog **replaces** the standard catalog; it is not additive. - -**Example A2A Message with `catalogUri`:** - -```json -{ - "messageId": "msg-123", - "metadata": { - "a2uiClientCapabilities": { - "catalogUri": "https://a2ui.org/catalogs/standard/0.8" - } - }, - "parts": [ - { - "data": { - "data": { - "userAction": { - "name": "find_restaurants", - "surfaceId": "s1", - "sourceComponentId": "c1", - "timestamp": "2025-11-24T09:59:58Z", - "context": { - "location": "Mountain View, CA" - } - } - } - } - } - ] -} -``` - -**Example A2A Message with `inlineCatalog`:** - -```json -{ - "messageId": "msg-124", - "metadata": { - "a2uiClientCapabilities": { - "inlineCatalog": { - "components": { - "SignaturePad": { - "type": "object", - "description": "A custom area for user signatures.", - "properties": { - "penColor": { "type": "string" }, - "required": { "type": "boolean" } - }, - "required": ["required"] - } - } - } - } - }, - "parts": [ - { - "data": { - "data": { - "userAction": { - "name": "sign_document", - "surfaceId": "s2", - "sourceComponentId": "c5", - "timestamp": "2025-11-24T10:04:00Z", - "context": {} - } - } - } - } - ] -} -``` - -### 1.3. The JSONL Stream: The Unit of Communication +### 1.2. The JSONL Stream: The Unit of Communication All UI descriptions are transmitted from the server to the client as a stream of JSON objects, formatted as JSON Lines (JSONL). Each line is a separate, compact JSON object representing a single message. This allows the client to parse and process each part of the UI definition as it arrives, enabling progressive rendering. -### 1.4. Surfaces: Managing Multiple UI Regions +### 1.3. Surfaces: Managing Multiple UI Regions A **Surface** is a contiguous portion of screen real estate into which a A2UI UI can be rendered. The protocol introduces the concept of a `surfaceId` to uniquely identify and manage these areas. This allows a single A2UI stream to control multiple, independent UI regions simultaneously. Each surface has a separate root component and a separate hierarchy of components. Each surface has a separate data model, to avoid collision of keys when working with a large number of surfaces. @@ -216,7 +96,7 @@ For example, in a chat application, each AI-generated response could be rendered The `surfaceId` is a property within each server-to-client message that directs changes to the correct area. It is used with messages like `beginRendering`, `surfaceUpdate`, `dataModelUpdate`, and `deleteSurface` to target a specific surface. -### 1.5. Data Flow Model +### 1.4. Data Flow Model The A2UI protocol is composed of a server-to-client stream describing UI and individual events sent to the server. The client consumes the stream, builds the UI, and renders it. Communication occurs via a JSON Lines (JSONL) stream, typically transported over **Server-Sent Events (SSE)**. @@ -228,7 +108,7 @@ The A2UI protocol is composed of a server-to-client stream describing UI and ind 3. **Render Signal:** The server sends a `beginRendering` message with the `root` component's ID. This prevents a "flash of incomplete content." The client buffers incoming components and data but waits for this explicit signal before attempting the first render, ensuring the initial view is coherent. 4. **Client-Side Rendering:** The client, now in a "ready" state, starts at the `root` component. It recursively walks the component tree by looking up component IDs in its buffer. It resolves any data bindings against the data model and uses its `WidgetRegistry` to instantiate native widgets. -5. **User Interaction and Event Handling:** The user interacts with a rendered widget (e.g., taps a button). The client constructs a `userAction` JSON payload, resolving any data bindings from the component's `action.context`. It sends this payload to the server via an A2A message, including the required `a2uiClientCapabilities` in the metadata. +5. **User Interaction and Event Handling:** The user interacts with a rendered widget (e.g., taps a button). The client constructs a `userAction` JSON payload, resolving any data bindings from the component's `action.context`. It sends this payload to the server via an A2A message. 6. **Dynamic Updates:** The server processes the `userAction`. If the UI needs to change in response, the server sends new `surfaceUpdate` and `dataModelUpdate` messages over the original SSE stream. As these arrive, the client updates its component buffer and data model, and the UI re-renders to reflect the changes. The server can also send `deleteSurface` to remove a UI region. ```mermaid @@ -251,7 +131,7 @@ sequenceDiagram Note over Client: 8. User interacts with UI (e.g., clicks button) Client->>Client: 9. Construct userAction payload - Client->>+Server: 10. A2A Message sent to server (with a2uiClientCapabilities in metadata) + Client->>+Server: 10. A2A Message sent to server (Client Event JSON with userAction) Server-->>-Client: 11. OK loop Dynamic Updates in Response to Event @@ -262,7 +142,7 @@ sequenceDiagram end ``` -### 1.6. Full Stream Example +### 1.5. Full Stream Example The following is a complete, minimal example of a JSONL stream that renders a user profile card. @@ -289,7 +169,7 @@ A2UI's component model is designed for flexibility, separating the protocol from ### 2.1. The Catalog: Defining Components -Unlike previous versions with a fixed component set, A2UI now defines components in a **Catalog**. A catalog is a schema that defines the available component types (e.g., `Row`, `Text`) and their supported properties. This allows for different clients to support different sets of components, including custom ones. The server must generate `surfaceUpdate` messages that conform to the component catalog selected by the client. The mechanism for this is detailed in the **Catalog Negotiation** section. +Unlike previous versions with a fixed component set, A2UI now defines components in a **Catalog**. A catalog is a schema that defines the available component types (e.g., `Row`, `Text`) and their supported properties. This allows for different clients to support different sets of components, including custom ones. The server must generate `surfaceUpdate` messages that conform to the component catalog understood by the client. Clients can inform the server of the catalog they support using the `clientUiCapabilities` message. #### Schemas for Developers @@ -534,7 +414,7 @@ While the server-to-client UI definition is a one-way stream (e.g., over SSE), u ### 5.1. The Client Event Message -The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction` or `error`. +The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction`, `clientUiCapabilities`, or `error`. ### 5.2. The `userAction` Message @@ -550,11 +430,60 @@ The `userAction` object has the following structure: The process for resolving the `action.context` remains the same: the client iterates over the `context` array, resolves all literal or data-bound values, and constructs the `context` object. -### 5.3. The `error` Message +### 5.3. The `clientUiCapabilities` Message + +This message is sent by the client to inform the server about its capabilities. This is crucial for supporting different component sets, allowing the server to generate UI that is compatible with the client. The message must contain exactly one of the following properties: `catalogUri` or `dynamicCatalog`. + +- `catalogUri`: A URI pointing to a predefined component catalog schema that the client supports. +- `dynamicCatalog`: An inline JSON object, conforming to the Catalog Schema, that defines the client's supported components. This is useful for development or for clients with highly custom component sets. + +```mermaid +sequenceDiagram + participant Client + participant Server + Client->>+Server: POST /event (clientUiCapabilities with catalog) + Server-->>-Client: HTTP 200 OK + Note over Server: Server now knows which catalog to use. + Server->>+Client: SSE Connection (JSONL Stream using client's catalog) + Client-->>-Server: (Renders UI based on custom/specified catalog) +``` + +#### `dynamicCatalog` + +The `dynamicCatalog` property allows the client to send an inline JSON object that defines its entire supported component set. This is especially useful for development or for clients with highly custom components. The object must conform to the Catalog Schema, containing `components`. + +- `components`: An object where each key is the name of a component (e.g., `"MyCustomCard"`) and the value is a valid JSON object schema defining the properties for that component. + +**Example of a `clientUiCapabilities` message:** + +```json +{ + "clientUiCapabilities": { + "dynamicCatalog": { + "components": { + "MyCustomCard": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "child": { + "type": "string" + } + }, + "required": ["title", "child"] + } + } + } + } +} +``` + +### 5.4. The `error` Message This message provides a feedback mechanism for the server. It is sent when the client encounters an error, for instance, during UI rendering or data binding. The content of the object is flexible and can contain any relevant error information. -### 5.4. Event Flow Example (`userAction`) +### 5.5. Event Flow Example (`userAction`) 1. **Component Definition** (from `surfaceUpdate`): @@ -608,34 +537,20 @@ This message provides a feedback mechanism for the server. It is sent when the c 3. **User Action:** The user taps the "submit_btn" button. 4. **Client-Side Resolution:** The client resolves the `action.context`. -5. **Client-to-Server Request:** The client sends an A2A `Message` to the server. The `userAction` is placed inside the `data` object of a `Part`, and the `metadata` contains the required `a2uiClientCapabilities`. +5. **Client-to-Server Request:** The client sends a `POST` request to `https://api.example.com/handle_event` with the following JSON body: ```json { - "messageId": "msg-125", - "metadata": { - "a2uiClientCapabilities": { - "catalogUri": "https://a2ui.org/catalogs/standard/0.8" - } - }, - "parts": [ - { - "data": { - "data": { - "userAction": { - "name": "submit_form", - "surfaceId": "main_content_area", - "sourceComponentId": "submit_btn", - "timestamp": "2025-09-19T17:05:00Z", - "context": { - "userInput": "User input text", - "formId": "f-123" - } - } - } - } + "userAction": { + "name": "submit_form", + "surfaceId": "main_content_area", + "sourceComponentId": "submit_btn", + "timestamp": "2025-09-19T17:05:00Z", + "context": { + "userInput": "User input text", + "formId": "f-123" } - ] + } } ``` diff --git a/specification/0.8/json/README.md b/specification/0.8/json/README.md index dbcdc7203..75d0d7c34 100644 --- a/specification/0.8/json/README.md +++ b/specification/0.8/json/README.md @@ -6,14 +6,10 @@ This directory contains the formal JSON Schema definitions for the A2UI protocol - `server_to_client.json`: This is the core, catalog-agnostic schema for messages sent from the server to the client. It defines the four main message types (`beginRendering`, `surfaceUpdate`, `dataModelUpdate`, `deleteSurface`) and their structure. In this schema, the `component` object within a `surfaceUpdate` message is generic (`"additionalProperties": true`), allowing any component definitions to be passed. -- `client_to_server.json`: This schema defines the structure for event message payloads sent from the client to the server within an A2A `Message`. This includes user-initiated actions (`userAction`) and error reporting (`error`). Note that catalog negotiation is no longer handled by a message in this payload. +- `client_to_server.json`: This schema defines the structure for event messages sent from the client to the server. This includes user-initiated actions (`userAction`), error reporting (`error`), and the crucial `clientUiCapabilities` message, which allows a client to inform the server about the component catalog it supports. - `catalog_description_schema.json`: This is a meta-schema that defines the structure of an A2UI component catalog. A catalog consists of a `components` object and a `styles` object, where each key is a component/style name and the value is a JSON schema defining its properties. This allows for the creation of custom component sets. - `standard_catalog_definition.json`: This file is a concrete implementation of a catalog, conforming to the `catalog_description_schema.json`. It defines the standard set of components (e.g., `Text`, `Image`, `Row`, `Card`) and styles that are part of the baseline A2UI specification. - `server_to_client_with_standard_catalog.json`: This is a resolved, LLM-friendly version of the server-to-client schema. It is generated by combining `server_to_client.json` with the `standard_catalog_definition.json`. In this version, the generic `component` object is replaced with a strict `oneOf` definition that includes every component from the standard catalog. This provides a complete, strictly-typed schema that is ideal for LLMs to use for generating valid A2UI messages without ambiguity. - -- `agent_card_a2ui_extension_params.json`: Defines the schema for the `params` object within the A2UI extension in an A2A agent card. This is how a server advertises its supported catalog URIs and whether it accepts inline catalogs. - -- `a2ui_client_capabilities.json`: Defines the schema for the `a2uiClientCapabilities` object, which is included in the `metadata` field of every A2A message from the client. This is how the client informs the server which catalog to use for a given request. diff --git a/specification/0.8/json/a2ui_client_capabilities.json b/specification/0.8/json/a2ui_client_capabilities.json deleted file mode 100644 index ee7e2295d..000000000 --- a/specification/0.8/json/a2ui_client_capabilities.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "A2UI Client Capabilities", - "description": "Schema for the 'a2uiClientCapabilities' object, which is included in the 'metadata' field of every A2A message from the client to the server.", - "type": "object", - "properties": { - "catalogUri": { - "type": "string", - "format": "uri", - "description": "The URI of the custom catalog to use. This must be one of the URIs advertised by the server in its agent card." - }, - "inlineCatalog": { - "$ref": "catalog_description_schema.json", - "description": "An inline catalog definition. This can only be provided if the server's agent card indicates it accepts inline catalogs." - } - }, - "oneOf": [ - { "required": ["catalogUri"] }, - { "required": ["inlineCatalog"] } - ], - "additionalProperties": false -} diff --git a/specification/0.8/json/agent_card_a2ui_extension_params.json b/specification/0.8/json/agent_card_a2ui_extension_params.json deleted file mode 100644 index 4d76245d0..000000000 --- a/specification/0.8/json/agent_card_a2ui_extension_params.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "A2UI Agent Card Extension Parameters", - "description": "Schema for the 'params' object of the A2UI extension within an A2A agent card.", - "type": "object", - "properties": { - "supportedCatalogUris": { - "type": "array", - "description": "A list of URIs for the A2UI catalogs supported by this agent.", - "items": { - "type": "string", - "format": "uri" - } - }, - "acceptsInlineCatalog": { - "type": "boolean", - "description": "Whether the agent accepts inline catalog definitions from the client." - } - }, - "required": ["supportedCatalogUris", "acceptsInlineCatalog"] -} diff --git a/specification/0.8/json/client_to_server.json b/specification/0.8/json/client_to_server.json index 5bd95fbd2..db082c805 100644 --- a/specification/0.8/json/client_to_server.json +++ b/specification/0.8/json/client_to_server.json @@ -1,6 +1,6 @@ { "title": "A2UI (Agent to UI) Client-to-Server Event Schema", - "description": "Describes the JSON payload for a client-to-server event message. Note that these messages are payloads within an A2A `Message` object. Catalog negotiation is handled via the `a2uiClientCapabilities` object in the A2A `Message.metadata` field, not within this payload.", + "description": "Describes a JSON payload for a client-to-server event message.", "type": "object", "minProperties": 1, "maxProperties": 1, @@ -40,6 +40,44 @@ "context" ] }, + "clientUiCapabilities": { + "type": "object", + "description": "Informs the server about the client's capabilities, such as the component catalog it supports. Exactly ONE of the properties in this object must be set.", + "properties": { + "catalogUri": { + "type": "string", + "format": "uri", + "description": "A URI pointing to a predefined component catalog schema that the server advertized, and the client supports." + }, + "dynamicCatalog": { + "type": "object", + "description": "An inline JSON object that defines the client's supported components.", + "properties": { + "components": { + "type": "object", + "title": "Components", + "description": "A map where each key is a component name and the value is a JSON Schema defining an object containing its properties.", + "additionalProperties": { + "$ref": "https://json-schema.org/draft/2020-12/schema" + } + }, + "styles": { + "title": "Styles", + "description": "A schema that defines a catalog of A2UI styles. Each key is a style name, and each value is the JSON schema for that style's properties.", + "type": "object", + "additionalProperties": { + "$ref": "https://json-schema.org/draft/2020-12/schema" + } + } + }, + "required": ["components"] + } + }, + "oneOf": [ + { "required": ["catalogUri"] }, + { "required": ["dynamicCatalog"] } + ] + }, "error": { "type": "object", "description": "Reports a client-side error. The content is flexible.", @@ -48,6 +86,7 @@ }, "oneOf": [ { "required": ["userAction"] }, + { "required": ["clientUiCapabilities"] }, { "required": ["error"] } ] } From af47e4ccca478e00bd1d3dbe6c8d1b18b79ff0b0 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 14:20:08 +1030 Subject: [PATCH 05/12] Update the v0.8 spec with the new custom catalog proposal --- .../0.8/docs/a2ui_extension_specification.md | 29 ++-- specification/0.8/docs/a2ui_protocol.md | 153 +++++++++++------- .../json/a2ui_client_capabilities_schema.json | 23 +++ .../0.8/json/catalog_description_schema.json | 6 + specification/0.8/json/client_to_server.json | 39 ----- specification/0.8/json/server_to_client.json | 4 + 6 files changed, 145 insertions(+), 109 deletions(-) create mode 100644 specification/0.8/json/a2ui_client_capabilities_schema.json diff --git a/specification/0.8/docs/a2ui_extension_specification.md b/specification/0.8/docs/a2ui_extension_specification.md index 91cd39636..9e9433b3b 100644 --- a/specification/0.8/docs/a2ui_extension_specification.md +++ b/specification/0.8/docs/a2ui_extension_specification.md @@ -24,26 +24,31 @@ Catalog Definition Schema: A standard format for defining a library of component Server-to-Client Message Schema: The core wire format for messages sent from the agent to the client (e.g., surfaceUpdate, dataModelUpdate). -Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., userAction, clientUiCapabilities). +Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., userAction). Agent Capability Declaration -Agents advertise their A2UI capabilities in their AgentCard within the AgentCapabilities.extensions list. The params object defines the agent's specific UI support, including which component catalogs it can generate and whether it accepts dynamic catalogs from the client. +Agents advertise their A2UI capabilities in their AgentCard within the `AgentCapabilities.extensions` list. The `params` object defines the agent's specific UI support. Example AgentExtension block: -Parameter Definitions -params.supportedSchemas: (REQUIRED) An array of strings, where each string is a URI pointing to a component Catalog Definition Schema that the agent can generate. This could include the default catalog or custom catalogs or both. +```json +{ + "uri": "https://a2ui.org/ext/a2a-ui/v0.8", + "description": "Ability to render A2UI", + "required": false, + "params": { + "acceptsInlineCatalogs": true + } +} +``` -params.acceptsDynamicSchemas: (OPTIONAL) A boolean indicating if the agent can accept a clientUiCapabilities message containing a dynamicCatalog. If omitted, this defaults to false. +#### Parameter Definitions +- `params.acceptsInlineCatalogs`: (OPTIONAL) A boolean indicating if the agent can accept an `inlineCatalogs` array in the client's `a2uiClientCapabilities`. If omitted, this defaults to `false`. -Client Capability Declaration -The client-to-server spec includes a clientUiCapabilities message. If a client wishes to use a specific catalog (other than the server's default) or provide its own dynamic catalog, it MUST send this message after the connection is established and before the first user prompt. +Client Capabilities +The client sends its capabilities to the server in an `a2uiClientCapabilities` object. This object is **not** sent as a standalone message, but is instead included in the `metadata` field of every A2A `Message` sent from the client to the server. -This message allows the client to specify either: - -A catalogUri: A URI for a known, shared catalog (which must be one of the supportedSchemas from the agent). - -A dynamicCatalog: An inline Catalog Definition Schema object. This is only allowed if the agent's acceptsDynamicSchemas capability is true. +This object allows the client to declare which catalogs it supports. For a complete definition of this object and the catalog negotiation process, please see the main [A2UI Protocol Specification](./a2ui_protocol.md). Extension Activation Clients indicate their desire to use the A2UI extension by specifying it via the transport-defined A2A extension activation mechanism. diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index dce19c02e..99528954a 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -62,13 +62,12 @@ Communication occurs via a JSON Lines (JSONL) stream. The client parses each lin - `surfaceUpdate`: Provides a list of component definitions to be added to or updated in a specific UI area called a "surface." - `dataModelUpdate`: Provides new data to be inserted into or to replace a surface's data model. Each surface has its own data model. -- `beginRendering`: Signals to the client that it has enough information to perform the initial render, specifying the ID of the root component. +- `beginRendering`: Signals to the client that it has enough information to perform the initial render, specifying the ID of the root component and, optionally, the component catalog to use. - `deleteSurface`: Explicitly removes a surface and its contents from the UI. -Client-to-server communication for user interactions is handled separately via a JSON payload sent to a REST API. This message can be one of several types: +Client-to-server communication for user interactions is handled separately via an A2A message. This message can be one of two types: - `userAction`: Reports a user-initiated action from a component. -- `clientUiCapabilities`: Informs the server about the client's capabilities, such as the component catalog it supports. - `error`: Reports a client-side error. This keeps the primary data stream unidirectional. @@ -167,13 +166,100 @@ The following is a complete, minimal example of a JSONL stream that renders a us A2UI's component model is designed for flexibility, separating the protocol from the component set. -### 2.1. The Catalog: Defining Components +### 2.1. Catalog Negotiation -Unlike previous versions with a fixed component set, A2UI now defines components in a **Catalog**. A catalog is a schema that defines the available component types (e.g., `Row`, `Text`) and their supported properties. This allows for different clients to support different sets of components, including custom ones. The server must generate `surfaceUpdate` messages that conform to the component catalog understood by the client. Clients can inform the server of the catalog they support using the `clientUiCapabilities` message. +A **Catalog** defines the contract between the server and the client for the UI that can be rendered. It contains a list of supported component types (e.g., `Row`, `Text`), their properties, and available styles. A catalog is defined by a **Catalog Definition Document**. + +There is a **Standard Catalog** associated with each version of the A2UI protocol. For v0.8, its identifier is `a2ui.org:standard_catalog_0_8_0`. + +The negotiation process allows the client and server to agree on which catalog to use for a given UI surface. This process is designed to be flexible, supporting standard, custom, and even dynamically-defined catalogs. + +The flow is as follows: + +#### 1. Server Advertises Capabilities + +The server (agent) advertises its capabilities in its Agent Card as part of the A2A protocol. For A2UI, this includes whether it can handle catalogs defined inline by the client. + +- `acceptsInlineCatalogs` (boolean, optional): If `true`, the server can process `inlineCatalogs` sent by the client. Defaults to `false`. + +**Example Server Agent Card Snippet:** +```json +{ + "name": "Restaurant Finder", + "capabilities": { + "extensions": [ + { + "uri": "https://a2ui.org/ext/a2a-ui/v0.8", + "params": { + "acceptsInlineCatalogs": true + } + } + ] + } +} +``` + +#### 2. Client Declares Supported Catalogs + +In **every** message sent to the server, the client includes an `a2uiClientCapabilities` object within the A2A `Message` metadata. This object informs the server of all catalogs the client can render. + +- `supportedCatalogIds` (array of strings, required): A list of identifiers for all pre-defined catalogs the client supports. The client MUST always include the standard catalog ID here. +- `inlineCatalogs` (array of objects, optional): An array of full Catalog Definition Documents. This allows a client to provide custom, on-the-fly catalogs. This should only be provided if the server has advertised `acceptsInlineCatalogs: true`. + +**Example A2A Message with Client Capabilities:** +```json +{ + "metadata": { + "a2uiClientCapabilities": { + "supportedCatalogIds": [ + "a2ui.org:standard_catalog_0_8_0", + "my-company.com:custom-reporting-catalog-1.2" + ], + "inlineCatalogs": [ + { + "catalogId": "my-company.com:temp-signature-pad-catalog", + "components": { + "SignaturePad": { + "type": "object", + "properties": { "penColor": { "type": "string" } } + } + }, + "styles": {} + } + ] + } + }, + "message": { + "prompt": { + "text": "Find me a good restaurant" + } + } +} +``` + +#### 3. Server Chooses Catalog and Renders + +The server receives the client's capabilities and chooses a catalog to use for a specific UI surface. The server specifies its choice in the `beginRendering` message using the `catalogId` field. + +- `catalogId` (string, optional): The identifier of the chosen catalog. This ID must be one of the `supportedCatalogIds` or the `catalogId` from one of the `inlineCatalogs` provided by the client. + +If the `catalogId` is omitted, the client **MUST** default to the standard catalog for the protocol version (`a2ui.org:standard_catalog_0_8_0`). + +**Example `beginRendering` Message:** +```json +{ + "beginRendering": { + "surfaceId": "unique-surface-1", + "catalogId": "my-company.com:custom-reporting-catalog-1.2", + "root": "root-component-id" + } +} +``` +Each surface can use a different catalog, providing a high degree of flexibility. #### Schemas for Developers -When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., `server_to_client_with_standard_catalog.json`). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation. +When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., a custom schema combining `server_to_client.json` with your `my-company.com:custom-reporting-catalog-1.2` definition). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation. ### 2.2. The `surfaceUpdate` Message @@ -414,7 +500,7 @@ While the server-to-client UI definition is a one-way stream (e.g., over SSE), u ### 5.1. The Client Event Message -The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction`, `clientUiCapabilities`, or `error`. +The client sends a single JSON object that acts as a wrapper. It must contain exactly one of the following keys: `userAction` or `error`. ### 5.2. The `userAction` Message @@ -430,60 +516,11 @@ The `userAction` object has the following structure: The process for resolving the `action.context` remains the same: the client iterates over the `context` array, resolves all literal or data-bound values, and constructs the `context` object. -### 5.3. The `clientUiCapabilities` Message - -This message is sent by the client to inform the server about its capabilities. This is crucial for supporting different component sets, allowing the server to generate UI that is compatible with the client. The message must contain exactly one of the following properties: `catalogUri` or `dynamicCatalog`. - -- `catalogUri`: A URI pointing to a predefined component catalog schema that the client supports. -- `dynamicCatalog`: An inline JSON object, conforming to the Catalog Schema, that defines the client's supported components. This is useful for development or for clients with highly custom component sets. - -```mermaid -sequenceDiagram - participant Client - participant Server - Client->>+Server: POST /event (clientUiCapabilities with catalog) - Server-->>-Client: HTTP 200 OK - Note over Server: Server now knows which catalog to use. - Server->>+Client: SSE Connection (JSONL Stream using client's catalog) - Client-->>-Server: (Renders UI based on custom/specified catalog) -``` - -#### `dynamicCatalog` - -The `dynamicCatalog` property allows the client to send an inline JSON object that defines its entire supported component set. This is especially useful for development or for clients with highly custom components. The object must conform to the Catalog Schema, containing `components`. - -- `components`: An object where each key is the name of a component (e.g., `"MyCustomCard"`) and the value is a valid JSON object schema defining the properties for that component. - -**Example of a `clientUiCapabilities` message:** - -```json -{ - "clientUiCapabilities": { - "dynamicCatalog": { - "components": { - "MyCustomCard": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "child": { - "type": "string" - } - }, - "required": ["title", "child"] - } - } - } - } -} -``` - -### 5.4. The `error` Message +### 5.3. The `error` Message This message provides a feedback mechanism for the server. It is sent when the client encounters an error, for instance, during UI rendering or data binding. The content of the object is flexible and can contain any relevant error information. -### 5.5. Event Flow Example (`userAction`) +### 5.4. Event Flow Example (`userAction`) 1. **Component Definition** (from `surfaceUpdate`): diff --git a/specification/0.8/json/a2ui_client_capabilities_schema.json b/specification/0.8/json/a2ui_client_capabilities_schema.json new file mode 100644 index 000000000..b42df0039 --- /dev/null +++ b/specification/0.8/json/a2ui_client_capabilities_schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "A2UI Client Capabilities Schema", + "description": "A schema for the a2uiClientCapabilities object, which is sent from the client to the server to describe the client's UI rendering capabilities.", + "type": "object", + "properties": { + "supportedCatalogIds": { + "type": "array", + "description": "The URI of each of the catalogs that is supported by the client. The standard catalog for v0.8 is 'a2ui.org:standard_catalog_0_8_0'.", + "items": { + "type": "string" + } + }, + "inlineCatalogs": { + "type": "array", + "description": "An array of inline catalog definitions. This should only be provided if the agent declares 'acceptsInlineCatalogs: true' in its capabilities.", + "items": { + "$ref": "catalog_description_schema.json" + } + } + }, + "required": ["supportedCatalogIds"] +} diff --git a/specification/0.8/json/catalog_description_schema.json b/specification/0.8/json/catalog_description_schema.json index 7cac4f5c1..ad8cf579e 100644 --- a/specification/0.8/json/catalog_description_schema.json +++ b/specification/0.8/json/catalog_description_schema.json @@ -4,6 +4,11 @@ "description": "A schema for a custom Catalog Description including A2UI components and styles.", "type": "object", "properties": { + "catalogId": { + "title": "Catalog ID", + "description": "A string that uniquely identifies this catalog. It is recommended to use a reverse-domain name notation, e.g. 'com.example.my_catalog'.", + "type": "string" + }, "components": { "title": "A2UI Components", "description": "A schema that defines a catalog of A2UI components. Each key is a component name, and each value is the JSON schema for that component's properties.", @@ -22,6 +27,7 @@ } }, "required": [ + "catalogId", "components", "styles" ] diff --git a/specification/0.8/json/client_to_server.json b/specification/0.8/json/client_to_server.json index db082c805..f4f964a24 100644 --- a/specification/0.8/json/client_to_server.json +++ b/specification/0.8/json/client_to_server.json @@ -40,44 +40,6 @@ "context" ] }, - "clientUiCapabilities": { - "type": "object", - "description": "Informs the server about the client's capabilities, such as the component catalog it supports. Exactly ONE of the properties in this object must be set.", - "properties": { - "catalogUri": { - "type": "string", - "format": "uri", - "description": "A URI pointing to a predefined component catalog schema that the server advertized, and the client supports." - }, - "dynamicCatalog": { - "type": "object", - "description": "An inline JSON object that defines the client's supported components.", - "properties": { - "components": { - "type": "object", - "title": "Components", - "description": "A map where each key is a component name and the value is a JSON Schema defining an object containing its properties.", - "additionalProperties": { - "$ref": "https://json-schema.org/draft/2020-12/schema" - } - }, - "styles": { - "title": "Styles", - "description": "A schema that defines a catalog of A2UI styles. Each key is a style name, and each value is the JSON schema for that style's properties.", - "type": "object", - "additionalProperties": { - "$ref": "https://json-schema.org/draft/2020-12/schema" - } - } - }, - "required": ["components"] - } - }, - "oneOf": [ - { "required": ["catalogUri"] }, - { "required": ["dynamicCatalog"] } - ] - }, "error": { "type": "object", "description": "Reports a client-side error. The content is flexible.", @@ -86,7 +48,6 @@ }, "oneOf": [ { "required": ["userAction"] }, - { "required": ["clientUiCapabilities"] }, { "required": ["error"] } ] } diff --git a/specification/0.8/json/server_to_client.json b/specification/0.8/json/server_to_client.json index 48f34c0b5..17c829814 100644 --- a/specification/0.8/json/server_to_client.json +++ b/specification/0.8/json/server_to_client.json @@ -13,6 +13,10 @@ "type": "string", "description": "The unique identifier for the UI surface to be rendered." }, + "catalogId": { + "type": "string", + "description": "The identifier of the component catalog to use for this surface. If omitted, the client MUST default to the standard catalog for this A2UI version (a2ui.org:standard_catalog_0_8_0)." + }, "root": { "type": "string", "description": "The ID of the root component to render." From c99cc95bc47c7a70f722341fcd7c68bc2f7e9857 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 14:30:58 +1030 Subject: [PATCH 06/12] Update mention of standard catalog to be not required --- .../0.8/docs/custom_catalog_changes.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 specification/0.8/docs/custom_catalog_changes.md diff --git a/specification/0.8/docs/custom_catalog_changes.md b/specification/0.8/docs/custom_catalog_changes.md new file mode 100644 index 000000000..f0605f868 --- /dev/null +++ b/specification/0.8/docs/custom_catalog_changes.md @@ -0,0 +1,58 @@ +# Summary of Custom Catalog Negotiation Changes in A2UI v0.8 + +This document summarizes the changes made to the A2UI protocol in v0.8 to support a more flexible and powerful custom catalog negotiation mechanism. It is intended as a guide for developers implementing these changes in agent or renderer libraries. + +The previous mechanism, which involved a single, one-time `clientUiCapabilities` message, has been deprecated. The new approach allows for a more dynamic, per-request declaration of capabilities, enabling a single client to support multiple catalogs and allowing the agent to choose the most appropriate one for each UI surface. + +## Key Changes to the Protocol + +1. **Agent Capability Advertisement (`acceptsInlineCatalogs`)**: The agent's role in negotiation has been simplified. It now only declares whether it is capable of processing catalogs defined "inline" by the client. + * **Relevant Doc**: [`a2ui_extension_specification.md`](./a2ui_extension_specification.md) + +2. **Client Capabilities via A2A Metadata**: The client now sends its capabilities in an `a2uiClientCapabilities` object. Crucially, this is no longer a standalone message but is included in the `metadata` field of **every** A2A message sent to the agent. + * This object contains `supportedCatalogIds` (an array of known catalog IDs) and an optional `inlineCatalogs` (an array of full catalog definitions). + * **Relevant Doc**: The new process is explained in the [`a2ui_protocol.md`](./a2ui_protocol.md#catalog-negotiation) section on Catalog Negotiation. + * **Relevant Schema**: [`a2ui_client_capabilities_schema.json`](../json/a2ui_client_capabilities_schema.json) + +3. **Per-Surface Catalog Selection (`beginRendering`)**: The agent is now responsible for selecting which catalog to use for each UI surface. It signals its choice using the new optional `catalogId` field in the `beginRendering` message. If this field is omitted, the client must default to the Standard Catalog. + * **Relevant Doc**: [`a2ui_protocol.md`](./a2ui_protocol.md#catalog-negotiation) + * **Relevant Schema**: The change is reflected in [`server_to_client.json`](../json/server_to_client.json). + +4. **Catalog Definition ID (`catalogId`)**: To facilitate identification, the catalog definition schema itself now has a required `catalogId` field. + * **Relevant Schema**: [`catalog_description_schema.json`](../json/catalog_description_schema.json) + +--- + +## Implementation Guide for Developers + +### For Agent (Server) Library Developers + +Your responsibilities are to process the client's declared capabilities and make a rendering choice. + +1. **Advertise Capability**: In the agent's capability card, add the `acceptsInlineCatalogs: true` parameter within the A2UI extension block if you intend to support catalogs sent dynamically from the client. + +2. **Parse Client Capabilities**: On every incoming A2A message, your library must parse the `metadata.a2uiClientCapabilities` object to determine which catalogs the client supports. You will get a list of `supportedCatalogIds` and potentially a list of `inlineCatalogs`. + +3. **Choose a Catalog**: Before rendering a UI, decide which catalog to use. Your choice must be one of the catalogs advertised by the client in the capabilities object. + +4. **Specify Catalog on Render**: When sending the `beginRendering` message for a surface, set the `catalogId` field to the ID of your chosen catalog (e.g., `"my-company.com:custom-catalog-1.2"`). If you do not set this field, you are implicitly requesting the use of the standard catalog. + +5. **Generate Compliant UI**: Ensure that all components generated in subsequent `surfaceUpdate` messages for that surface conform to the properties and types defined in the chosen catalog. + +### For Renderer (Client) Library Developers + +Your responsibilities are to accurately declare your capabilities and render surfaces using the catalog selected by the agent. + +1. **Declare Capabilities on Every Request**: For every A2A message your application sends, your library must inject the `a2uiClientCapabilities` object into the top-level `metadata` field. + +2. **Populate `supportedCatalogIds`**: In the capabilities object, populate this array with the string identifiers of all pre-compiled catalogs your renderer supports. If your renderer supports the standard catalog for v0.8, you **should** include its ID: `a2ui.org:standard_catalog_0_8_0`. + +3. **Provide `inlineCatalogs` (Optional)**: If your renderer supports dynamically generating or defining catalogs at runtime, include their full, valid Catalog Definition Documents in the `inlineCatalogs` array. + +4. **Process `beginRendering`**: When your renderer receives a `beginRendering` message, it must inspect the new `catalogId` field. + +5. **Select Catalog for Surface**: + * If `catalogId` is present, use the corresponding catalog to render that surface. Your renderer must be able to look up the catalog from its pre-compiled list or from the inline definitions it just sent. + * If `catalogId` is **absent**, you **must** default to using the Standard Catalog for v0.8 for that surface. + +6. **Manage Multiple Catalogs**: Your renderer must be architected to handle multiple surfaces being rendered with different catalogs simultaneously. A dictionary mapping `surfaceId` to the chosen `catalog` is a common approach. From a9fa288fffaedbc49bae17634d8032ec2a93ca50 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 14:46:31 +1030 Subject: [PATCH 07/12] Some manual tweaks --- .../0.8/docs/a2ui_extension_specification.md | 16 +++++++--------- specification/0.8/docs/a2ui_protocol.md | 7 +++++-- .../0.8/json/catalog_description_schema.json | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/specification/0.8/docs/a2ui_extension_specification.md b/specification/0.8/docs/a2ui_extension_specification.md index 9e9433b3b..61eeccf9d 100644 --- a/specification/0.8/docs/a2ui_extension_specification.md +++ b/specification/0.8/docs/a2ui_extension_specification.md @@ -12,7 +12,7 @@ This is the only URI accepted for this extension. ## Core Concepts -The A2UI extension is built on three main concepts: +The A2UI extension is built on the following main concepts: Surfaces: A "Surface" is a distinct, controllable region of the client's UI. The spec uses a surfaceId to direct updates to specific surfaces (e.g., a main content area, a side panel, or a new chat bubble). This allows a single agent stream to manage multiple UI areas independently. @@ -26,7 +26,10 @@ Server-to-Client Message Schema: The core wire format for messages sent from the Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., userAction). -Agent Capability Declaration +Client Capabilities: The client sends its capabilities to the server in an `a2uiClientCapabilities` object. This object is included in the `metadata` field of every A2A `Message` sent from the client to the server.This object allows the client to declare which catalogs it supports. + +## Agent Card details + Agents advertise their A2UI capabilities in their AgentCard within the `AgentCapabilities.extensions` list. The `params` object defines the agent's specific UI support. Example AgentExtension block: @@ -42,15 +45,10 @@ Example AgentExtension block: } ``` -#### Parameter Definitions +### Parameter Definitions - `params.acceptsInlineCatalogs`: (OPTIONAL) A boolean indicating if the agent can accept an `inlineCatalogs` array in the client's `a2uiClientCapabilities`. If omitted, this defaults to `false`. -Client Capabilities -The client sends its capabilities to the server in an `a2uiClientCapabilities` object. This object is **not** sent as a standalone message, but is instead included in the `metadata` field of every A2A `Message` sent from the client to the server. - -This object allows the client to declare which catalogs it supports. For a complete definition of this object and the catalog negotiation process, please see the main [A2UI Protocol Specification](./a2ui_protocol.md). - -Extension Activation +## Extension Activation Clients indicate their desire to use the A2UI extension by specifying it via the transport-defined A2A extension activation mechanism. For JSON-RPC and HTTP transports, this is indicated via the X-A2A-Extensions HTTP header. diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index 99528954a..caf85e8f6 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -203,8 +203,8 @@ The server (agent) advertises its capabilities in its Agent Card as part of the In **every** message sent to the server, the client includes an `a2uiClientCapabilities` object within the A2A `Message` metadata. This object informs the server of all catalogs the client can render. -- `supportedCatalogIds` (array of strings, required): A list of identifiers for all pre-defined catalogs the client supports. The client MUST always include the standard catalog ID here. -- `inlineCatalogs` (array of objects, optional): An array of full Catalog Definition Documents. This allows a client to provide custom, on-the-fly catalogs. This should only be provided if the server has advertised `acceptsInlineCatalogs: true`. +- `supportedCatalogIds` (array of strings, required): A list of identifiers for all pre-defined catalogs the client supports. The client must explicitly include the standard catalog ID here if it supports the standard catalog. +- `inlineCatalogs` (array of objects, optional): An array of full Catalog Definition Documents. This allows a client to provide custom, on-the-fly catalogs. This may only be provided if the server has advertised `acceptsInlineCatalogs: true`. **Example A2A Message with Client Capabilities:** ```json @@ -261,6 +261,9 @@ Each surface can use a different catalog, providing a high degree of flexibility When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., a custom schema combining `server_to_client.json` with your `my-company.com:custom-reporting-catalog-1.2` definition). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation. +See `server_to_client_with_standard_catalog.json` for an example of a resolved +schema which has the components substituted in. + ### 2.2. The `surfaceUpdate` Message This message is the primary way UI structure is defined. It contains a `surfaceId` and a `components` array. diff --git a/specification/0.8/json/catalog_description_schema.json b/specification/0.8/json/catalog_description_schema.json index ad8cf579e..8338c37a9 100644 --- a/specification/0.8/json/catalog_description_schema.json +++ b/specification/0.8/json/catalog_description_schema.json @@ -6,7 +6,7 @@ "properties": { "catalogId": { "title": "Catalog ID", - "description": "A string that uniquely identifies this catalog. It is recommended to use a reverse-domain name notation, e.g. 'com.example.my_catalog'.", + "description": "A string that uniquely identifies this catalog. It is recommended to prefix this with an internet domain that you own, to avoid conflicts e.g. mycompany.com:somecatalog'.", "type": "string" }, "components": { From d83fc18438dd8c5f9539aa9f75d21d7fbf459a43 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 27 Nov 2025 14:51:24 +1030 Subject: [PATCH 08/12] Update docs about versioning etc --- specification/0.8/docs/a2ui_protocol.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index caf85e8f6..4df11d316 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -172,6 +172,8 @@ A **Catalog** defines the contract between the server and the client for the UI There is a **Standard Catalog** associated with each version of the A2UI protocol. For v0.8, its identifier is `a2ui.org:standard_catalog_0_8_0`. +Catalog IDs are simple strings. While they can be anything, it's recommended to use an internet domain you own as a prefix (e.g., `my-company.com:my-custom-catalog`) to avoid collisions. Furthermore, if any changes are made to a catalog that could break compatibility between an agent and renderer, a new `catalogId` **must** be assigned. This ensures clear versioning and prevents unexpected behavior if an agent has changes but the client does not, or vice versa. + The negotiation process allows the client and server to agree on which catalog to use for a given UI surface. This process is designed to be flexible, supporting standard, custom, and even dynamically-defined catalogs. The flow is as follows: From 053092904684a9bca24a0f9aa21e94934982468b Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Thu, 4 Dec 2025 09:21:11 +1030 Subject: [PATCH 09/12] Update spec based on feedback --- specification/0.8/docs/a2ui_protocol.md | 36 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index 4df11d316..f25c2be70 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -170,9 +170,9 @@ A2UI's component model is designed for flexibility, separating the protocol from A **Catalog** defines the contract between the server and the client for the UI that can be rendered. It contains a list of supported component types (e.g., `Row`, `Text`), their properties, and available styles. A catalog is defined by a **Catalog Definition Document**. -There is a **Standard Catalog** associated with each version of the A2UI protocol. For v0.8, its identifier is `a2ui.org:standard_catalog_0_8_0`. +There is a **Standard Catalog** associated with each version of the A2UI protocol. For v0.8, its identifier is `https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json`. -Catalog IDs are simple strings. While they can be anything, it's recommended to use an internet domain you own as a prefix (e.g., `my-company.com:my-custom-catalog`) to avoid collisions. Furthermore, if any changes are made to a catalog that could break compatibility between an agent and renderer, a new `catalogId` **must** be assigned. This ensures clear versioning and prevents unexpected behavior if an agent has changes but the client does not, or vice versa. +Catalog IDs are simple string identifiers. While they can be anything, it is conventional to use a URI within a domain that you own, to simplify debugging, avoid confusion, and avoid name collisions. Furthermore, if any changes are made to a catalog that could break compatibility between an agent and renderer, a new `catalogId` **must** be assigned. This ensures clear versioning and prevents unexpected behavior if an agent has changes but the client does not, or vice versa. The negotiation process allows the client and server to agree on which catalog to use for a given UI surface. This process is designed to be flexible, supporting standard, custom, and even dynamically-defined catalogs. @@ -203,10 +203,10 @@ The server (agent) advertises its capabilities in its Agent Card as part of the #### 2. Client Declares Supported Catalogs -In **every** message sent to the server, the client includes an `a2uiClientCapabilities` object within the A2A `Message` metadata. This object informs the server of all catalogs the client can render. +In **every** message sent to the server, the client includes an `a2uiClientCapabilities` object within the A2A `Message` metadata. This object informs the agent server of all catalogs the client can render. -- `supportedCatalogIds` (array of strings, required): A list of identifiers for all pre-defined catalogs the client supports. The client must explicitly include the standard catalog ID here if it supports the standard catalog. -- `inlineCatalogs` (array of objects, optional): An array of full Catalog Definition Documents. This allows a client to provide custom, on-the-fly catalogs. This may only be provided if the server has advertised `acceptsInlineCatalogs: true`. +- `supportedCatalogIds` (array of strings, required): A list of identifiers for all pre-defined catalogs the client supports. The client must explicitly include the standard catalog ID here if it supports the standard catalog. The contents of these catalogs are expected to be compiled into the agent server and not downloaded at runtime, in order to prevent malicious content being injected into the prompt dynamically, and ensure predictable results. +- `inlineCatalogs` (array of objects, optional): An array of full Catalog Definition Documents. This allows a client to provide custom, on-the-fly catalogs, typically for use in local development workflows where it is faster to update a catalog in one place on the client. This may only be provided if the server has advertised `acceptsInlineCatalogs: true`. **Example A2A Message with Client Capabilities:** ```json @@ -214,12 +214,12 @@ In **every** message sent to the server, the client includes an `a2uiClientCapab "metadata": { "a2uiClientCapabilities": { "supportedCatalogIds": [ - "a2ui.org:standard_catalog_0_8_0", - "my-company.com:custom-reporting-catalog-1.2" + "https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json", + "https://my-company.com/a2ui_catalogs/custom-reporting-catalog-1.2" ], "inlineCatalogs": [ { - "catalogId": "my-company.com:temp-signature-pad-catalog", + "catalogId": "https://my-company.com/inline_catalogs/temp-signature-pad-catalog", "components": { "SignaturePad": { "type": "object", @@ -245,23 +245,35 @@ The server receives the client's capabilities and chooses a catalog to use for a - `catalogId` (string, optional): The identifier of the chosen catalog. This ID must be one of the `supportedCatalogIds` or the `catalogId` from one of the `inlineCatalogs` provided by the client. -If the `catalogId` is omitted, the client **MUST** default to the standard catalog for the protocol version (`a2ui.org:standard_catalog_0_8_0`). +If the `catalogId` is omitted, the client **MUST** default to the standard catalog for the protocol version (`https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json`). **Example `beginRendering` Message:** ```json { "beginRendering": { "surfaceId": "unique-surface-1", - "catalogId": "my-company.com:custom-reporting-catalog-1.2", + "catalogId": "https://my-company.com/inline_catalogs/temp-signature-pad-catalog", "root": "root-component-id" } } ``` -Each surface can use a different catalog, providing a high degree of flexibility. + +Each surface can use a different catalog, providing a high degree of flexibility, particularly in multi-agent systems where different agents may support different catalogs. #### Schemas for Developers -When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., a custom schema combining `server_to_client.json` with your `my-company.com:custom-reporting-catalog-1.2` definition). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation. +When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., a custom schema combining `server_to_client.json` with your `https://my-company.com/a2ui_catalogs/custom-reporting-catalog-1.2` definition). This provides the LLM with a strict definition of all available components and their properties, as well as the catalog-specific styles, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation. + +In order to do the substitution, based on the standard `server_to_client_schema` and a `custom_catalog_definition` object, you can use JSON manipulation logic similar to: + +```py +component_properties = custom_catalog_definition["components"] +style_properties = custom_catalog_definition["components"] +resolved_schema = copy.deepcopy(server_to_client_schema) + +resolved_schema["properties"]["surfaceUpdate"]["properties"]["components"]["items"]["properties"]["component"]["properties"] = component_properties +resolved_schema["properties"]["beginRendering"]["properties"]["styles"]["properties"] = style_properties +``` See `server_to_client_with_standard_catalog.json` for an example of a resolved schema which has the components substituted in. From 88e88e67dad1f890a2c2ccc3c0cfe64152fe69a8 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Mon, 8 Dec 2025 15:37:23 +1030 Subject: [PATCH 10/12] Update angular rizzcharts to use catalogId instead o catalogUri --- .../rizzcharts/src/components/toolbar/toolbar.html | 2 +- .../rizzcharts/src/components/toolbar/toolbar.ts | 14 +++++++------- .../rizzcharts/src/services/a2a_service.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/angular/projects/rizzcharts/src/components/toolbar/toolbar.html b/angular/projects/rizzcharts/src/components/toolbar/toolbar.html index c2f12f1e7..09ab564c3 100644 --- a/angular/projects/rizzcharts/src/components/toolbar/toolbar.html +++ b/angular/projects/rizzcharts/src/components/toolbar/toolbar.html @@ -24,7 +24,7 @@ A2UI Component Catalog - + @for (option of catalogs; track option) { {{ option.viewValue }} } diff --git a/angular/projects/rizzcharts/src/components/toolbar/toolbar.ts b/angular/projects/rizzcharts/src/components/toolbar/toolbar.ts index 3cc090eef..acefd35dd 100644 --- a/angular/projects/rizzcharts/src/components/toolbar/toolbar.ts +++ b/angular/projects/rizzcharts/src/components/toolbar/toolbar.ts @@ -19,10 +19,10 @@ import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatToolbarModule } from '@angular/material/toolbar'; -import {MatInputModule} from '@angular/material/input'; -import {MatSelectChange, MatSelectModule} from '@angular/material/select'; -import {MatFormFieldModule} from '@angular/material/form-field'; -import {FormsModule} from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectChange, MatSelectModule } from '@angular/material/select'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { FormsModule } from '@angular/forms'; import { A2aService } from '@rizzcharts/services/a2a_service'; @Component({ @@ -36,16 +36,16 @@ export class Toolbar { catalogs = [ { - value: 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/json/standard_catalog_definition.json', + value: 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/json/standard_catalog_definition.json', viewValue: 'Standard' }, { - value: 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/a2a_agents/python/adk/samples/rizzcharts/rizzcharts_catalog_definition.json', + value: 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/a2a_agents/python/adk/samples/rizzcharts/rizzcharts_catalog_definition.json', viewValue: 'Rizzcharts Custom' }, ]; ngOnInit() { - this.a2aService.supportedCatalogUris = this.catalogs.map(c => c.value); + this.a2aService.supportedCatalogIds = this.catalogs.map(c => c.value); } } diff --git a/angular/projects/rizzcharts/src/services/a2a_service.ts b/angular/projects/rizzcharts/src/services/a2a_service.ts index 38e8bdc5f..8852ac016 100644 --- a/angular/projects/rizzcharts/src/services/a2a_service.ts +++ b/angular/projects/rizzcharts/src/services/a2a_service.ts @@ -20,7 +20,7 @@ import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class A2aService implements A2aServiceInterface { - public supportedCatalogUris: string[] = [ + public supportedCatalogIds: string[] = [ 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/json/standard_catalog_definition.json', 'https://raw.githubusercontent.com/google/A2UI/refs/heads/main/a2a_agents/python/adk/samples/rizzcharts/rizzcharts_catalog_definition.json' ]; @@ -32,7 +32,7 @@ export class A2aService implements A2aServiceInterface { 'parts': parts, 'metadata': { "clientUiCapabilities": { - "supportedCatalogUris": this.supportedCatalogUris + "supportedCatalogIds": this.supportedCatalogIds } }, 'context_id': this.contextId From 3034d165d78cd9bc030a91eded12b78973559690 Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Mon, 8 Dec 2025 15:37:39 +1030 Subject: [PATCH 11/12] Update specification to make agent card advertise supported catalogs --- specification/0.8/docs/a2ui_extension_specification.md | 7 ++++++- specification/0.8/docs/a2ui_protocol.md | 9 ++++++++- specification/0.8/docs/custom_catalog_changes.md | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/specification/0.8/docs/a2ui_extension_specification.md b/specification/0.8/docs/a2ui_extension_specification.md index 61eeccf9d..bfa96253d 100644 --- a/specification/0.8/docs/a2ui_extension_specification.md +++ b/specification/0.8/docs/a2ui_extension_specification.md @@ -6,7 +6,7 @@ This extension implements the A2UI (Agent-to-Agent UI) spec, a format for agents ## Extension URI -The URI of this extension is https://raw.githubusercontent.com/google/A2UI/refs/heads/main/specification/0.8/docs/a2ui_extension_specification.md +The URI of this extension is https://a2ui.org/ext/a2a-ui/v0.8 This is the only URI accepted for this extension. @@ -40,12 +40,17 @@ Example AgentExtension block: "description": "Ability to render A2UI", "required": false, "params": { + "supportedCatalogIds": [ + "https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json", + "https://my-company.com/a2ui/v0.8/my_custom_catalog.json" + ], "acceptsInlineCatalogs": true } } ``` ### Parameter Definitions +- `params.supportedCatalogIds`: (OPTIONAL) An array of strings, where each string is a URI pointing to a component Catalog Definition Schema that the agent can generate. - `params.acceptsInlineCatalogs`: (OPTIONAL) A boolean indicating if the agent can accept an `inlineCatalogs` array in the client's `a2uiClientCapabilities`. If omitted, this defaults to `false`. ## Extension Activation diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index f25c2be70..8b41b7a7c 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -180,8 +180,9 @@ The flow is as follows: #### 1. Server Advertises Capabilities -The server (agent) advertises its capabilities in its Agent Card as part of the A2A protocol. For A2UI, this includes whether it can handle catalogs defined inline by the client. +The server (agent) advertises its capabilities in its Agent Card as part of the A2A protocol. For A2UI, this includes which catalogs it supports and whether it can handle catalogs defined inline by the client. +- `supportedCatalogIds` (array of strings, optional): A list of IDs for all pre-defined catalogs the agent is known to support. - `acceptsInlineCatalogs` (boolean, optional): If `true`, the server can process `inlineCatalogs` sent by the client. Defaults to `false`. **Example Server Agent Card Snippet:** @@ -193,6 +194,10 @@ The server (agent) advertises its capabilities in its Agent Card as part of the { "uri": "https://a2ui.org/ext/a2a-ui/v0.8", "params": { + "supportedCatalogIds": [ + "https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json", + "https://my-company.com/a2ui/v0.8/my_custom_catalog.json" + ], "acceptsInlineCatalogs": true } } @@ -201,6 +206,8 @@ The server (agent) advertises its capabilities in its Agent Card as part of the } ``` +Note that this is not a strict contract and purely included as a signal to help orchestrators and clients identify agents with matching UI capabilities. At runtime, orchestrating agents may dynamically delegate tasks to subagents which support additional catalogs that the orchestrating agent did not advertise. Thus, clients should consider the advertised supportedCatalogIds as a subset of the true catalogs that the agent or its subagents may support. + #### 2. Client Declares Supported Catalogs In **every** message sent to the server, the client includes an `a2uiClientCapabilities` object within the A2A `Message` metadata. This object informs the agent server of all catalogs the client can render. diff --git a/specification/0.8/docs/custom_catalog_changes.md b/specification/0.8/docs/custom_catalog_changes.md index f0605f868..fd68de71a 100644 --- a/specification/0.8/docs/custom_catalog_changes.md +++ b/specification/0.8/docs/custom_catalog_changes.md @@ -6,7 +6,7 @@ The previous mechanism, which involved a single, one-time `clientUiCapabilities` ## Key Changes to the Protocol -1. **Agent Capability Advertisement (`acceptsInlineCatalogs`)**: The agent's role in negotiation has been simplified. It now only declares whether it is capable of processing catalogs defined "inline" by the client. +1. **Agent Capability Advertisement (`supportedCatalogIds`, `acceptsInlineCatalogs`)**: The agent's role in negotiation has been expanded. It now can declare a list of supported catalog IDs, in addition to whether it is capable of processing catalogs defined "inline" by the client. * **Relevant Doc**: [`a2ui_extension_specification.md`](./a2ui_extension_specification.md) 2. **Client Capabilities via A2A Metadata**: The client now sends its capabilities in an `a2uiClientCapabilities` object. Crucially, this is no longer a standalone message but is included in the `metadata` field of **every** A2A message sent to the agent. @@ -29,7 +29,7 @@ The previous mechanism, which involved a single, one-time `clientUiCapabilities` Your responsibilities are to process the client's declared capabilities and make a rendering choice. -1. **Advertise Capability**: In the agent's capability card, add the `acceptsInlineCatalogs: true` parameter within the A2UI extension block if you intend to support catalogs sent dynamically from the client. +1. **Advertise Capability**: In the agent's capability card, add the `supportedCatalogIds` array and the `acceptsInlineCatalogs: true` parameter within the A2UI extension block to declare which catalogs you support and whether you can handle dynamic ones. 2. **Parse Client Capabilities**: On every incoming A2A message, your library must parse the `metadata.a2uiClientCapabilities` object to determine which catalogs the client supports. You will get a list of `supportedCatalogIds` and potentially a list of `inlineCatalogs`. From 08c5cb6b85c60e7ed4ee196a5bb8d6ea1043b5ef Mon Sep 17 00:00:00 2001 From: Jacob Simionato Date: Tue, 9 Dec 2025 07:15:32 +1030 Subject: [PATCH 12/12] Update URI vs ID example --- specification/0.8/docs/custom_catalog_changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/0.8/docs/custom_catalog_changes.md b/specification/0.8/docs/custom_catalog_changes.md index fd68de71a..559eb26f9 100644 --- a/specification/0.8/docs/custom_catalog_changes.md +++ b/specification/0.8/docs/custom_catalog_changes.md @@ -35,7 +35,7 @@ Your responsibilities are to process the client's declared capabilities and make 3. **Choose a Catalog**: Before rendering a UI, decide which catalog to use. Your choice must be one of the catalogs advertised by the client in the capabilities object. -4. **Specify Catalog on Render**: When sending the `beginRendering` message for a surface, set the `catalogId` field to the ID of your chosen catalog (e.g., `"my-company.com:custom-catalog-1.2"`). If you do not set this field, you are implicitly requesting the use of the standard catalog. +4. **Specify Catalog on Render**: When sending the `beginRendering` message for a surface, set the `catalogId` field to the ID of your chosen catalog (e.g., `"https://my-company.com/inline_catalogs/my-custom-catalog"`). If you do not set this field, you are implicitly requesting the use of the standard catalog. 5. **Generate Compliant UI**: Ensure that all components generated in subsequent `surfaceUpdate` messages for that surface conform to the properties and types defined in the chosen catalog.