From 6ec69e0f0ecb31a3c1cbef7b2900d6bc32dc2c97 Mon Sep 17 00:00:00 2001 From: Ava Mattie <6314286+ava-cassiopeia@users.noreply.github.com> Date: Mon, 26 Jan 2026 22:48:54 +0000 Subject: [PATCH 1/2] Make titles in README more consistent with style guide --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 593fdb929..82406667b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ to generate or populate rich user interfaces. *A gallery of A2UI rendered cards, showing a variety of UI compositions that A2UI can achieve.* -## ⚠️ Status: Early Stage Public Preview +## ⚠️ Status: Early stage public preview > **Note:** A2UI is currently in **v0.8 (Public Preview)**. The specification and implementations are functional but are still evolving. We are opening the project to @@ -30,7 +30,7 @@ component library (Flutter, Angular, Lit, etc.). This approach ensures that agent-generated UIs are **safe like data, but expressive like code**. -## High-Level Philosophy +## High-Level philosophy A2UI was designed to address the specific challenges of interoperable, cross-platform, generative or template-based UI responses from agents. @@ -63,7 +63,7 @@ places security firmly in the developer's hands, enabling them to enforce strict sandboxing policies and "trust ladders" directly within their custom component logic rather than relying solely on the core system. -## Use Cases +## Use cases Some of the use cases include: @@ -98,7 +98,7 @@ A2UI is designed to be a lightweight format, but it fits into a larger ecosystem * **Host Frameworks:** Requires a host application built in a supported framework (currently: Web or Flutter). -## Getting Started +## Getting started The best way to understand A2UI is to run the samples. @@ -108,7 +108,7 @@ The best way to understand A2UI is to run the samples. * Python (for agent samples) * A valid [Gemini API Key](https://aistudio.google.com/) is required for the samples. -### Running the Restaurant Finder Demo +### Running the Restaurant Finder demo 1. **Clone the repository:** @@ -117,7 +117,7 @@ The best way to understand A2UI is to run the samples. cd A2UI ``` -2. **Set your API Key:** +2. **Set your API key:** ```bash export GEMINI_API_KEY="your_gemini_api_key" @@ -160,10 +160,10 @@ to try out as well. We hope to work with the community on the following: -* **Spec Stabilization:** Moving towards a v1.0 specification. -* **More Renderers:** Adding official support for React, Jetpack Compose, iOS (SwiftUI), and more. -* **Additional Transports:** Support for REST and more. -* **Additional Agent Frameworks:** Genkit, LangGraph, and more. +* **Spec stabilization:** Moving towards a v1.0 specification. +* **More renderers:** Adding official support for React, Jetpack Compose, iOS (SwiftUI), and more. +* **Additional transports:** Support for REST and more. +* **Additional Agent frameworks:** Genkit, LangGraph, and more. ## Contribute From d3617c498d18805fae4757241f987a1fa2bab718 Mon Sep 17 00:00:00 2001 From: Ava Mattie <6314286+ava-cassiopeia@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:04:46 +0000 Subject: [PATCH 2/2] Update non docs/ markdown files --- README.md | 2 +- a2a_agents/python/a2ui_agent/README.md | 8 +- renderers/lit/README | 9 -- samples/agent/adk/contact_lookup/README.md | 6 +- .../v0_8/docs/a2ui_extension_specification.md | 12 +- specification/v0_8/docs/a2ui_protocol.md | 8 +- .../v0_8/docs/custom_catalog_changes.md | 44 +++--- .../v0_9/docs/a2ui_extension_specification.md | 18 +-- specification/v0_9/docs/a2ui_protocol.md | 136 +++++++++--------- 9 files changed, 117 insertions(+), 126 deletions(-) delete mode 100644 renderers/lit/README diff --git a/README.md b/README.md index 82406667b..7d3783497 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ component library (Flutter, Angular, Lit, etc.). This approach ensures that agent-generated UIs are **safe like data, but expressive like code**. -## High-Level philosophy +## High-level philosophy A2UI was designed to address the specific challenges of interoperable, cross-platform, generative or template-based UI responses from agents. diff --git a/a2a_agents/python/a2ui_agent/README.md b/a2a_agents/python/a2ui_agent/README.md index d15bca8bb..5edef04bd 100644 --- a/a2a_agents/python/a2ui_agent/README.md +++ b/a2a_agents/python/a2ui_agent/README.md @@ -1,8 +1,8 @@ -# A2UI Agent Implementation +# A2UI Agent implementation The `a2a_agents/python/a2ui_agent/` is the Python implementation of the a2ui agent library. -### Extension Components (`src/a2ui/extension`) +### Extension components (`src/a2ui/extension`) The `src/a2ui/extension` directory contains the core logic for the A2UI agent extension: @@ -10,7 +10,7 @@ The `src/a2ui/extension` directory contains the core logic for the A2UI agent ex * **`a2ui_schema_utils.py`**: Schema manipulation helpers. * **`send_a2ui_to_client_toolset.py`**: An example implementation of using ADK toolcalls to implement A2UI. -## Running Tests +## Running tests 1. Navigate to the a2ui_agent dir: @@ -40,4 +40,4 @@ All operational data received from an external agent—including its AgentCard, Similarly, any UI definition or data stream received must be treated as untrusted. Malicious agents could attempt to spoof legitimate interfaces to deceive users (phishing), inject malicious scripts via property values (XSS), or generate excessive layout complexity to degrade client performance (DoS). If your application supports optional embedded content (such as iframes or web views), additional care must be taken to prevent exposure to malicious external sites. -Developer Responsibility: Failure to properly validate data and strictly sandbox rendered content can introduce severe vulnerabilities. Developers are responsible for implementing appropriate security measures—such as input sanitization, Content Security Policies (CSP), strict isolation for optional embedded content, and secure credential handling—to protect their systems and users. \ No newline at end of file +Developer Responsibility: Failure to properly validate data and strictly sandbox rendered content can introduce severe vulnerabilities. Developers are responsible for implementing appropriate security measures—such as input sanitization, Content Security Policies (CSP), strict isolation for optional embedded content, and secure credential handling—to protect their systems and users. diff --git a/renderers/lit/README b/renderers/lit/README deleted file mode 100644 index 2e908410d..000000000 --- a/renderers/lit/README +++ /dev/null @@ -1,9 +0,0 @@ -Lit implementation of A2UI. - -Important: The sample code provided is for demonstration purposes and illustrates the mechanics of A2UI and the Agent-to-Agent (A2A) protocol. When building production applications, it is critical to treat any agent operating outside of your direct control as a potentially untrusted entity. - -All operational data received from an external agent—including its AgentCard, messages, artifacts, and task statuses—should be handled as untrusted input. For example, a malicious agent could provide crafted data in its fields (e.g., name, skills.description) that, if used without sanitization to construct prompts for a Large Language Model (LLM), could expose your application to prompt injection attacks. - -Similarly, any UI definition or data stream received must be treated as untrusted. Malicious agents could attempt to spoof legitimate interfaces to deceive users (phishing), inject malicious scripts via property values (XSS), or generate excessive layout complexity to degrade client performance (DoS). If your application supports optional embedded content (such as iframes or web views), additional care must be taken to prevent exposure to malicious external sites. - -Developer Responsibility: Failure to properly validate data and strictly sandbox rendered content can introduce severe vulnerabilities. Developers are responsible for implementing appropriate security measures—such as input sanitization, Content Security Policies (CSP), strict isolation for optional embedded content, and secure credential handling—to protect their systems and users. \ No newline at end of file diff --git a/samples/agent/adk/contact_lookup/README.md b/samples/agent/adk/contact_lookup/README.md index 1fdaad2ec..cc8aa3f8a 100644 --- a/samples/agent/adk/contact_lookup/README.md +++ b/samples/agent/adk/contact_lookup/README.md @@ -1,4 +1,4 @@ -# A2UI Contact Lookup Agent Sample +# A2UI Contact Lookup Agent sample This sample uses the Agent Development Kit (ADK) along with the A2A protocol to create a simple "Contact Lookup" agent that is hosted as an A2A server. @@ -8,7 +8,7 @@ This sample uses the Agent Development Kit (ADK) along with the A2A protocol to - [UV](https://docs.astral.sh/uv/) - Access to an LLM and API Key -## Running the Sample +## Running the sample 1. Navigate to the samples directory: @@ -38,4 +38,4 @@ All operational data received from an external agent—including its AgentCard, Similarly, any UI definition or data stream received must be treated as untrusted. Malicious agents could attempt to spoof legitimate interfaces to deceive users (phishing), inject malicious scripts via property values (XSS), or generate excessive layout complexity to degrade client performance (DoS). If your application supports optional embedded content (such as iframes or web views), additional care must be taken to prevent exposure to malicious external sites. -Developer Responsibility: Failure to properly validate data and strictly sandbox rendered content can introduce severe vulnerabilities. Developers are responsible for implementing appropriate security measures—such as input sanitization, Content Security Policies (CSP), strict isolation for optional embedded content, and secure credential handling—to protect their systems and users. \ No newline at end of file +Developer Responsibility: Failure to properly validate data and strictly sandbox rendered content can introduce severe vulnerabilities. Developers are responsible for implementing appropriate security measures—such as input sanitization, Content Security Policies (CSP), strict isolation for optional embedded content, and secure credential handling—to protect their systems and users. diff --git a/specification/v0_8/docs/a2ui_extension_specification.md b/specification/v0_8/docs/a2ui_extension_specification.md index 98ecd7cb4..8afa7976a 100644 --- a/specification/v0_8/docs/a2ui_extension_specification.md +++ b/specification/v0_8/docs/a2ui_extension_specification.md @@ -1,4 +1,4 @@ -# A2UI (Agent-to-Agent UI) Extension Spec +# A2UI (Agent-to-Agent UI) Extension spec ## Overview @@ -10,7 +10,7 @@ The URI of this extension is https://a2ui.org/a2a-extension/a2ui/v0.8 This is the only URI accepted for this extension. -## Core Concepts +## Core concepts The A2UI extension is built on the following main concepts: @@ -49,11 +49,11 @@ Example AgentExtension block: } ``` -### Parameter Definitions +### 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 +## 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. @@ -62,7 +62,7 @@ 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). -## Data Encoding +## Data encoding A2UI messages are encoded as an A2A `DataPart`. @@ -86,4 +86,4 @@ Example A2UI DataPart: "mimeType": "application/json+a2ui" } } -``` \ No newline at end of file +``` diff --git a/specification/v0_8/docs/a2ui_protocol.md b/specification/v0_8/docs/a2ui_protocol.md index 6bfbe3a84..b546f7ed1 100644 --- a/specification/v0_8/docs/a2ui_protocol.md +++ b/specification/v0_8/docs/a2ui_protocol.md @@ -12,7 +12,7 @@ A Specification for a JSONL-Based, Streaming UI Protocol Created: Sep 19, 2025 Updated: Nov 12, 2025 -## Design Requirements +## Design requirements The A2UI (Agent to UI) protocol should be a system where an LLM can stream a platform-agnostic, abstract UI definition to a client, which then renders it progressively using a native widget set. Every major design choice is traced back to the core challenges of LLM generation, perceived performance, and platform independence. @@ -71,11 +71,11 @@ Client-to-server communication for user interactions is handled separately via a - `error`: Reports a client-side error. This keeps the primary data stream unidirectional. -## Section 1: Foundational Architecture and Data Flow +## Section 1: Foundational architecture and data flow This document specifies the architecture and data formats for the A2UI protocol. The design is guided by principles of strict separation of concerns, versioning, and progressive rendering. -### 1.1. Core Philosophy: Decoupling and Contracts +### 1.1. Core philosophy: decoupling and contracts The central philosophy of A2UI is the decoupling of three key elements: @@ -83,7 +83,7 @@ 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. 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. diff --git a/specification/v0_8/docs/custom_catalog_changes.md b/specification/v0_8/docs/custom_catalog_changes.md index 559eb26f9..d800bc012 100644 --- a/specification/v0_8/docs/custom_catalog_changes.md +++ b/specification/v0_8/docs/custom_catalog_changes.md @@ -1,58 +1,58 @@ -# Summary of Custom Catalog Negotiation Changes in A2UI v0.8 +# 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 +## Key changes to the protocol -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. +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. +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) + * **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). +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) +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 +## Implementation guide for developers -### For Agent (Server) Library 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 `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. +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`. +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., `"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. +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. +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 +### 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. +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. +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**: +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. +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. diff --git a/specification/v0_9/docs/a2ui_extension_specification.md b/specification/v0_9/docs/a2ui_extension_specification.md index d8060f9e4..40c1d1d4f 100644 --- a/specification/v0_9/docs/a2ui_extension_specification.md +++ b/specification/v0_9/docs/a2ui_extension_specification.md @@ -1,4 +1,4 @@ -# A2UI (Agent-to-Agent UI) Extension Spec v0.9 +# A2UI (Agent-to-Agent UI) Extension spec v0.9 ## Overview @@ -10,7 +10,7 @@ The URI of this extension is https://a2ui.org/a2a-extension/a2ui/v0.9 This is the only URI accepted for this extension. -## Core Concepts +## Core concepts The A2UI extension is built on the following main concepts: @@ -48,11 +48,11 @@ Example AgentExtension block: } ``` -### Parameter Definitions +### Parameter definitions - `params.supportedCatalogIds`: (OPTIONAL) An array of strings, where each string is a URI pointing to a 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 +## 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. @@ -61,7 +61,7 @@ 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 updateComponents) and the client is expected to send A2UI-specific events (like action). -## Data Encoding +## Data encoding A2UI messages are encoded as an A2A `DataPart`. @@ -71,13 +71,13 @@ To identify a `DataPart` as containing A2UI data, it must have the following met The `data` field of the `DataPart` contains a **single** A2UI JSON message (e.g., `createSurface`, `updateComponents`, `action`). It MUST NOT be an array of messages. -### Atomicity and Multiple Messages +### Atomicity and multiple messages To send multiple A2UI messages that should be processed atomically (e.g., creating a surface and immediately populating it), the sender MUST include multiple `DataPart`s within a single A2A `Message`. Receivers (both Clients and Agents) MUST process all A2UI `DataPart`s within a single A2A `Message` sequentially and atomically. For a renderer, this means the UI should not be repainted until all parts in the message have been applied. -### Server-to-Client Messages +### Server-to-client messages When an agent sends a message to a client (or another agent acting as a client/renderer), the `data` payload must validate against the **Server-to-Client Message Schema**. @@ -98,7 +98,7 @@ Example `createSurface` DataPart: } ``` -### Client-to-Server Events +### Client-to-server events When a client (or an agent forwarding an event) sends a message to an agent, it also uses a `DataPart` with the same `application/json+a2ui` MIME type. However, the `data` payload must validate against the **Client-to-Server Event Schema**. @@ -122,4 +122,4 @@ Example `action` DataPart: "mimeType": "application/json+a2ui" } } -``` \ No newline at end of file +``` diff --git a/specification/v0_9/docs/a2ui_protocol.md b/specification/v0_9/docs/a2ui_protocol.md index d289bad3b..7c6ca2bc6 100644 --- a/specification/v0_9/docs/a2ui_protocol.md +++ b/specification/v0_9/docs/a2ui_protocol.md @@ -34,14 +34,14 @@ Version 0.9 of the A2UI protocol represents a philosophical shift from previous This "prompt-first" approach offers several advantages: -1. **Richer Schema:** The protocol is no longer limited by the constraints of structured output formats. This allows for more readable, complex, and expressive component catalogs. +1. **Richer schema:** The protocol is no longer limited by the constraints of structured output formats. This allows for more readable, complex, and expressive component catalogs. 2. **Modularity:** The schema is now refactored into separate, more manageable components (e.g., [`common_types.json`], [`standard_catalog.json`], [`server_to_client.json`]), improving maintainability and modularity. The main disadvantage of this approach is that it requires more complex post-generation validation, as the LLM is not strictly constrained by the schema. This requires robust error handling and correction, so the system can identify discrepancies and attempt to fix them before rendering, or request a retry or correction from the LLM. See [the evolution guide](evolution_guide.md) for a detailed explanation of the differences between v0.8 and v0.9. -## Protocol Overview & Data Flow +## Protocol overview & data flow The A2UI protocol uses a unidirectional stream of JSON messages from the server to the client to describe and update the UI. The client consumes this stream, builds the UI, and renders it. User interactions are handled separately, typically by sending events to a different endpoint, which may in turn trigger new messages on the UI stream. @@ -51,7 +51,7 @@ Here is an example sequence of events (which don't have to be in exactly this or 2. **Update Surface:** Once a surface has been created, the server sends one or more `updateComponents` messages containing the definitions for all the components that will be part of the surface. 3. **Update Data Model:** Once a surface has been created, the server can send `updateDataModel` messages at any time to populate or change the data that the UI components will display. 4. **Render:** The client renders the UI for the surface, using the component definitions to build the structure and the data model to populate the content. -5. **Dynamic Updates:** As the user interacts with the application or as new information becomes available, the server can send additional `updateComponents` and `updateDataModel` messages to dynamically change the UI. +5. **Dynamic updates:** As the user interacts with the application or as new information becomes available, the server can send additional `updateComponents` and `updateDataModel` messages to dynamically change the UI. 6. **Delete Surface:** When a UI region is no longer needed, the server sends a `deleteSurface` message to remove it. ```mermaid @@ -77,42 +77,42 @@ sequenceDiagram Client-->>-Server: (UI is gone) ``` -## Transport Decoupling +## Transport decoupling The A2UI protocol is designed to be transport-agnostic. It defines the JSON message structure and the semantic contract between the server (Agent) and the client (Renderer), but it does not mandate a specific transport layer. -### The Transport Contract +### The transport contract To support A2UI, a transport layer must fulfill the following contract: -1. **Reliable Delivery**: Messages must be delivered in the order they were generated. A2UI relies on stateful updates (e.g., creating a surface before updating it), so out-of-order delivery can corrupt the UI state. -2. **Message Framing**: The transport must clearly delimit individual JSON envelope messages (e.g., using newlines in JSONL, WebSocket frames, or SSE events). -3. **Metadata Support**: The transport must provide a mechanism to associate metadata with messages. This is critical for: - * **Data Model Synchronization**: The `sendDataModel` feature requires the client to send the current data model state as metadata alongside user actions. - * **Capabilities Exchange**: Client capabilities (supported catalogs, custom components) are exchanged via metadata. -4. **Bidirectional Capability (Optional)**: While the rendering stream is unidirectional (Server -> Client), interactive applications require a return channel for `action` messages (Client -> Server). +1. **Reliable delivery**: Messages must be delivered in the order they were generated. A2UI relies on stateful updates (e.g., creating a surface before updating it), so out-of-order delivery can corrupt the UI state. +2. **Message framing**: The transport must clearly delimit individual JSON envelope messages (e.g., using newlines in JSONL, WebSocket frames, or SSE events). +3. **Metadata support**: The transport must provide a mechanism to associate metadata with messages. This is critical for: + * **Data model synchronization**: The `sendDataModel` feature requires the client to send the current data model state as metadata alongside user actions. + * **Capabilities exchange**: Client capabilities (supported catalogs, custom components) are exchanged via metadata. +4. **Bidirectional capability (optional)**: While the rendering stream is unidirectional (Server -> Client), interactive applications require a return channel for `action` messages (Client -> Server). -### Transport Bindings +### Transport bindings While A2UI is agnostic, it is most commonly used with the following transports. -#### A2A (Agent2Agent) Binding +#### A2A (Agent2Agent) binding [A2A (Agent-to-Agent)](https://a2a-protocol.org/latest/) is an excellent transport option for A2UI in agentic systems, extending A2A with additional payloads. A2A is uniquely capable of handling remote agent communication, and can also provide a secure and effecient transport between an agentic backend and front end application. -* **Message Mapping**: Each A2UI envelope (e.g., `updateComponents`) corresponds to the payload of a single A2A message Part. +* **Message mapping**: Each A2UI envelope (e.g., `updateComponents`) corresponds to the payload of a single A2A message Part. * **Metadata**: - * **Data Model**: When `sendDataModel` is active, the client's `a2uiClientDataModel` object is placed in the `metadata` field of the A2A message. + * **Data model**: When `sendDataModel` is active, the client's `a2uiClientDataModel` object is placed in the `metadata` field of the A2A message. * **Capabilities**: The `a2uiClientCapabilities` object is placed in the `metadata` field of every A2A message sent from the client to the server. * **Context**: A2UI sessions typically map to A2A `contextId`. All messages for a set of related surfaces should share the same `contextId`. -#### AG UI (Agent to User Interface) Binding +#### AG UI (Agent to User Interface) binding **[AG-UI](https://docs.ag-ui.com/introduction)** is also an excellent transport option for A2UI Agent–User Interaction protocol. AG UI provides convenient integrations into many agent frameworks and frontends. AG UI provides low latency and shared state message passing between front ends and agentic backends. -#### Other Transports +#### Other transports A2UI can also be carried over: @@ -121,11 +121,11 @@ A2UI can also be carried over: - **[WebSockets](https://en.wikipedia.org/wiki/WebSocket)**: For bidirectional, real-time sessions. **[REST](https://cloud.google.com/discover/what-is-rest-api?hl=en)**: For simple use case, REST APIs will work but lack streaming capabilities. -## The Protocol Schemas +## The protocol schemas A2UI v0.9 is defined by three interacting JSON schemas. -### Common Types +### Common types The [`common_types.json`] schema defines reusable primitives used throughout the protocol. @@ -137,7 +137,7 @@ The [`common_types.json`] schema defines reusable primitives used throughout the - **`ComponentId`**: A reference to the unique ID of another component within the same surface. -### Server to Client Message Structure: The Envelope +### Server to client message structure: the envelope The [`server_to_client.json`] schema is the top-level entry point. Every message streamed by the server must validate against this schema. It handles the message dispatching. @@ -147,20 +147,20 @@ The [`standard_catalog.json`] schema contains the definitions for all specific U Custom catalogs can be used to define additional UI components or modify the behavior of existing components. To use a custom catalog, simply include it in the prompt in place of the standard catalog. It should have the same form as the standard catalog, and use common elements in the [`common_types.json`] schema. -### Validator Compliance & Custom Catalogs +### Validator compliance & custom Catalogs To ensure that automated validators can verify the integrity of your UI tree (checking that parents reference existing children), custom catalogs MUST adhere to the following strict typing rules: -1. **Single Child References:** Any property that holds the ID of another component MUST use the `ComponentId` type defined in `common_types.json`. +1. **Single child references:** Any property that holds the ID of another component MUST use the `ComponentId` type defined in `common_types.json`. * Use: `"$ref": "common_types.json#/$defs/ComponentId"` * Do NOT use: `"type": "string"` -2. **List References:** Any property that holds a list of children or a template MUST use the `ChildList` type. +2. **List references:** Any property that holds a list of children or a template MUST use the `ChildList` type. * Use: `"$ref": "common_types.json#/$defs/ChildList"` Validators determine which fields represent structural links by looking for these specific schema references. If you use a raw string type for an ID, the validator will treat it as static text (like a URL or label) and will not check if the target component exists. -## Envelope Message Structure +## Envelope message structure The envelope defines four primary message types, and every message streamed by the server must be a JSON object containing exactly one of the following keys: `createSurface`, `updateComponents`, `updateDataModel`, or `deleteSurface`. The key indicates the type of message, and these are the messages that make up each message in the protocol stream. @@ -277,11 +277,11 @@ The following example demonstrates a complete interaction to render a Contact Fo {"deleteSurface":{"surfaceId":"contact_form_1"}} ``` -## Component Model +## Component model A2UI's component model is designed for flexibility, separating the protocol's structure from the set of available UI components. -### The Component Object +### The component object Each object in the `components` array of an `updateComponents` message defines a single UI component. It has the following structure: @@ -291,11 +291,11 @@ Each object in the `components` array of an `updateComponents` message defines a This structure is designed to be both flexible and strictly validated. -### The Component Catalog +### The component catalog The set of available UI components and functions is defined in a **Catalog**. The standard catalog is defined in [`standard_catalog.json`]. This allows for different clients to support different sets of components and functions, including custom ones. Advanced use cases may want to define their own custom catalogs to support custom front end design systems or renderers. The server must generate messages that conform to the catalog understood by the client. -### UI Composition: The Adjacency List Model +### UI composition: the adjacency list model The A2UI protocol defines the UI as a flat list of components. The tree structure is built implicitly using ID references. This is known as an adjacency list model. @@ -328,11 +328,11 @@ flowchart TD ``` -### Defining Actions +### Defining actions Interactive components (like `Button`) use an `action` property to define what happens when the user interacts with them. Actions can either trigger an event sent to the server or execute a local client-side function. -#### Server Actions +#### Server actions To send an event to the server, use the `event` property within the `action` object. It requires a `name` and an optional `context`. @@ -351,7 +351,7 @@ To send an event to the server, use the `event` property within the `action` obj } ``` -#### Local Actions +#### Local actions To execute a local function, use the `functionCall` property within the `action` object. This property references a standard `FunctionCall` object. @@ -370,37 +370,37 @@ To execute a local function, use the `functionCall` property within the `action` } ``` -## Data Model Representation: Binding, Scope +## Data model representation: binding, scope This section describes how UI components **represent** and reference data from the Data Model. A2UI relies on a strictly defined relationship between the UI structure (Components) and the state (Data Model), defining the mechanics of path resolution, variable scope during iteration. -### Path Resolution & Scope +### Path resolution & scope Data bindings in A2UI are defined using **JSON Pointers** ([RFC 6901]). How a pointer is resolved depends on the current **Evaluation Scope**. -> **Note on Progressive Rendering:** During the initial streaming phase, data paths may resolve to `undefined` if the `updateDataModel` message containing that data has not yet arrived. Renderers should handle `undefined` values gracefully (e.g., by treating them as empty strings or showing a loading indicator) to support progressive rendering. +> **Note on progressive rendering:** During the initial streaming phase, data paths may resolve to `undefined` if the `updateDataModel` message containing that data has not yet arrived. Renderers should handle `undefined` values gracefully (e.g., by treating them as empty strings or showing a loading indicator) to support progressive rendering. -#### The Root Scope +#### The root scope By default, all components operate in the **Root Scope**. - Paths starting with `/` (e.g., `/user/profile/name`) are **Absolute Paths**. They always resolve from the root of the Data Model, regardless of where the component is nested in the UI tree. -#### Collection Scopes (Relative Paths) +#### Collection scopes (relative paths) When a container component (such as `Column`, `Row`, or `List`) utilizes the **Template** feature of `ChildList`, it creates a new **Child Scope** for each item in the bound array. -- **Template Definition:** When a container binds its children to a path (e.g., `path: "/users"`), the client iterates over the array found at that location. -- **Scope Instantiation:** For every item in the array, the client instantiates the template component. -- **Relative Resolution:** Inside these instantiated components, any path that **does not** start with a forward slash `/` is treated as a **Relative Path**. +- **Template definition:** When a container binds its children to a path (e.g., `path: "/users"`), the client iterates over the array found at that location. +- **Scope instantiation:** For every item in the array, the client instantiates the template component. +- **Relative resolution:** Inside these instantiated components, any path that **does not** start with a forward slash `/` is treated as a **Relative Path**. - A relative path `firstName` inside a template iterating over `/users` resolves to `/users/0/firstName` for the first item, `/users/1/firstName` for the second, etc. -- **Mixing Scopes:** Components inside a Child Scope can still access the Root Scope by using an Absolute Path. +- **Mixing scopes:** Components inside a Child Scope can still access the Root Scope by using an Absolute Path. -#### Example: Scope Resolution +#### Example: scope resolution -**Data Model:** +**Data model:** ```json { @@ -412,7 +412,7 @@ When a container component (such as `Column`, `Row`, or `List`) utilizes the **T } ``` -**Component Definition:** +**Component definition:** ```json { @@ -442,19 +442,19 @@ When a container component (such as `Column`, `Row`, or `List`) utilizes the **T } ``` -#### Type Conversion +#### Type conversion When a non-string value is interpolated, the client converts it to a string: - **Numbers/Booleans**: Standard string representation. -- **Null/Undefined**: An empty string `""`. +- **null/undefined**: An empty string `""`. - **Objects/Arrays**: Stringified as JSON to ensure consistency across different client implementations. -### Two-Way Binding & Input Components +### Two-way binding & input components Interactive components that accept user input (`TextField`, `CheckBox`, `Slider`, `ChoicePicker`, `DateTimeInput`) establish a **Two-Way Binding** with the Data Model. -#### The Read/Write Contract +#### The read/write contract Unlike static display components (like `Text`), input components modify the client-side data model immediately upon user interaction. @@ -467,7 +467,7 @@ Because the local Data Model is the single source of truth, updates from input c - If a `TextField` is bound to `/user/name`, and a separate `Text` label is also bound to `/user/name`, the label must update in real-time as the user types in the text field. -#### Server Synchronization +#### Server synchronization It is critical to note that Two-Way Binding is **local to the client**. @@ -475,7 +475,7 @@ It is critical to note that Two-Way Binding is **local to the client**. - The updated state is sent to the server only when a specific **User Action** is triggered (e.g., a `Button` click). - When an `action` is dispatched, the `context` property of the action can reference the modified data paths to send the user's input back to the server. -#### Example: Form Submission Pattern +#### Example: form submission pattern 1. **Bind:** `TextField` is bound to `/formData/email`. 2. **Interact:** User types "jane@example.com". The local model at `/formData/email` is updated. @@ -494,13 +494,13 @@ It is critical to note that Two-Way Binding is **local to the client**. 4. **Send:** When clicked, the client resolves `/formData/email` (getting "jane@example.com") and sends it in the `action` payload. -## Data Model Updates: Synchronization and Convergence +## Data model updates: synchronization and convergence While the sections above describe how components reference data, this section defines how the Data Model itself is **updated** and synchronized. To support reliable data synchronization between the Renderer and the Agent that created the surface, the A2UI protocol uses a simple synchronization mechanism controlled by the `sendDataModel` property in the `createSurface` message. -### Server to Client Updates +### Server to client updates The server sends `updateDataModel` messages to modify the client's data model. These updates follow strict upsert semantics: @@ -555,7 +555,7 @@ _Replace the entire data model:_ } ``` -### Client to Server Updates +### Client to server updates When `sendDataModel` is set to `true` for a surface, the client automatically appends the **entire data model** of that surface to the metadata of every message (such as `action` or user query) sent to the server that created the surface. The data model is included using the transport's metadata facility (e.g., the `metadata` field in A2A or a header in HTTP). The payload follows the schema in [`a2ui_client_data_model.json`](../json/a2ui_client_data_model.json). @@ -564,11 +564,11 @@ When `sendDataModel` is set to `true` for a surface, the client automatically ap - **Payload**: The data model is included in the transport metadata, tagged by its `surfaceId`. - **Convergence**: The server treats the received data model as the current state of the client at the time of the action. -## Client-Side Logic & Validation +## Client-side logic & validation A2UI v0.9 generalizes client-side logic into **Functions**. These can be used for validation, data transformation, and dynamic property binding. -### Registered Functions +### Registered functions The client supports a set of named **Functions** (e.g., `required`, `regex`, `email`, `add`, `concat`) which are defined in the JSON schema (e.g. `standard_catalog.json`) alongside the component definitions. The server references these functions by name in `FunctionCall` objects. This avoids sending executable code. @@ -592,7 +592,7 @@ Input components (like `TextField`, `CheckBox`) can define a list of checks. Eac ] ``` -### Example: Button Validation +### Example: button validation Buttons can also define `checks`. If any check fails, the button is automatically disabled. This allows the button's state to depend on the validity of data in the model. @@ -675,7 +675,7 @@ The standard catalog defines the following theme properties that can be set in t | **iconUrl** | URI | A URL for an image (e.g., logo or avatar) that identifies the agent or tool associated with the surface. | | **agentDisplayName** | String | Text to be displayed next to the surface to identify the agent or tool that created it (e.g. "Weather Bot"). | -#### Identity and Attribution +#### Identity and attribution The `iconUrl` and `agentDisplayName` fields are used to provide attribution to the user, identifying which sub-agent or tool is responsible for a particular UI surface. @@ -685,11 +685,11 @@ In multi-agent systems or orchestrators, the orchestrator is responsible for set The `formatString` function supports embedding dynamic expressions directly within string properties. This allows for mixing static text with data model values and function results. -#### `formatString` Syntax +#### `formatString` syntax Interpolated expressions are enclosed in `${...}`. To include a literal `${` in a string, it must be escaped as `\${`. -#### `formatString` Data Model Binding +#### `formatString` data model binding Values from the data model can be interpolated using their JSON Pointer path. @@ -711,7 +711,7 @@ Values from the data model can be interpolated using their JSON Pointer path. } ``` -#### `formatString` Client-Side Functions +#### `formatString` client-side functions Results of client-side functions can be interpolated. Function calls are identified by the presence of parentheses `()`. @@ -720,14 +720,14 @@ Results of client-side functions can be interpolated. Function calls are identif Arguments can be **Literals** (quoted strings, numbers, or booleans), or **Nested Expressions**. -#### `formatString` Nested Interpolation +#### `formatString` nested interpolation Expressions can be nested using additional `${...}` wrappers inside an outer expression to make bindings explicit or to chain function calls. - **Explicit Binding**: `${formatDate(${/currentDate}, 'yyyy-MM-dd')}` - **Nested Functions**: `${upper(${now()})}` -#### `formatString` Type Conversion +#### `formatString` type conversion When a non-string value is interpolated, the client converts it to a string: @@ -735,7 +735,7 @@ When a non-string value is interpolated, the client converts it to a string: - **Null/Undefined**: An empty string `""`. - **Objects/Arrays**: Stringified as JSON to ensure consistency across different client implementations. -## Usage Pattern: The Prompt-Generate-Validate Loop +## Usage pattern: the prompt-generate-validate loop The A2UI protocol is designed to be used in a three-step loop with a Large Language Model: @@ -751,7 +751,7 @@ The A2UI protocol is designed to be used in a three-step loop with a Large Langu This loop allows for a high degree of flexibility and robustness, as the system can leverage the generative capabilities of the LLM while still enforcing the structural integrity of the UI protocol. -### Standard Validation Error Format +### Standard validation error format If validation fails, the client (or the system acting on behalf of the client) should send an `error` message back to the LLM. To ensure the LLM can understand and correct the error, use the following standard format within the `error` message payload: @@ -760,7 +760,7 @@ If validation fails, the client (or the system acting on behalf of the client) s - `path` (string, required): The JSON pointer to the field that failed validation (e.g. `/components/0/text`). - `message` (string, required): A short one-sentence description of why validation failed. -**Example Error Message:** +**Example error message:** ```json { @@ -773,7 +773,7 @@ If validation fails, the client (or the system acting on behalf of the client) s } ``` -## Client-to-Server Messages +## Client-to-server messages The protocol also defines messages that the client can send to the server, which are defined in the [`client_to_server.json`] schema. These are used for handling user interactions and reporting client-side information. @@ -789,11 +789,11 @@ This message is sent when the user interacts with a component that has an `actio - `timestamp` (string, required): An ISO 8601 timestamp. - `context` (object, required): A JSON object containing any context provided in the component's `action` property. -### Client Capabilities & Metadata +### Client capabilities & metadata In A2UI v0.9, client capabilities and other metadata are sent as part of the **Transport metadata** (e.g., A2A metadata) envelope in every message, rather than as first-class A2UI messages. -#### Client Capabilities +#### Client capabilities The `a2uiClientCapabilities` object in the metadata follows the [`a2ui_client_capabilities.json`] schema. @@ -802,7 +802,7 @@ The `a2uiClientCapabilities` object in the metadata follows the [`a2ui_client_ca - `supportedCatalogIds` (array of strings, required): URIs of supported catalogs. - `inlineCatalogs`: An array of inline catalog definitions provided directly by the client (useful for custom or ad-hoc components and functions). -#### Client Data Model +#### Client data model When `sendDataModel` is enabled for a surface, the client includes the `a2uiClientDataModel` object in the metadata, following the [`a2ui_client_data_model.json`] schema.