Evolution Guide: v0.8 → v0.9¶
Living Document
This guide is automatically included from specification/0.9/docs/evolution_guide.md. Any updates will automatically appear here.
Related Documentation: - A2UI Protocol v0.8 (Stable - what you're migrating from) - A2UI Protocol v0.9 (Draft - what you're migrating to)
A2UI Protocol Evolution Guide: v0.8.1 to v0.9¶
This document serves as a comprehensive guide to the changes between A2UI version 0.8 and version 0.9. It details the shifts in philosophy, architecture, and implementation, providing a reference for stakeholders and developers migrating between versions.
1. Executive Summary¶
Version 0.9 represents a fundamental philosophical shift from "Structured Output First" to "Prompt First."
- v0.8.1 was designed to be generated by an LLM using Structured Output above all else, optimized for LLMs that support strict JSON mode or function calling (which is also a form of Structured Output). It relied on deep nesting and specific wrapper structures that were definable in the limited schema features but often confusing for an LLM to generate.
- v0.9 is designed to be embedded directly in an LLM's system prompt. The schema is refactored to be more human-readable and "token-efficient" for the model to understand. It prioritizes patterns that LLMs naturally excel at (like standard JSON objects for maps) over strict structured output-friendly structures (like arrays of key-value pairs).
Summary Table¶
| Feature | v0.8.1 | v0.9 |
|---|---|---|
| Philosophy | Structured Output / Function Calling | Prompt-First / In-Context Schema |
| Message Types | beginRendering, surfaceUpdate, ... |
createSurface, updateComponents, ... |
| Surface Creation | Explicit beginRendering |
Explicit createSurface |
| Component Type | Key-based wrapper ({"Text": ...}) |
Property-based discriminator ("component": "Text") |
| Data Model Update | Array of Key-Value Pairs | Standard JSON Object |
| Data Binding | dataBinding / literalString |
path / Native JSON types |
| Button Context | Array of Key-Value pairs | Standard JSON Object |
| Auxiliary Rules | N/A | standard_catalog_rules.txt |
| Validation | Basic Schema | Strict ValidationFailed feedback loop |
2. Architectural & Schema Changes¶
2.1. Modular Schema Architecture¶
v0.8.1:
- Monolithic tendencies.
server_to_client.jsonoften contained deep definitions or relied on complexoneOfstructures that were hard to decompose. standard_catalog_definition.jsonexisted but was often implicitly coupled.
v0.9:
- Modularization: The schema is strictly split into:
common_types.json: Reusable primitives (IDs, paths, weights).server_to_client.json: The "envelope" defining the message types.standard_catalog_definition.json: The specific UI components.- Benefit: This allows developers to swap out the
standard_catalog_definition.jsonfor acustom_catalog.jsonwithout touching the core protocol envelope.
2.2. Strict Message Typing¶
v0.8.1:
- Messages were objects where properties like
surfaceUpdatewere optional keys. - Validation often relied on "minProperties: 1" constraints.
v0.9:
- Uses a top-level
oneOfconstraint inserver_to_client.json. - Reason: This is a more natural way to express the schema to an LLM, and easier for the LLM to reason about. It's also a more natural form for the developer to read.
2.3. Auxiliary Rules File¶
v0.9:
- New Artifact:
standard_catalog_rules.txt. - Purpose: A plain-text prompt fragment containing rules for using the catalog schema (e.g., "MUST provide 'action' for Button").
- Usage: Designed to be included in the system prompt alongside the catalog schema.
- Reason: Some constraints (like conditional requirements or specific property combinations) are difficult or verbose to express in JSON Schema but easy to express in natural language rules for an LLM, and it can be packaged with the catalog schema for ease of customizing the prompt for a particular catalog.
3. Protocol Lifecycle Changes¶
3.1. beginRendering Replaced by createSurface¶
v0.8.1 (beginRendering):
- Explicit Signal: The server sent a
beginRenderingmessage to tell the client "I am done sending the initial batch of components, you can draw now." - Root Definition: The root component ID was defined in this message.
- Style Information: The message included style information for the surface.
v0.9 (createSurface):
- Replacement:
beginRenderingis REPLACED bycreateSurface. - Purpose:
createSurfacesignals the client to create a new surface and prepare for rendering. - Style Information Removed:
createSurfacedoes NOT contain style information. Theming is now handled via the client styles, decoupling it from the message stream. - Root Rule: The rule is: "There must be exactly one component with the ID
root." The "root" attribute thatbeginRenderinghad has been removed. The client is expected to render as soon as it has a valid tree with a root component. - New Requirement:
createSurfacenow requires acatalogId(URI) to explicitly state which component set is being used.
Example:
v0.8.1 (beginRendering):
{
"beginRendering": {
"surfaceId": "user_profile_card",
"root": "root",
"styles": {
"primaryColor": "#007bff",
}
}
}
v0.9 (createSurface):
{
"createSurface": {
"surfaceId": "user_profile_card",
"catalogId": "https://a2ui.dev/specification/0.9/standard_catalog_definition.json"
}
}
4. Message Structure Comparison¶
4.1. Component Updates¶
v0.8.1 (surfaceUpdate):
- Components were wrapped in an object where the key was the component type.
- Structure:
{ "id": "...", "component": { "Text": { "text": "..." } } }
v0.9 (updateComponents):
- Renamed:
surfaceUpdate->updateComponents. - Refactored: Components use a flattened structure with a const discriminator property
component. - Structure:
{ "id": "...", "component": "Text", "text": "..." } - Reason: This "flat" structure with a discriminator field (
component: "Text") is much easier for LLMs to generate consistently than a dynamic key ("Text": {...}). It also simplifies polymorphism in many JSON parsers.
Specifying an unknown surfaceId will cause an error. It is recommended that clients implement a namespacing scheme internally to prevent separate agents from creating surfaces with the same ID, and to prevent agents from modifying surfaces created by other agents.
Side-by-Side Example¶
v0.8.1:
{
"surfaceUpdate": {
"surfaceId": "main",
"components": [
{
"id": "title",
"component": {
"Text": { "text": { "literalString": "Hello" } }
}
}
]
}
}
v0.9:
{
"updateComponents": {
"surfaceId": "main",
"components": [
{
"id": "root",
"component": "Column",
"children": ["title"]
},
{
"id": "title",
"component": "Text",
"text": "Hello"
}
]
}
}
4.2. Data Model Updates¶
v0.8.1 (dataModelUpdate):
- Adjacency List: The
contentsproperty was an array of key-value pair objects. - Typed Values: Each entry required explicit typing like
valueString,valueNumber,valueBoolean. - Structure:
[{ "key": "name", "valueString": "Alice" }]
v0.9 (updateDataModel):
- Renamed:
dataModelUpdate->updateDataModel. - Standard JSON: The
valueproperty is now a standard JSON object. - Op: The
opproperty is added to allow for more complex updates (e.g.,replace,remove). - Structure:
{ "name": "Alice" } - Reason: LLMs are trained to generate JSON objects. Forcing them to generate an "adjacency list" representation of a map was inefficient and error-prone.
5. Data Binding & State¶
5.1. Standardization of path¶
v0.8.1:
- Used
dataBindinginchildrenPropertytemplates. - Used
pathinBoundValueobjects. - Inconsistent terminology.
v0.9:
- Unified: Everything is now
path. - Reason: Reduces cognitive load for the LLM. "Path" always means "JSON Pointer to data."
5.2. Simplified Bound Values¶
v0.8.1:
{ "literalString": "foo" }or{ "path": "/foo" }.- Explicit typing in keys (
literalNumber,literalBoolean).
v0.9:
- Implicit Typing:
stringOrPath,numberOrPath, etc. are defined incommon_types.json. - Structure: The schema allows
stringOR{ "path": "..." }. - Reason: Much more natural JSON.
{ "text": "Hello" }is valid.{ "text": { "path": "/msg" } }is valid. No need for{ "text": { "literalString": "Hello" } }.
6. Component-Specific Changes¶
6.1. Button Context¶
v0.8.1:
- Array of Pairs:
context: [{ "key": "id", "value": "123" }] - Reason: Easy to parse, hard to generate.
v0.9:
- Standard Map:
context: { "id": "123" } - Reason: Token efficiency. LLMs understand JSON objects as maps natively.
6.2. TextField¶
v0.8.1:
- Property:
textFieldType(e.g., "email", "password").
v0.9:
- Property:
usageHint. - Reason: Consistency with
TextandImagecomponents which already usedusageHint.
6.3. ChoicePicker (vs MultipleChoice)¶
v0.8.1:
- Component:
MultipleChoice. - Properties:
selections(array),maxAllowedSelections(integer).
v0.9:
- Component:
ChoicePicker. - Properties:
value(array),usageHint(enum:multipleSelection,mutuallyExclusive). ThemaxAllowedSelectionsproperty was removed. - Reason:
ChoicePickeris a more generic name that covers both radio buttons (mutually exclusive) and checkboxes (multiple selection). TheusageHintcontrols the behavior, simplifying the component surface area.
6.4. Slider¶
v0.8.1:
- Properties:
minValue,maxValue.
v0.9:
- Properties:
min,max. - Reason: Standardizing on shorter, more common property names.
7. Error Handling¶
v0.9 introduces a strict ValidationFailed error format in client_to_server.json.
- Purpose: To allow the "Prompt-Generate-Validate" loop to work effectively.
- Mechanism: If the LLM generates invalid JSON, the system sends back a structured error:
- Result: The LLM sees this and can "self-correct" in the next turn.