From 093002aa1308d232991d1a8d27600cb9e89e03c7 Mon Sep 17 00:00:00 2001 From: wrenj Date: Wed, 18 Mar 2026 16:31:18 -0400 Subject: [PATCH 1/4] add actionResponse --- specification/v0_10/docs/a2ui_protocol.md | 35 +++++++++++++++- specification/v0_10/docs/evolution_guide.md | 6 +++ .../v0_10/json/client_to_server.json | 4 ++ .../v0_10/json/server_to_client.json | 41 ++++++++++++++++++- 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/specification/v0_10/docs/a2ui_protocol.md b/specification/v0_10/docs/a2ui_protocol.md index d8bcf2701..f6f2d2990 100644 --- a/specification/v0_10/docs/a2ui_protocol.md +++ b/specification/v0_10/docs/a2ui_protocol.md @@ -167,7 +167,7 @@ Validators determine which fields represent structural links by looking for thes ## 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. +The envelope defines several message types, and every message streamed by the server must be a JSON object containing exactly one of the following keys: `createSurface`, `updateComponents`, `updateDataModel`, `deleteSurface`, or `actionResponse`. The key indicates the type of message, and these are the messages that make up each message in the protocol stream. ### `createSurface` @@ -275,6 +275,33 @@ This message instructs the client to remove a surface and all its associated com } ``` +### `actionResponse` + +This message is sent by the server to respond to a client-initiated action that requested a response via `wantResponse: true`. + +**Properties:** + +- `actionId` (string, required): The unique ID of the action call this response belongs to. MUST match the `actionId` sent by the client. +- `actionResponse` (object, required): The payload containing the response. + - `value` (any): The return value of the action. Present on success. + - `error` (object): Error details if the action failed. + - `code` (string): Error code. + - `message` (string): Description of the error. + +Exactly one of `value` or `error` must be present. + +**Example:** + +```json +{ + "version": "v0.10", + "actionId": "req_abc123", + "actionResponse": { + "value": ["apple", "application", "approved"] + } +} +``` + ## Example Stream The following example demonstrates a complete interaction to render a Contact Form, expressed as a JSONL stream. @@ -343,7 +370,10 @@ Interactive components (like `Button`) use an `action` property to define what h #### 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`. +To send an event to the server, use the `event` property within the `action` object. It requires a `name` and supports an optional `context`, `wantResponse`, and `responsePath`. + +- `wantResponse` (boolean, optional): If true, the client expects an `actionResponse` from the server. Defaults to false. +- `responsePath` (string, optional): A JSON Pointer path in the local data model where the response `value` should be saved. ```json { @@ -813,6 +843,7 @@ This message is sent when the user interacts with a component that has an `actio - `sourceComponentId` (string, required): The ID of the component that triggered the action. - `timestamp` (string, required): An ISO 8601 timestamp. - `context` (object, required): A JSON object containing any context provided in the component's `action` property. +- `actionId` (string, optional): A unique ID for this action call, generated by the client if `wantResponse` is true. ### Capabilities & metadata diff --git a/specification/v0_10/docs/evolution_guide.md b/specification/v0_10/docs/evolution_guide.md index fe9471ce0..f30fb1928 100644 --- a/specification/v0_10/docs/evolution_guide.md +++ b/specification/v0_10/docs/evolution_guide.md @@ -6,6 +6,7 @@ This document serves as a comprehensive guide to the changes between A2UI versio Version 0.10 differs from 0.9 in the following ways: +- **Client-to-Server RPC**: Introduced `actionResponse` enabling synchronous responses to client-initiated actions. Added `actionId` for response correlation. - ## 2. Changes @@ -16,10 +17,12 @@ Version 0.10 differs from 0.9 in the following ways: ### 2.2. Server-to-Client Message List Schema +- Added `ActionResponseMessage` to allow the server to respond to a specific action call using an `actionId`. - ### 2.3. Client-to-Server Message List Schema +- Added `actionId` to the `action` message properties, which the client generates if a response is expected (`wantResponse: true`). - ### 2.4. Client Capabilities Schema @@ -40,10 +43,13 @@ Version 0.10 differs from 0.9 in the following ways: ### 2.8. Server-to-Client Messages +- Added `actionResponse` message structure to support synchronous responses with a `value` or `error`. - ### 2.9. Client-to-Server Events +- Updated `action` message to include `actionId`. +- Updated `Action` type in `common_types.json` to include `wantResponse` and `responsePath` on event triggers. - ## 3. Migration Guide diff --git a/specification/v0_10/json/client_to_server.json b/specification/v0_10/json/client_to_server.json index 82f8a9206..a969bec02 100644 --- a/specification/v0_10/json/client_to_server.json +++ b/specification/v0_10/json/client_to_server.json @@ -35,6 +35,10 @@ "type": "object", "description": "A JSON object containing the key-value pairs from the component's action.event.context, after resolving all data bindings.", "additionalProperties": true + }, + "actionId": { + "type": "string", + "description": "Unique ID for this action call. Only needed if wantResponse is true." } }, "required": [ diff --git a/specification/v0_10/json/server_to_client.json b/specification/v0_10/json/server_to_client.json index 650478427..f5122c973 100644 --- a/specification/v0_10/json/server_to_client.json +++ b/specification/v0_10/json/server_to_client.json @@ -9,7 +9,8 @@ { "$ref": "#/$defs/UpdateComponentsMessage" }, { "$ref": "#/$defs/UpdateDataModelMessage" }, { "$ref": "#/$defs/DeleteSurfaceMessage" }, - { "$ref": "#/$defs/CallFunctionMessage" } + { "$ref": "#/$defs/CallFunctionMessage" }, + { "$ref": "#/$defs/ActionResponseMessage" } ], "$defs": { "CreateSurfaceMessage": { @@ -166,6 +167,44 @@ }, "required": ["version", "callFunction", "functionCallId"], "additionalProperties": false + }, + "ActionResponseMessage": { + "type": "object", + "description": "A response to a client-initiated action.", + "properties": { + "version": { + "const": "v0.10" + }, + "actionId": { + "type": "string", + "description": "The ID of the action call this response belongs to." + }, + "actionResponse": { + "type": "object", + "properties": { + "value": { + "description": "The return value of the action.", + "type": [ "string", "number", "boolean", "array", "object", "null" ] + }, + "error": { + "type": "object", + "properties": { + "code": { "type": "string" }, + "message": { "type": "string" } + }, + "required": [ "code", "message" ], + "additionalProperties": false + } + }, + "oneOf": [ + { "required": [ "value" ] }, + { "required": [ "error" ] } + ], + "additionalProperties": false + } + }, + "required": [ "version", "actionResponse", "actionId" ], + "additionalProperties": false } } } From 6a1c41c0b2d0f338280d99b18a5d785e53353c31 Mon Sep 17 00:00:00 2001 From: wrenj Date: Wed, 18 Mar 2026 16:33:50 -0400 Subject: [PATCH 2/4] update --- specification/v0_10/docs/a2ui_protocol.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specification/v0_10/docs/a2ui_protocol.md b/specification/v0_10/docs/a2ui_protocol.md index f6f2d2990..301888c86 100644 --- a/specification/v0_10/docs/a2ui_protocol.md +++ b/specification/v0_10/docs/a2ui_protocol.md @@ -373,7 +373,6 @@ Interactive components (like `Button`) use an `action` property to define what h To send an event to the server, use the `event` property within the `action` object. It requires a `name` and supports an optional `context`, `wantResponse`, and `responsePath`. - `wantResponse` (boolean, optional): If true, the client expects an `actionResponse` from the server. Defaults to false. -- `responsePath` (string, optional): A JSON Pointer path in the local data model where the response `value` should be saved. ```json { From d778c13e33e0c71e1f893c5d9b38d969e4f3cad2 Mon Sep 17 00:00:00 2001 From: wrenj Date: Wed, 18 Mar 2026 17:37:37 -0400 Subject: [PATCH 3/4] add response path --- specification/v0_10/docs/a2ui_protocol.md | 1 + specification/v0_10/json/client_to_server.json | 1 + specification/v0_10/json/common_types.json | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/specification/v0_10/docs/a2ui_protocol.md b/specification/v0_10/docs/a2ui_protocol.md index 301888c86..f6f2d2990 100644 --- a/specification/v0_10/docs/a2ui_protocol.md +++ b/specification/v0_10/docs/a2ui_protocol.md @@ -373,6 +373,7 @@ Interactive components (like `Button`) use an `action` property to define what h To send an event to the server, use the `event` property within the `action` object. It requires a `name` and supports an optional `context`, `wantResponse`, and `responsePath`. - `wantResponse` (boolean, optional): If true, the client expects an `actionResponse` from the server. Defaults to false. +- `responsePath` (string, optional): A JSON Pointer path in the local data model where the response `value` should be saved. ```json { diff --git a/specification/v0_10/json/client_to_server.json b/specification/v0_10/json/client_to_server.json index a969bec02..e3e9a3250 100644 --- a/specification/v0_10/json/client_to_server.json +++ b/specification/v0_10/json/client_to_server.json @@ -40,6 +40,7 @@ "type": "string", "description": "Unique ID for this action call. Only needed if wantResponse is true." } + }, "required": [ "name", diff --git a/specification/v0_10/json/common_types.json b/specification/v0_10/json/common_types.json index 3d2e6679a..044b50622 100644 --- a/specification/v0_10/json/common_types.json +++ b/specification/v0_10/json/common_types.json @@ -311,6 +311,15 @@ "additionalProperties": { "$ref": "#/$defs/DynamicValue" } + }, + "wantResponse": { + "type": "boolean", + "description": "If true, the client expects an actionResponse from the server.", + "default": false + }, + "responsePath": { + "type": "string", + "description": "Optional JSON Pointer path where the client should save the response value in its local data model." } }, "required": ["name"], From 4cd197054659d36fb944f395d7ac27d6c6b6be56 Mon Sep 17 00:00:00 2001 From: wrenj Date: Thu, 19 Mar 2026 14:50:37 -0400 Subject: [PATCH 4/4] updates --- specification/v0_10/docs/a2ui_protocol.md | 22 +++++++++++++++++-- .../v0_10/json/client_to_server.json | 6 ++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/specification/v0_10/docs/a2ui_protocol.md b/specification/v0_10/docs/a2ui_protocol.md index f6f2d2990..3026e3230 100644 --- a/specification/v0_10/docs/a2ui_protocol.md +++ b/specification/v0_10/docs/a2ui_protocol.md @@ -277,7 +277,7 @@ This message instructs the client to remove a surface and all its associated com ### `actionResponse` -This message is sent by the server to respond to a client-initiated action that requested a response via `wantResponse: true`. +This message is sent by the server to respond to a client-initiated `action` that requested a response via `wantResponse: true`. **Properties:** @@ -292,10 +292,28 @@ Exactly one of `value` or `error` must be present. **Example:** +Client sends this to the server: ```json { "version": "v0.10", - "actionId": "req_abc123", + "action": { + "name": "get_typeahead_suggestions", + "surfaceId": "mysurface", + "sourceComponentId": "myinput", + "context": { + "prefix": "app" + }, + "wantResponse": true, + "actionId": "get_typeahead_suggestions_1" + } +} +``` + +Server responds with: +```json +{ + "version": "v0.10", + "actionId": "get_typeahead_suggestions_1", "actionResponse": { "value": ["apple", "application", "approved"] } diff --git a/specification/v0_10/json/client_to_server.json b/specification/v0_10/json/client_to_server.json index e3e9a3250..f0aa24b40 100644 --- a/specification/v0_10/json/client_to_server.json +++ b/specification/v0_10/json/client_to_server.json @@ -36,11 +36,15 @@ "description": "A JSON object containing the key-value pairs from the component's action.event.context, after resolving all data bindings.", "additionalProperties": true }, + "wantResponse": { + "type": "boolean", + "description": "If true, the client expects an actionResponse from the server.", + "default": false + }, "actionId": { "type": "string", "description": "Unique ID for this action call. Only needed if wantResponse is true." } - }, "required": [ "name",