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
67 changes: 40 additions & 27 deletions specification/v0_9/docs/a2ui_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ The [`common_types.json`] schema defines reusable primitives used throughout the
- **`DynamicString` / `DynamicNumber` / `DynamicBoolean` / `DynamicStringList`**: The core of the data binding system. Any property that can be bound to data is defined as a `Dynamic*` type. It accepts either a literal value, a `path` string ([JSON Pointer]), or a `FunctionCall` (function call).
- **`ChildList`**: Defines how containers hold children. It supports:

- `array`: A static array of string component IDs.
- `array`: A static array of `ComponentId` component references.
- `object`: A template for generating children from a data binding list (requires a template `componentId` and a data binding `path`).

- **`id`**: The unique identifier for a component. Defined here so that all IDs are consistent and can be used for data binding.
- **`ComponentId`**: A reference to the unique ID of another component within the same surface.

### Server to Client Message Structure: The Envelope

Expand All @@ -103,6 +103,19 @@ 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

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`.
* 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.
* 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

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.
Expand Down Expand Up @@ -228,7 +241,7 @@ A2UI's component model is designed for flexibility, separating the protocol's st

Each object in the `components` array of a `updateComponents` message defines a single UI component. It has the following structure:

- `id` (string, required): A unique string that identifies this specific component instance. This is used for parent-child references.
- `id` (`ComponentId`, required): A unique string that identifies this specific component instance. This is used for parent-child references.
- `component` (string, required): Specifies the component's type (e.g., `"Text"`).
- **Component Properties**: Other properties relevant to the specific component type (e.g., `text`, `url`, `children`) are included directly in the component object.

Expand Down Expand Up @@ -547,26 +560,26 @@ The [`standard_catalog.json`] provides the baseline set of components and functi

### Components

| Component | Description |
| :---------------- | :------------------------------------------------------------------------------------- |
| **Text** | Displays text. Supports simple Markdown. |
| **Image** | Displays an image from a URL. |
| **Icon** | Displays a system-provided icon from a predefined list. |
| **Video** | Displays a video from a URL. |
| **AudioPlayer** | A player for audio content from a URL. |
| **Row** | A horizontal layout container. |
| **Column** | A vertical layout container. |
| **List** | A scrollable list of components. |
| **Card** | A container with card-like styling. |
| **Tabs** | A set of tabs, each with a title and child component. |
| **Divider** | A horizontal or vertical dividing line. |
| **Modal** | A dialog that appears over the main content triggered by a button in the main content. |
| Component | Description |
| :---------------- | :------------------------------------------------------------------------------------------ |
| **Text** | Displays text. Supports simple Markdown. |
| **Image** | Displays an image from a URL. |
| **Icon** | Displays a system-provided icon from a predefined list. |
| **Video** | Displays a video from a URL. |
| **AudioPlayer** | A player for audio content from a URL. |
| **Row** | A horizontal layout container. |
| **Column** | A vertical layout container. |
| **List** | A scrollable list of components. |
| **Card** | A container with card-like styling. |
| **Tabs** | A set of tabs, each with a title and child component. |
| **Divider** | A horizontal or vertical dividing line. |
| **Modal** | A dialog that appears over the main content triggered by a button in the main content. |
| **Button** | A clickable button that dispatches an action. Supports 'primary' and 'borderless' variants. |
| **CheckBox** | A checkbox with a label and a boolean value. |
| **TextField** | A field for user text input. |
| **DateTimeInput** | An input for date and/or time. |
| **ChoicePicker** | A component for selecting one or more options. |
| **Slider** | A slider for selecting a numeric value within a range. |
| **CheckBox** | A checkbox with a label and a boolean value. |
| **TextField** | A field for user text input. |
| **DateTimeInput** | An input for date and/or time. |
| **ChoicePicker** | A component for selecting one or more options. |
| **Slider** | A slider for selecting a numeric value within a range. |

### Functions

Expand All @@ -583,11 +596,11 @@ The [`standard_catalog.json`] provides the baseline set of components and functi

The standard catalog defines the following theme properties that can be set in the `createSurface` message:

| Property | Type | Description |
| :----------------- | :----- | :-------------------------------------------------------------------------------------------------------- |
| **primaryColor** | String | The primary brand color used for highlights throughout the UI (e.g., primary buttons, active borders). The renderer may generate variants, such as lighter shades, as needed. Format: Hexadecimal code (e.g., '#00BFFF'). |
| **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").|
| Property | Type | Description |
| :------------------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **primaryColor** | String | The primary brand color used for highlights throughout the UI (e.g., primary buttons, active borders). The renderer may generate variants, such as lighter shades, as needed. Format: Hexadecimal code (e.g., '#00BFFF'). |
| **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

Expand Down
28 changes: 14 additions & 14 deletions specification/v0_9/docs/evolution_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output

### Summary Table

| Feature | v0.8.1 | v0.9 |
| :----------------------- | :--------------------------------------- | :--------------------------------------------------- |
| **Philosophy** | Structured Output / Function Calling | Prompt-First / In-Context Schema |
| **Message Types** | `beginRendering`, `surfaceUpdate`, ... | `createSurface`, `updateComponents`, ... |
| **Surface Creation** | Explicit `beginRendering` | Explicit `createSurface` |
| **Component Type** | Key-based wrapper (`{"Text": ...}`) | Property-based discriminator (`"component": "Text"`) |
| **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 |
| **Button Variant** | Boolean (`primary: true`) | Enum (`variant: "primary"`) |
| **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 |
| Feature | v0.8.1 | v0.9 |
| :----------------------- | :--------------------------------------- | :------------------------------------------------------- |
| **Philosophy** | Structured Output / Function Calling | Prompt-First / In-Context Schema |
| **Message Types** | `beginRendering`, `surfaceUpdate`, ... | `createSurface`, `updateComponents`, ... |
| **Surface Creation** | Explicit `beginRendering` | Explicit `createSurface` |
| **Component Type** | Key-based wrapper (`{"Text": ...}`) | Property-based discriminator (`"component": "Text"`) |
| **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 |
| **Button Variant** | Boolean (`primary: true`) | Enum (`variant: "primary"`) |
| **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 |
| **Data Synchronization** | Implicit | Explicit Client->Server data syncing (`attachDataModel`) |

## 2. Architectural & Schema Changes
Expand Down Expand Up @@ -80,7 +80,7 @@ Version 0.9 represents a fundamental philosophical shift from "Structured Output
- **Replacement**: `beginRendering` is **REPLACED** by `createSurface`.
- **Purpose**: `createSurface` signals the client to create a new surface and prepare for rendering.
- **Theme Information**: `createSurface` includes a `theme` property to specify theme parameters (like `primaryColor`). This replaces the `styles` property in v0.8.
- **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.
- **Root Rule**: The rule is: "There must be exactly one component with the `ComponentId` '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 unified catalog (components and functions) is being used.

**Example:**
Expand Down
10 changes: 5 additions & 5 deletions specification/v0_9/json/common_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"title": "A2UI Common Types",
"description": "Common type definitions used across A2UI schemas.",
"$defs": {
"id": {
"ComponentId": {
"type": "string",
"description": "The unique identifier for this component."
"description": "The unique identifier for a component, used for both definitions and references within the same surface."
},
"ComponentCommon": {
"type": "object",
"properties": {
"id": {
"$ref": "#/$defs/id"
"$ref": "#/$defs/ComponentId"
}
},
"required": ["id"]
Expand All @@ -22,7 +22,7 @@
{
"type": "array",
"items": {
"type": "string"
"$ref": "#/$defs/ComponentId"
},
"description": "A static list of child component IDs."
},
Expand All @@ -31,7 +31,7 @@
"description": "A template for generating a dynamic list of children from a data model list. The `componentId` is the component to use as a template.",
"properties": {
"componentId": {
"$ref": "#/$defs/id"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this PR remove the id type, since it's no longer used? Theid was meant to serve a similar purpose, with perhaps a too-generic name.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes! Ummm sorry I was vibecoding too freely and missed that there was an ID type already defined right above my new one.

"$ref": "#/$defs/ComponentId"
},
"path": {
"type": "string",
Expand Down
10 changes: 5 additions & 5 deletions specification/v0_9/json/standard_catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@
"properties": {
"component": { "const": "Card" },
"child": {
"type": "string",
"$ref": "common_types.json#/$defs/ComponentId",
"description": "The ID of the single child component to be rendered inside the card. To display multiple elements, you MUST wrap them in a layout component (like Column or Row) and pass that container's ID here. Do NOT pass multiple IDs or a non-existent ID. Do NOT define the child component inline."
}
},
Expand Down Expand Up @@ -343,7 +343,7 @@
"$ref": "common_types.json#/$defs/DynamicString"
},
"child": {
"type": "string",
"$ref": "common_types.json#/$defs/ComponentId",
"description": "The ID of the child component. Do NOT define the component inline."
}
},
Expand All @@ -367,11 +367,11 @@
"properties": {
"component": { "const": "Modal" },
"trigger": {
"type": "string",
"$ref": "common_types.json#/$defs/ComponentId",
"description": "The ID of the component that opens the modal when interacted with (e.g., a button). Do NOT define the component inline."
},
"content": {
"type": "string",
"$ref": "common_types.json#/$defs/ComponentId",
"description": "The ID of the component to be displayed inside the modal. Do NOT define the component inline."
}
},
Expand Down Expand Up @@ -412,7 +412,7 @@
"properties": {
"component": { "const": "Button" },
"child": {
"type": "string",
"$ref": "common_types.json#/$defs/ComponentId",
"description": "The ID of the child component. Use a 'Text' component for a labeled button. Only use an 'Icon' if the requirements explicitly ask for an icon-only button. Do NOT define the child component inline."
},
"variant": {
Expand Down
Loading