Messages
A2UI agents and client renderers communicate by exchanging asynchronous JSON messages in both directions to manage UI surfaces and handle user interactions. These message types can be sent over a variety of transports, including Agent-to-Agent (A2A) and Model Context Protocol (MCP).
Alongside explicit A2UI messages, implementations can use metadata to include renderer context in requests sent for other purposes. For example, when a user sends a text prompt, the renderer can attach its supported catalogs or synchronized surface state to the outgoing request.
Agent-to-renderer messages
Agent-to-renderer messages construct surfaces, update component hierarchies and reactive data models, clean up surfaces, invoke client-side functions, and return results for agent-side function calls. Each wire message in either direction is a JSON object with a "version" field ("1.0" in v1.0, or "v0.9" / "v0.9.1" in v0.9.1) and a single message key.
createSurface
The createSurface message allocates a new UI surface identified by surfaceId. The surfaceId must be globally unique within the rendering context (the MessageProcessor instance on the renderer), which is typically a conversation. Creating a surface implicitly instantiates the reserved Surface container component with child: "root". In v1.0, createSurface can also include optional surface-level custom extensions under metadata.extensions (Extensions).
Properties
| Property | Type | Required | Description |
|---|---|---|---|
surfaceId | string | Yes | Unique identifier for the surface. |
catalogId | string | Optional (v1.0), Yes (v0.9.1) | Default catalog identifier for this surface (for example, travel:flights). In v1.0, individual components and function calls can specify their own catalogId when omitted here. |
sendDataModel | boolean | Optional | When true, the renderer attaches the full surface data model in transport metadata (a2uiRendererDataModel in v1.0 / a2uiClientDataModel in v0.9.1) on every message to the creating agent. |
components | array | Optional (v1.0) | Initial flat list of component definitions, allowing single-message surface creation. |
dataModel | object | Optional (v1.0) | Initial root data model JSON object for the surface. |
metadata | object | Optional (v1.0) | Surface-level extensions container with optional extensions (Extensions). |
Example
Creating a "flight_search" surface:
{ "version": "1.0", "createSurface": { "surfaceId": "flight_search", "catalogId": "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json", "sendDataModel": false, "components": [ { "id": "root", "component": "Column", "children": ["title", "flight_card"] }, { "id": "title", "component": "Text", "text": "Available Flights" }, { "id": "flight_card", "component": "Card", "child": "flight_info" }, { "id": "flight_info", "component": "Text", "text": {"@path": "/flights/0/summary"} } ], "dataModel": { "flights": [ {"summary": "LH458 · BER -> SFO · $680", "price": 680} ] } }}{ "version": "v0.9", "createSurface": { "surfaceId": "flight_search", "catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json", "sendDataModel": false }}updateComponents
The updateComponents message adds or replaces component definitions in an existing surface. Relationships between components are expressed by ID references in a flat adjacency list rather than nested JSON trees, and one component in the surface must have id: "root". In v1.0, individual component definitions in components can also carry optional component-level extensions via metadata.extensions (ComponentCommon).
Properties
| Property | Type | Required | Description |
|---|---|---|---|
surfaceId | string | Yes | Identifier of the surface to update. |
components | array | Yes | Non-empty flat array of component objects. Components whose id already exists in the surface replace the stored definition. |
Example
Populating a surface with a Column, header Text, and interactive Button:
{ "version": "1.0", "updateComponents": { "surfaceId": "flight_search", "components": [ { "id": "root", "component": "Column", "children": ["header", "btn_select_lh458"] }, { "id": "header", "component": "Text", "text": "Outbound Flights" }, { "id": "btn_select_label", "component": "Text", "text": "Select LH458 ($680)" }, { "id": "btn_select_lh458", "component": "Button", "child": "btn_select_label", "variant": "primary", "action": { "event": { "name": "select_flight", "userMessage": "Selected flight LH458", "context": { "flightId": "LH458", "price": {"@path": "/flights/0/price"} } } } } ] }}{ "version": "v0.9", "updateComponents": { "surfaceId": "flight_search", "components": [ { "id": "root", "component": "Column", "children": ["header", "btn_select_lh458"] }, { "id": "header", "component": "Text", "text": "Outbound Flights" }, { "id": "btn_select_label", "component": "Text", "text": "Select LH458 ($680)" }, { "id": "btn_select_lh458", "component": "Button", "child": "btn_select_label", "variant": "primary", "action": { "event": { "name": "select_flight", "context": { "flightId": "LH458", "price": {"path": "/flights/0/price"} } } } } ] }}updateDataModel
The updateDataModel message updates the surface data model at a targeted location using an RFC 6901 JSON Pointer, allowing the agent to refresh bound values without resending component definitions.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
surfaceId | string | Yes | Identifier of the target surface. |
path | string | Optional | RFC 6901 JSON Pointer indicating where to apply the update (for example, "/selectedFlight"). When omitted or set to "/", the update replaces the entire data model. |
value | any | Yes (v1.0), Optional (v0.9.1) | Value to store at path. |
Examples
Updating /selectedFlight:
{ "version": "1.0", "updateDataModel": { "surfaceId": "flight_search", "path": "/selectedFlight", "value": { "flightId": "LH458", "status": "confirmed", "passengers": 2 } }}Deleting /selectedFlight in v1.0 by setting "value": null:
{ "version": "1.0", "updateDataModel": { "surfaceId": "flight_search", "path": "/selectedFlight", "value": null }}Updating /selectedFlight:
{ "version": "v0.9", "updateDataModel": { "surfaceId": "flight_search", "path": "/selectedFlight", "value": { "flightId": "LH458", "status": "confirmed", "passengers": 2 } }}Deleting /selectedFlight in v0.9.1 by omitting value:
{ "version": "v0.9", "updateDataModel": { "surfaceId": "flight_search", "path": "/selectedFlight" }}deleteSurface
The deleteSurface message instructs the renderer to unmount the surface identified by surfaceId and release its component tree and data model state.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
surfaceId | string | Yes | Identifier of the surface to drop. |
Example
Deleting the "flight_search" surface:
{ "version": "1.0", "deleteSurface": { "surfaceId": "flight_search" }}{ "version": "v0.9", "deleteSurface": { "surfaceId": "flight_search" }}callRendererFunction (v1.0 only)
The callRendererFunction message is an agent-initiated remote procedure call (RPC) that directs the renderer to execute a catalog function registered on the client (for example, reading device timezone or screen dimensions). Only catalog functions declaring allowedCallers as "agentOnly" or "rendererOrAgent" may be called by the agent.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
functionCallId | string | Yes | Unique correlation identifier for this call, copied verbatim into rendererFunctionResponse. |
callFunction | object | Yes | FunctionCall object with required @call, required catalogId, and optional args. |
surfaceId | string | Optional | Surface ID whose data model provides the evaluation context. When omitted, the function executes in an isolated root context with {}. |
Example
Calling a client-side getDeviceTimezone function on the renderer:
{ "version": "1.0", "callRendererFunction": { "surfaceId": "flight_search", "functionCallId": "call_tz_101", "callFunction": { "@call": "getDeviceTimezone", "catalogId": "device:sensors", "args": {} } }}agentFunctionResponse (v1.0 only)
The agentFunctionResponse message returns the execution result or structured error for a preceding callAgentFunction message sent by the renderer.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
functionCallId | string | Yes | Correlation identifier matching the initiating callAgentFunction message. |
value | any | Conditional | Return value produced on success. Exactly one of value or error must be present. |
error | object | Conditional | Error object with required code (string) and message (string) fields if execution failed. Mutually exclusive with value. |
Example
Returning baggage allowance data for an agent function call:
{ "version": "1.0", "agentFunctionResponse": { "functionCallId": "call_baggage_202", "value": { "allowedBags": 2, "maxWeightKg": 23, "feePerExtraBag": 75 } }}Renderer-to-agent messages
Renderer-to-agent messages report user interactions, invoke remote functions on the agent, and return results from agent-initiated client function calls.
action
The action message notifies the agent that the user triggered an event action on an interactive component (such as clicking a Button configured with action.event). Before dispatching the message, the renderer resolves any data bindings inside action.event.context and action.event.userMessage against the local data model. In v1.0, action can also include optional renderer-side custom extensions under metadata.extensions (Extensions).
Properties
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Event name declared on the component’s action.event.name. |
surfaceId | string | Yes | Surface ID where the interaction originated. |
sourceComponentId | string | Yes | Component id that triggered the action. |
timestamp | string | Yes | ISO 8601 date-time string indicating when the event occurred. |
context | object | Yes | Resolved key-value dictionary from action.event.context with all data bindings evaluated to current values. |
userMessage | string | Optional (v1.0) | Human-readable string resolved from action.event.userMessage, suitable for adding to LLM conversation history. |
metadata | object | Optional (v1.0) | Action-level extensions container with optional extensions (Extensions). |
Example
Reporting a "select_flight" button action with resolved context:
{ "version": "1.0", "action": { "name": "select_flight", "surfaceId": "flight_search", "sourceComponentId": "btn_select_lh458", "timestamp": "2026-11-02T10:15:30.000Z", "userMessage": "Selected flight LH458", "context": { "flightId": "LH458", "price": 680 } }}{ "version": "v0.9", "action": { "name": "select_flight", "surfaceId": "flight_search", "sourceComponentId": "btn_select_lh458", "timestamp": "2026-11-02T10:15:30.000Z", "context": { "flightId": "LH458", "price": 680 } }}callAgentFunction (v1.0 only)
The callAgentFunction message is a renderer-initiated RPC requesting that the agent execute a function remotely (for example, checking live baggage rules or verifying a backend identifier).
Properties
| Property | Type | Required | Description |
|---|---|---|---|
surfaceId | string | Yes | Surface ID where the call originated. |
functionCallId | string | Yes | Unique correlation identifier for this call, copied verbatim into agentFunctionResponse. |
callFunction | object | Yes | FunctionCall object with required @call, optional catalogId, and optional args. |
Example
Invoking getBaggageAllowance on the agent from the renderer:
{ "version": "1.0", "callAgentFunction": { "surfaceId": "flight_search", "functionCallId": "call_baggage_202", "callFunction": { "@call": "getBaggageAllowance", "catalogId": "travel:flights", "args": { "flightId": "LH458", "cabin": "economy" } } }}rendererFunctionResponse (v1.0 only)
The rendererFunctionResponse message delivers the renderer’s return value or structured execution error for a preceding callRendererFunction message.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
functionCallId | string | Yes | Correlation identifier matching the initiating callRendererFunction message. |
value | any | Conditional | Return value produced on success. Exactly one of value or error must be present. |
error | object | Conditional | Error object with required code (string) and message (string) fields if execution failed. Mutually exclusive with value. |
Example
Returning the device timezone for a preceding callRendererFunction call:
{ "version": "1.0", "rendererFunctionResponse": { "functionCallId": "call_tz_101", "value": { "timeZone": "Europe/Berlin", "utcOffsetMinutes": 60 } }}Metadata
Transport metadata lets the renderer attach A2UI context to outgoing requests sent for other purposes (such as user text prompts in A2A or request metadata in MCP), flowing from the renderer to the agent.
| Metadata key (v1.0) | Metadata key (v0.9.1) | Purpose |
|---|---|---|
a2uiRendererCapabilities | a2uiClientCapabilities | Advertises supported protocol versions, supportedCatalogIds, and optional inlineCatalogs. |
a2uiRendererDataModel | a2uiClientDataModel | Sends full local data models for active surfaces created with sendDataModel: true. |
Renderer capabilities (a2uiRendererCapabilities in v1.0 / a2uiClientCapabilities in v0.9.1) are an optional mechanism that loosely coupled systems can use to negotiate which protocol versions and catalogs can be used when they are not known in advance. Systems where the agent and client are owned by the same party may not need capability negotiation if the protocol version and catalogs are agreed in advance. Agents can also advertise their static catalog support ahead of time via agent_capabilities.json (v1.0) or server_capabilities.json (v0.9.1), such as in an A2A Agent Card.
When any active surface was created with sendDataModel: true, the renderer attaches a2uiRendererDataModel (or a2uiClientDataModel in v0.9.1) on outgoing messages to that agent so local input state stays synchronized without embedding full data models inside action payloads.
Example
Attaching capabilities and synchronized surface state to an outgoing transport request:
{ "metadata": { "a2uiRendererCapabilities": { "1.0": { "supportedCatalogIds": [ "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json", "travel:flights" ] } }, "a2uiRendererDataModel": { "version": "1.0", "surfaces": { "flight_search": { "selectedFlight": "LH458", "passengers": 2 } } } }}{ "metadata": { "a2uiClientCapabilities": { "v0.9": { "supportedCatalogIds": [ "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json", "travel:flights" ] } }, "a2uiClientDataModel": { "version": "v0.9", "surfaces": { "flight_search": { "selectedFlight": "LH458", "passengers": 2 } } } }}