YAML first
Pages declare layout, components, bindings, actions, and stable component identifiers in YAML.
A2UI
Democr.ai implements and extends Google's A2UI protocol, letting modules describe pages and publish effects while clients render native web or desktop interfaces. The backend remains the owner of business behavior.
Authoring model
Democr.ai's A2UI layer builds on Google's A2UI protocol and extends it with YAML-first module pages, runtime effects, native desktop rendering, and SDK-managed server actions.
Pages declare layout, components, bindings, actions, and stable component identifiers in YAML.
A view loads the YAML, prepares minimal data, and seeds page data or stores through the SDK.
Actions can append, replace, open drawers, navigate, and publish stream updates without rebuilding the whole page.
Live example
The capture shows a chat agent publishing runtime updates and inserting structured components into the same message timeline.
Dynamic surfaces
A2UI is designed for interactions where the final result is not the only useful UI update.
A message list can receive user turns, ephemeral agent steps, streamed text, components, and final persisted rows.
Long-running actions can publish state changes while background work continues.
Tools and agents can add tables, cards, lists, charts, or other structured UI blocks to the same conversation surface.
Client contract
The strongest test of a server-driven UI protocol is whether genuinely different clients can consume it. Democr.ai runs a native desktop renderer and web renderers from the same payloads — two very different stacks, one wire format.
A Qt/PySide desktop renderer and a browser renderer consume the same A2UI components and effects. If the protocol leaked rendering assumptions, two stacks this different could not share it.
Effects address predictable targets — message lists, drawers, composers, collection-capable components — so the same update lands on every client.
Dynamic screens append or replace focused elements instead of forcing full-page rerenders, on every renderer.
Example
The example shows the contract shape without turning the page into implementation documentation.
- kind: Row
id: chat_page
children:
- kind: ThreadList
id: chat_thread_list
- kind: MessageList
id: chat_message_list
- kind: Composer
id: chat_composer
send_action:
name: chat.submit_message
Next
Use these pages to move from the concept to adjacent parts of the runtime.