| name | a2ui-rendering |
| description | Use when an agent renders rich UI back to a client surface (cards, dashboards, forms, modals) using the A2UI v0.8.0 declarative protocol. Required whenever the response should display structured components rather than plain text, or whenever the validate_and_emit_a2ui tool is in scope.
|
| license | Apache-2.0 |
A2UI Rendering
A2UI is a declarative JSON protocol for delivering rich UI from agents
to client surfaces. UI is composed as a flat list of components where
layout containers reference children by ID. The protocol enforces typed
value wrappers and a fixed catalog of 18 primitives.
When to Compose A2UI
Compose A2UI only in response to a user message that needs rich
visual output. Do not generate A2UI on session creation or
proactively. Plain text remains the default for narrative responses.
Workflow
A2UI Render Progress:
- [ ] Decide what information to present
- [ ] Choose primitives (Text, Card, Column/Row, etc.)
- [ ] Compose the surfaceUpdate JSON with unique component IDs
- [ ] Call validate_and_emit_a2ui with the surfaceUpdate JSON
- [ ] If validation fails, fix the violations and re-validate
- [ ] Compose the beginRendering JSON pointing to the root component
- [ ] Call validate_and_emit_a2ui with the beginRendering JSON
- [ ] Wrap both validated payloads in ```a2ui markdown fences
validate_and_emit_a2ui MUST be called twice per surface: once
for surfaceUpdate and once for beginRendering. Without
beginRendering, the frontend will not render the surface.
Message Structure
surfaceUpdate (defines components)
{
"surfaceUpdate": {
"surfaceId": "my-surface",
"components": [
{"id": "unique-id", "component": {"TypeName": { ...props }}}
]
}
}
surfaceId: unique identifier for this UI surface.
components: flat array of component definitions (NOT nested trees).
- Each component has
id (unique string) and component
(object with exactly one key = the type name).
beginRendering (tells the frontend which component is root)
{
"beginRendering": {
"surfaceId": "my-surface",
"root": "root-component-id"
}
}
surfaceId: must match the surfaceUpdate's surfaceId.
root: the id of the outermost component (usually a Card).
Typed Value Wrappers
CRITICAL: Never use raw JSON primitives. All values MUST be wrapped.
| Type | Wrapper | Example |
|---|
| String | {"literalString": "value"} | "text": {"literalString": "Hello"} |
| Number | {"literalNumber": 42.0} | "value": {"literalNumber": 3.14} |
| Boolean | {"literalBoolean": true} | "autoplay": {"literalBoolean": true} |
| Binding | {"path": "some.data.path"} | "text": {"path": "user.name"} |
Raw "value", raw 42, or raw true as property values will be
rejected by validate_and_emit_a2ui.
Container Children
Layout containers reference children by ID:
- Multiple children:
"children": {"explicitList": ["child-id-1", "child-id-2"]} (NEVER raw arrays)
- Single child:
"child": "child-id" (used by Card, Button)
Component ID Rules
- IDs MUST be unique within a
surfaceUpdate.
- Use descriptive names:
"title-heading", "main-card", "details-column".
- All ID references (
child, children.explicitList,
entryPointChild, contentChild, tabItems[].child) MUST
resolve to IDs in the same components array.
Component Catalog
For the full catalog of 18 primitives, with required and optional
props plus per-type notes, see components.md.
Examples
For three complete surfaceUpdate + beginRendering payloads
(simple info card, data list card, dashboard with action button), see
examples.md.