Learning outcome
Read A2UI messages as a component graph and a separate data model.
A surface is an independently identified UI region. Its component tree describes structure; its data model holds values. Components refer to child IDs instead of embedding arbitrary executable widgets. This separation lets the renderer update a checkbox value without replacing the surrounding conversation or asking Gemini for each tap.
Illustrative batch matching the pinned wire format
[
{"version":"v0.9","createSurface":{
"surfaceId":"lesson-1",
"catalogId":"https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json",
"sendDataModel":true
}},
{"version":"v0.9","updateDataModel":{
"surfaceId":"lesson-1","path":"/","value":{"ready0":false}
}},
{"version":"v0.9","updateComponents":{
"surfaceId":"lesson-1","components":[
{"id":"root","component":"Card","child":"items"},
{"id":"items","component":"Column","children":["heading","pack"]},
{"id":"heading","component":"Text","text":"Before you go","variant":"h4"},
{"id":"pack","component":"CheckBox","label":"Pack a charger","value":{"path":"/ready0"}}
]
}}
]
Follow root → items → heading and pack. The CheckBox binds to /ready0, which initially resolves to false. Its component ID pack is identity in the tree; /ready0 is identity in the data model. Confusing them causes shared state or missing values. The surface ID isolates these names from other responses.
A complete message batch becomes an active native surface.
The server returns text plus a messages array in one HTTP response. CommunityViewModel parses each message through the official parser and processor, then Compose reads activeSurfaces. Sequential message processing is not network token streaming. This app does not implement SSE, progressive transport or an agent repair loop.
Version precision
The current Android guide describes support for specification 0.9.1. The pinned sample and published alpha serializer use version: v0.9 and the v0_9 basic catalog URL in their envelopes. Keep the exact tested values; do not rewrite message version strings from a documentation heading. Recheck the protocol and dependency contract when upgrading.
Open Inspect after a real request. Find createSurface, the initial updateDataModel and the root in updateComponents. Compare your output with the conceptual batch above: the shape should match even when component counts and labels differ. DeleteSurface is used when New conversation clears existing surfaces.
Practice and checkpoint
Draw the four-node graph and predict the result of replacing pack.value.path with /missing. Then explain the difference between an absent bound value and a missing child ID. Verify that the baseline server initializes accepted checkbox paths and rejects missing child references.
Source and next steps
- Pinned implementation — The exact app and server revision used by this lesson.
Back to roadmap · Practice this unit in the codelab