A2UI — Agent-to-UI
The JSON UI language the LLM writes and the shell renders.
A2UI (Agent-to-UI) is the heart of MeghaOS. Instead of generating code, the LLM generates JSON that describes a user interface. The Flutter shell renders that JSON into real, interactive widgets at runtime — no compile step, no redeploy.
The full schema is defined in the A2UI schema (the A2UI schema) and injected into the composition prompt.
The shape of A2UI
Every node is an object with a type and properties directly on the object (not nested
under props):
{
"type": "column",
"spacing": 16,
"children": [
{ "type": "text", "content": "System Health", "size": "large" },
{ "type": "gauge", "value": 72, "max": 100, "label": "CPU", "color": "0xFF007AFF" },
{ "type": "sparkline", "values": [10, 24, 18, 40, 35], "color": "0xFF4CAF50" }
]
}Properties go directly on the component object. {"type":"text","content":"Hi"} is
correct; {"type":"text","props":{"content":"Hi"}} is wrong and won't render.
Component families
The schema groups types into families. See the full catalog in the Component Reference.
container, row, column, stack, grid, wrap, padding, align, center,
positioned, transform, sized_box, divider.
button, slider, toggle, input_text, dropdown — each carries an action.
animated_value, gauge, sparkline, chart, pulse, typing_text,
fade_in_column.
Self-managing widgets like live_timer, pomodoro, kanban_board, live_weather —
organized into tiers (see below).
animated_svg, diagram, node_graph, calendar_view for explaining concepts with
animated visuals.
Colors and theming
Use hex strings or semantic tokens. Tokens adapt to the active theme
(dark / light / glassmorphic) automatically:
{ "type": "text", "content": "Total", "color": "textPrimary" }
{ "type": "gauge", "value": 80, "color": "0xFF007AFF" }Colors must be strings: "0xFF000000", not 0xFF000000. Property names must be
double-quoted, and no trailing commas — it's strict JSON.
Actions
Interactive elements carry an action payload the shell dispatches back to the agent:
{
"type": "button",
"label": "Kill",
"style": "danger",
"action": { "payload": { "command": "kill_process", "pid": "1234" } }
}Built-in commands include kill_process, set_volume, set_brightness, toggle_wifi,
run_command, open_app, and refresh.
Safety: the layout validator
Because the UI tree is generated by an LLM, the renderer enforces hard structural limits so a malformed or oversized tree can't crash the shell. The schema tells the model to stay well under these:
| Limit | Cap | Behavior when exceeded |
|---|---|---|
| Nesting depth | < 50 | Deep subtrees collapse to a placeholder |
| Children per node | < 300 | Excess children dropped |
| Total components | ~2,000 | Tree truncated |
The same caps are enforced in both the assistant and the desktop — keep them in sync if you change one.
Why JSON instead of code?
JSON can't execute. The worst a bad layout does is render oddly — and the validator catches that.
No build step. The model returns JSON, the shell renders it in the same frame loop.
Smart components encapsulate behavior, so the model assembles rich UIs from a small vocabulary.
Add a widget once in the registry and the model can use it everywhere.