Skip to content

Evolution Guide: v0.8 → v0.9

Living Document

This guide is automatically included from specification/v0_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.1 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
Button Variant Boolean (primary: true) Enum (variant: "primary")
Catalog Separate component and function catalogs Unified Catalog (standard_catalog.json)
Auxiliary Rules N/A standard_catalog_rules.txt
Validation Basic Schema Strict ValidationFailed feedback loop
Data Synchronization Implicit Explicit Client->Server data syncing (sendDataModel)

2. Architectural & Schema Changes

2.1. Modular Schema Architecture

v0.8.1:

  • Monolithic tendencies. server_to_client.json often contained deep definitions or relied on complex oneOf structures that were hard to decompose.
  • standard_catalog_definition.json existed but was often implicitly coupled.ß

v0.9:

  • Modularization: The schema is strictly split into:
  • common_types.json: Reusable primitives (IDs, paths) and logic/expression types.
  • server_to_client.json: The "envelope" defining the message types.
  • standard_catalog.json: The unified catalog of UI components and functions.
  • Swappable Catalogs: server_to_client.json now uses a relative reference to catalog.json as a placeholder. This allows developers to alias catalog.json to standard_catalog.json (or any custom catalog) during validation, enabling the use of custom component sets without modifying the core envelope schema.
  • Unification: Components and functions are now part of the same catalog object, simplifying capability negotiation and inline definitions.

2.2. Strict Message Typing

v0.8.1:

  • Messages were objects where properties like surfaceUpdate were optional keys.
  • Validation often relied on "minProperties: 1" constraints.

v0.9:

  • Uses a top-level oneOf constraint in server_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 beginRendering message 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: beginRendering is REPLACED by createSurface.
  • Purpose: createSurface signals the client to create a new surface and prepare for rendering.
  • Theme Information: createSurface includes a theme property to specify theme parameters (like primaryColor). This replaces the styles property in v0.8.
  • Root Rule: The rule is: "There must be exactly one component with the ComponentId 'root'." The "root" attribute that beginRendering had has been removed. The client is expected to render as soon as it has a valid tree with a root component.
  • New Requirement: createSurface now requires a catalogId (URI) to explicitly state which unified catalog (components and functions) 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.org/specification/v0_9/standard_catalog.json",
    "theme": {
      "primaryColor": "#007bff"
    }
  }
}

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 contents property 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 value property is now a standard JSON object.
  • Simplified: The system relies on upsert semantics, so the client will create or update the data model at the specified path, or remove it if the value is null.
  • 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 dataBinding in childrenProperty templates.
  • Used path in BoundValue objects.
  • Inconsistent terminology.

v0.9:

  • Unified: Everything is now a 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: DynamicString, DynamicNumber, etc. are defined in common_types.json.
  • Structure: The schema allows string OR { "path": "..." }.
  • Reason: Much more natural JSON. { "text": "Hello" } is valid. { "value": { "path": "/msg" } } is valid. No need for { "text": { "literalString": "Hello" } }.

5.3. String Interpolation

v0.8.1:

  • Strict Envelopes: Static text and data model references had to be separate or wrapped in explicit objects. Mixing literal text and dynamic values in a single string was not officially supported at the protocol level without custom logic.
  • Structure: { "text": "static" } OR { "text": { "path": "/var" } }.

v0.9:

  • String Formatting: Introduced the formatString function, which supports ${expression} syntax for interpolation.
  • Unified Expression Language: Allows embedding JSON Pointer paths (absolute and relative) and client-side function calls directly within the format string.
  • Nesting: Supports recursive nesting of expressions (e.g., ${formatDate(value: ${/timestamp}, format: 'yyyy-MM-dd')}).
  • Restriction: String interpolation ${...} is ONLY supported within the formatString function. It is not supported in general for string properties, in order to strictly separate data binding definitions from static content.
  • Reason: Improves readability for complex strings. Instead of generating complex nested JSON objects (like chained concatenations) to combine strings and data, the model can write natural-looking template literals within the formatString function.

5.4. Data Synchronization

v0.8.1:

  • Data synchronization was implicit and relied on ad-hoc mechanisms.

v0.9:

  • Explicit Client->Server Data Model Sync: createSurface introduced sendDataModel (boolean).
  • Single-Path Updates: Server pushes updates via updateDataModel using simple path/value pairs.
  • Client->Server Data Model Sync: When sendDataModel is true, the client includes the full data model in every A2A message metadata.

6. Component-Specific Changes

6.1. Button Context

v0.8.1:

  • Array of Pairs: context: [{ "key": "id", "value": { "literalString": "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. Button Variant

v0.8.1:

  • Boolean: primary: true or primary: false.
  • Limited: Only two styles were explicitly supported.

v0.9:

  • Enum: variant: "primary" or variant: "borderless".
  • Reason: More flexible and consistent with other components (like Text and Image) that use variant for styling hints. 'borderless' provides a standard way to represent clickable text or icons without a button-like frame.

6.3. TextField

v0.8.1:

  • Property: textFieldType (e.g., "email", "password").
  • Validation: validationRegexp.

v0.9:

  • Property: variant.
  • Validation: checks (generic list of function calls).
  • Reason: Consistency with Text and Image components which already used variant. Validation is now more flexible and reusable. Also, text was renamed to value to match other input components.

6.4. ChoicePicker (vs MultipleChoice)

v0.8.1:

  • Component: MultipleChoice.
  • Properties: selections (typed wrapper), maxAllowedSelections (integer).

v0.9:

  • Component: ChoicePicker.
  • Properties: value (array), variant (enum: multipleSelection, mutuallyExclusive). The maxAllowedSelections property was removed.
  • Reason: ChoicePicker is a more generic name that covers both radio buttons (mutually exclusive) and checkboxes (multiple selection). The variant controls the behavior, simplifying the component surface area.

6.5. 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:
{
  "error": {
    "code": "VALIDATION_FAILED",
    "surfaceId": "...",
    "path": "/components/0/text",
    "message": "Expected string, got number"
  }
}
  • Result: The LLM sees this and can "self-correct" in the next turn.

8. Property Rename Summary (Migration Quick Reference)

For developers migrating from earlier versions, here is a quick reference of property renaming:

Component Old Name New Name
Row / Column distribution justify
Row / Column alignment align
Modal entryPointChild trigger
Modal contentChild content
Tabs tabItems tabs
TextField text value
Many usageHint variant
Client Message userAction action
Common Type childrenProperty ChildList