You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/a2ui_protocol.md
+52-40Lines changed: 52 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ The A2UI (Agent to UI) protocol should be a system where an LLM can stream a pla
10
10
11
11
### Requirement: The protocol must be easily generated by a Transformer Large Language Model (LLM)
12
12
13
-
This is the most critical driver. "LLM-friendliness" is explicitly mentioned. This requirement directly leads to several design choices:
13
+
This is the most critical driver. This requirement directly leads to several design choices:
14
14
15
15
Declarative, Simple Structure: The protocol should use a straightforward, declarative format ("this is a column with these children") rather than an imperative one ("now, add a column; then, append a text widget to it"). LLMs excel at generating structured, declarative data.
16
16
@@ -95,14 +95,13 @@ The A2UI protocol is composed of a server-to-client stream describing UI and ind
95
95
1.**Server Stream:** The server begins sending the JSONL stream over an SSE connection.
96
96
2.**Client-Side Buffering:** The client receives messages and buffers them:
97
97
98
-
-`updateSurface`: Component definitions are stored in a `Map<String, Component>`, organized by `surfaceId`. If a surface doesn't exist, it is created.
98
+
-`surfaceUpdate`: Component definitions are stored in a `Map<String, Component>`, organized by `surfaceId`. If a surface doesn't exist, it is created.
99
99
-`dataModelUpdate`: The client's internal JSON data model is built or updated.
100
100
101
101
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.
102
102
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.
103
103
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.
104
-
105
-
6.**Dynamic Updates:** The server processes the `userAction`. If the UI needs to change in response, the server sends new `updateSurface` 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.
104
+
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.
106
105
107
106
```mermaid
108
107
sequenceDiagram
@@ -112,8 +111,8 @@ sequenceDiagram
112
111
Server->>+Client: SSE Connection (JSONL Stream)
113
112
Client->>Client: 1. Parse JSONL message
114
113
loop Until 'beginRendering'
115
-
Client->>Client: 2a. Process surfaceUpdate (store components in map for surfaceId)
116
-
Client->>Client: 2b. Process dataModelUpdate (update data model)
114
+
Client->>Client: 2a. Process surfaceUpdate
115
+
Client->>Client: 2b. Process dataModelUpdate
117
116
end
118
117
Client->>Client: 3. Process beginRendering (rootId: 'root', isReady: true)
119
118
Note right of Client: 4. Triggers UI build for a surface
@@ -140,15 +139,15 @@ sequenceDiagram
140
139
The following is a complete, minimal example of a JSONL stream that renders a user profile card.
{"updateSurface": {"components": [{"id": "bio_text", "component": {"Text": {"text": {"literalString": "Building beautiful apps from a single codebase."}}}}]}}
{"surfaceUpdate": {"components": [{"id": "bio_text", "component": {"Text": {"text": {"literalString": "Building beautiful apps from a single codebase."}}}}]}}
152
151
{"dataModelUpdate": {"contents": {}}}
153
152
{"beginRendering": {"root": "root"}}
154
153
```
@@ -159,9 +158,9 @@ A2UI's component model is designed for flexibility, separating the protocol from
159
158
160
159
### 2.1. The Catalog: Defining Components
161
160
162
-
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 `updateSurface` 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.
161
+
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.
163
162
164
-
### 2.2. The `updateSurface` Message
163
+
### 2.2. The `surfaceUpdate` Message
165
164
166
165
This message is the primary way UI structure is defined. It contains a `surfaceId` and a `components` array.
167
166
@@ -430,30 +429,40 @@ This message provides a feedback mechanism for the server. It is sent when the c
@@ -462,8 +471,11 @@ This message provides a feedback mechanism for the server. It is sent when the c
462
471
463
472
```json
464
473
{
465
-
"form": {
466
-
"textField": "User input text"
474
+
"dataModelUpdate": {
475
+
"surfaceId": "main_content_area",
476
+
"form": {
477
+
"textField": "User input text"
478
+
}
467
479
}
468
480
}
469
481
```
@@ -487,7 +499,7 @@ This message provides a feedback mechanism for the server. It is sent when the c
487
499
}
488
500
```
489
501
490
-
6. **Server Response:** The server processes this event. If the UI needs to change as a result, the server sends new `updateSurface` or `dataModelUpdate` messages over the **separate SSE stream**.
502
+
6. **Server Response:** The server processes this event. If the UI needs to change as a result, the server sends new `surfaceUpdate` or `dataModelUpdate` messages over the **separate SSE stream**.
Copy file name to clipboardExpand all lines: docs/proposals/v0_8.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -91,7 +91,7 @@ We will update the standard catalog in the following ways:
91
91
92
92
The schema adapter is an agent-side utility that can accept a custom widget catalog and convert it to a schema which allows the LLM to generate `surfaceUpdate` messages for a particular catalog reliably.
93
93
94
-
The most simple adapter, which will work for Gemini and other common LLMs, will simply take the “components” from a “Catalog description object” and paste it into `updateSurface.components.componentProperties` and takes the “styles” and pastes them into `beginRendering.styles`. This creates a new schema which includes the detailed widget catalog, and can be passed to the LLM. This schema should be almost identical in structure to a v0.7 A2UI schema. This schema is a strict subset of the more generic v0.8 “Server-to-Client Protocol Schema” and thus messages generated this way do formally conform to the protocol spec.
94
+
The most simple adapter, which will work for Gemini and other common LLMs, will simply take the “components” from a “Catalog description object” and paste it into `surfaceUpdate.components.componentProperties` and takes the “styles” and pastes them into `beginRendering.styles`. This creates a new schema which includes the detailed widget catalog, and can be passed to the LLM. This schema should be almost identical in structure to a v0.7 A2UI schema. This schema is a strict subset of the more generic v0.8 “Server-to-Client Protocol Schema” and thus messages generated this way do formally conform to the protocol spec.
95
95
96
96
## Detailed design
97
97
@@ -300,7 +300,7 @@ To simplify the generation of UIs, especially for LLMs, we propose a shorthand f
300
300
Currently, to display a dynamic value that has a default, the server must send two separate messages:
301
301
302
302
1. A `dataModelUpdate` message to set the initial value in the data model.
303
-
2. An `updateSurface` message with a component that has a property bound to that data model path.
303
+
2. An `surfaceUpdate` message with a component that has a property bound to that data model path.
304
304
305
305
The proposed shorthand combines these two steps. When a component property that accepts a `BoundValue` (e.g., `text`, `value`) is defined with _both_ a `path` and a `literal*` value (e.g., `literalString`), it should be interpreted as follows:
306
306
@@ -313,14 +313,14 @@ Instead of sending two messages:
0 commit comments