Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions specification/0.9/docs/a2ui_extension_specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# A2UI (Agent-to-Agent UI) Extension Spec v0.9

## Overview

This extension implements the A2UI (Agent-to-Agent UI) spec v0.9, a format for agents to send streaming, interactive user interfaces to clients.

## Extension URI

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

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.

Catalog Definition Document: The a2ui extension is catalog-agnostic. All UI components (e.g., Text, Row, Button) and functions (e.g., required, email) 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 several primary JSON schemas:

- Catalog Definition Schema: A standard format for defining a library of components and functions.
- Server-to-Client Message Schema: The core wire format for messages sent from the agent to the client (e.g., updateComponents, updateDataModel).
- Client-to-Server Event Schema: The core wire format for messages sent from the client to the agent (e.g., action).
- Client Capabilities Schema: The schema for the `a2uiClientCapabilities` object.

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:

```json
{
"uri": "https://a2ui.org/a2a-extension/a2ui/v0.9",
"description": "Ability to render A2UI v0.9",
"required": false,
"params": {
"supportedCatalogIds": [
"https://a2ui.dev/specification/0.9/standard_catalog.json",
"https://my-company.com/a2ui/v0.9/my_custom_catalog.json"
],
"acceptsInlineCatalogs": true
}
}
```

### 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
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 updateComponents) and the client is expected to send A2UI-specific events (like action).

## Data Encoding

A2UI messages are encoded as an A2A `DataPart`.

To identify a `DataPart` as containing A2UI data, it must have the following metadata:

- `mimeType`: `application/json+a2ui`

The `data` field of the `DataPart` contains the A2UI JSON message (e.g., `updateComponents`, `action`).

Example A2UI DataPart:

```json
{
"data": {
"createSurface": {
"surfaceId": "user_profile_surface",
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog.json"
}
},
"kind": "data",
"metadata": {
"mimeType": "application/json+a2ui"
}
}
```
33 changes: 17 additions & 16 deletions specification/0.9/docs/a2ui_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ 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.
2. **Modularity:** The schema is now refactored into separate, more manageable components (e.g., [`common_types.json`], [`standard_catalog_definition.json`], [`server_to_client.json`]), improving maintainability and modularity.
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.

Expand Down Expand Up @@ -100,7 +100,7 @@ The [`server_to_client.json`] schema is the top-level entry point. Every line st

### The Standard Catalog

The [`standard_catalog_definition.json`] schema contains the definitions for all specific UI components (e.g., `Text`, `Button`, `Row`). By separating this from the envelope, developers can easily swap in custom catalogs (e.g., `material_catalog.json` or `cupertino_catalog.json`) without rewriting the core protocol parser.
The [`standard_catalog.json`] schema contains the definitions for all specific UI components (e.g., `Text`, `Button`, `Row`) and functions (e.g., `required`, `email`). By separating this from the envelope, developers can easily swap in custom catalogs (e.g., `material_catalog.json` or `cupertino_catalog.json`) without rewriting the core protocol parser.

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.

Expand All @@ -115,15 +115,15 @@ This message signals the client to create a new surface and begin rendering it.
**Properties:**

- `surfaceId` (string, required): The unique identifier for the UI surface to be rendered.
- `catalogId` (string, required): A string that uniquely identifies the component catalog used for this surface. It is recommended to prefix this with an internet domain that you own, to avoid conflicts (e.g., `https://mycompany.com/1.0/somecatalog`).
- `catalogId` (string, required): A string that uniquely identifies the catalog (components and functions) used for this surface. It is recommended to prefix this with an internet domain that you own, to avoid conflicts (e.g., `https://mycompany.com/1.0/somecatalog`).

**Example:**

```json
{
"createSurface": {
"surfaceId": "user_profile_card",
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog_definition.json"
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog.json"
}
}
```
Expand Down Expand Up @@ -212,9 +212,9 @@ This message instructs the client to remove a surface and all its associated com
The following example demonstrates a complete interaction to render a Contact Form, expressed as a JSONL stream.

```jsonl
{"createSurface":{"surfaceId":"contact_form_1","catalogId":"https://a2ui.dev/specification/0.9/standard_catalog_definition.json"}}
{"updateComponents":{"surfaceId":"contact_form_1","components":[{"id":"root","component":"Column","children":["first_name_label","first_name_field","last_name_label","last_name_field","email_label","email_field","phone_label","phone_field","notes_label","notes_field","submit_button"]},{"id":"first_name_label","component":"Text","text":"First Name"},{"id":"first_name_field","component":"TextField","label":"First Name","value":{"path":"/contact/firstName"},"variant":"shortText"},{"id":"last_name_label","component":"Text","text":"Last Name"},{"id":"last_name_field","component":"TextField","label":"Last Name","value":{"path":"/contact/lastName"},"variant":"shortText"},{"id":"email_label","component":"Text","text":"Email"},{"id":"email_field","component":"TextField","label":"Email","value":{"path":"/contact/email"},"variant":"shortText","checks":[{"call":"email","message":"Please enter a valid email address."}]},{"id":"phone_label","component":"Text","text":"Phone"},{"id":"phone_field","component":"TextField","label":"Phone","value":{"path":"/contact/phone"},"variant":"shortText"},{"id":"notes_label","component":"Text","text":"Notes"},{"id":"notes_field","component":"TextField","label":"Notes","value":{"path":"/contact/notes"},"variant":"longText"},{"id":"submit_button_label","component":"Text","text":"Submit"},{"id":"submit_button","component":"Button","child":"submit_button_label","action":{"name":"submitContactForm"}}]}}
{"updateDataModel": {"surfaceId": "contact_form_1", "path": "/contact", "value": {"firstName": "John", "lastName": "Doe", "email": "john.doe@example.com"}}}
{"createSurface":{"surfaceId":"contact_form_1","catalogId":"https://a2ui.dev/specification/0.9/standard_catalog.json"}}
{"updateComponents":{"surfaceId":"contact_form_1","components":[{"id":"root","component":"Card","child":"form_container"},{"id":"form_container","component":"Column","children":["header_row","name_row","email_group","phone_group","pref_group","divider_1","newsletter_checkbox","submit_button"],"justify":"start","align":"stretch"},{"id":"header_row","component":"Row","children":["header_icon","header_text"],"align":"center"},{"id":"header_icon","component":"Icon","name":"mail"},{"id":"header_text","component":"Text","text":"# Contact Us","variant":"h2"},{"id":"name_row","component":"Row","children":["first_name_group","last_name_group"],"justify":"spaceBetween"},{"id":"first_name_group","component":"Column","children":["first_name_label","first_name_field"],"weight":1},{"id":"first_name_label","component":"Text","text":"First Name","variant":"caption"},{"id":"first_name_field","component":"TextField","label":"First Name","value":{"path":"/contact/firstName"},"variant":"shortText"},{"id":"last_name_group","component":"Column","children":["last_name_label","last_name_field"],"weight":1},{"id":"last_name_label","component":"Text","text":"Last Name","variant":"caption"},{"id":"last_name_field","component":"TextField","label":"Last Name","value":{"path":"/contact/lastName"},"variant":"shortText"},{"id":"email_group","component":"Column","children":["email_label","email_field"]},{"id":"email_label","component":"Text","text":"Email Address","variant":"caption"},{"id":"email_field","component":"TextField","label":"Email","value":{"path":"/contact/email"},"variant":"shortText","checks":[{"call":"required","message":"Email is required."},{"call":"email","message":"Please enter a valid email address."}]},{"id":"phone_group","component":"Column","children":["phone_label","phone_field"]},{"id":"phone_label","component":"Text","text":"Phone Number","variant":"caption"},{"id":"phone_field","component":"TextField","label":"Phone","value":{"path":"/contact/phone"},"variant":"shortText","checks":[{"call":"regex","args":{"pattern":"^\\d{10}$"},"message":"Phone number must be 10 digits."}]},{"id":"pref_group","component":"Column","children":["pref_label","pref_picker"]},{"id":"pref_label","component":"Text","text":"Preferred Contact Method","variant":"caption"},{"id":"pref_picker","component":"ChoicePicker","variant":"mutuallyExclusive","options":[{"label":"Email","value":"email"},{"label":"Phone","value":"phone"},{"label":"SMS","value":"sms"}],"value":{"path":"/contact/preference"}},{"id":"divider_1","component":"Divider","axis":"horizontal"},{"id":"newsletter_checkbox","component":"CheckBox","label":"Subscribe to our newsletter","value":{"path":"/contact/subscribe"}},{"id":"submit_button_label","component":"Text","text":"Send Message"},{"id":"submit_button","component":"Button","child":"submit_button_label","primary":true,"action":{"name":"submitContactForm","context":{"formId":"contact_form_1","clientTime":{"call":"now","returnType":"string"},"isNewsletterSubscribed":{"path":"/contact/subscribe"}}}}]}}
{"updateDataModel":{"surfaceId":"contact_form_1","path":"/contact","value":{"firstName":"John","lastName":"Doe","email":"john.doe@example.com","phone":"1234567890","preference":["email"],"subscribe":true}}}
```

## Component Model
Expand All @@ -234,7 +234,7 @@ This structure is designed to be both flexible and strictly validated.

### The Component Catalog

The set of available UI components and their properties is defined in a **Component Catalog**. The standard catalog is defined in [`standard_catalog_definition.json`]. This allows for different clients to support different sets of components, including custom ones. The server must generate `updateComponents` messages that conform to the component catalog understood by the client.
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. The server must generate messages that conform to the catalog understood by the client.

### UI Composition: The Adjacency List Model

Expand Down Expand Up @@ -495,7 +495,7 @@ Buttons can also define `checks`. If any check fails, the button is automaticall

## Standard Component Catalog

The [`standard_catalog_definition.json`] provides the baseline set of components.
The [`standard_catalog.json`] provides the baseline set of components and functions.

| Component | Description |
| :---------------- | :------------------------------------------------------------------------------------- |
Expand Down Expand Up @@ -572,24 +572,25 @@ 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.

### `capabilities`
### Client Capabilities

This message is sent by the client upon connection to inform the server of its capabilities, including supported component catalogs and validation catalogs.
Client capabilities are sent by the client to inform the server of its capabilities, including supported catalogs (components and functions). In A2UI v0.9, these are sent as part of the **A2A metadata** envelope in every message, rather than as a first-class A2UI message. This ensures the server always has the client's latest capabilities without needing a separate handshake.

The `a2uiClientCapabilities` object in the metadata follows the [`a2ui_client_capabilities_schema.json`] schema.

**Properties:**

- `supportedCatalogIds` (array of strings, required): URIs of supported component catalogs.
- `supportedFunctionCatalogIds`: A list of URIs for the function catalogs supported by the client.
- `inlineCatalogs`: An array of inline component catalog definitions provided directly by the client (useful for custom or ad-hoc components).
- `inlineFunctionCatalogs`: An array of function catalog definitions provided directly by the client (useful for custom or ad-hoc functions).
- `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).

### `error`

This message is used to report a client-side error to the server.

[`standard_catalog_definition.json`]: ../json/standard_catalog_definition.json
[`standard_catalog.json`]: ../json/standard_catalog.json
[`common_types.json`]: ../json/common_types.json
[`server_to_client.json`]: ../json/server_to_client.json
[`client_to_server.json`]: ../json/client_to_server.json
[`a2ui_client_capabilities_schema.json`]: ../json/a2ui_client_capabilities_schema.json
[JSON Pointer]: https://datatracker.ietf.org/doc/html/rfc6901
[RFC 6901]: https://datatracker.ietf.org/doc/html/rfc6901
13 changes: 7 additions & 6 deletions specification/0.9/docs/evolution_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output
| **Data Model Update** | Array of Key-Value Pairs | Standard JSON Object |
| **Data Binding** | `dataBinding` / `literalString` | `path` / Native JSON types |
| **Button Context** | Array of Key-Value pairs | Standard JSON Object |
| **Catalog** | Separate component and function catalogs | Unified Catalog (`standard_catalog.json`) |
| **Auxiliary Rules** | N/A | `standard_catalog_rules.txt` |
| **Validation** | Basic Schema | Strict `ValidationFailed` feedback loop |
| **Interpolation** | N/A (Object wrappers only) | Native `${expression}` syntax |
Expand All @@ -36,10 +37,11 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output
**v0.9:**

- **Modularization**: The schema is strictly split into:
- `common_types.json`: Reusable primitives (IDs, paths, weights).
- `common_types.json`: Reusable primitives (IDs, paths, weights) and logic/expression types.
- `server_to_client.json`: The "envelope" defining the message types.
- `standard_catalog_definition.json`: The specific UI components.
- **Benefit**: This allows developers to swap out the `standard_catalog_definition.json` for a `custom_catalog.json` without touching the core protocol envelope.
- `standard_catalog.json`: The unified catalog of UI components and functions.
- **Benefit**: This allows developers to swap out the `standard_catalog.json` for a `custom_catalog.json` without touching the core protocol envelope.
- **Unification**: Components and functions are now part of the same catalog object, simplifying capability negotiation and inline definitions.

### 2.2. Strict Message Typing

Expand Down Expand Up @@ -78,7 +80,7 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output
- **Purpose**: `createSurface` signals the client to create a new surface and prepare for rendering.
- **Style Information Removed**: `createSurface` does **NOT** contain style information. Theming is now handled via the client styles, decoupling it from the message stream.
- **Root Rule**: The rule is: "There must be exactly one component with the ID `root`." The "root" attribute that `beginRendering` had has been removed. The client is expected to render as soon as it has a valid tree with a root component.
- **New Requirement**: `createSurface` now requires a **`catalogId`** (URI) to explicitly state which component set is being used.
- **New Requirement**: `createSurface` now requires a **`catalogId`** (URI) to explicitly state which unified catalog (components and functions) is being used.

**Example:**

Expand All @@ -102,7 +104,7 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output
{
"createSurface": {
"surfaceId": "user_profile_card",
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog_definition.json"
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog.json"
}
}
```
Expand Down Expand Up @@ -310,5 +312,4 @@ For developers migrating from earlier versions, here is a quick reference of pro
| **TextField** | `text` | `value` |
| **Many** | `usageHint` | `variant` |
| **Client Message** | `userAction` | `action` |
| **Client Message** | `clientUiCapabilities` | `capabilities` |
| **Common Type** | `childrenProperty` | `ChildList` |
Loading
Loading