Today we are releasing A2UI 1.0, now faster, easier, and stable, an open protocol and framework for generative UI across web, Android, iOS, wearables, TVs, and any other surface.
👇 Check out what shipped https://x.com/i/article/2120555220635652096
A2UI 1.0 launch and 6 answers to commonly asked generative UI questions
Ask a room of developers what "generative UI" means, and half of them will picture a language model streaming raw HTML and Tailwind classes into a browser pane. Try to make that conform to a design system or work the same across web, mobile, wearables, and TUIs… well… you can’t.
Today we shipped A2UI 1.0 under Apache 2.0, our first stable open protocol & framework for generative UI. It supports renderers across web (React, Angular, Lit), mobile and desktop (Flutter, SwiftUI, Jetpack Compose, Lynx, etc). It includes Agent SDKs (Python, TypeScript, and Dart) and is baked into integration systems like AGUI, etc. It’s significantly faster and easier to build with, still safe and portable.
By Alan Blount (@zeroasterisk)
Read the launch blog to read about the newly launched features like express, macros, skills, more renderers, system one models and more. This article explains some of the technical design choices behind our approach, and answers some of the most common questions we get.
1. Why not Gen HTML/CSS/JS, it’s more flexible?
1. Why not DOM maniulation, it’s faster?
1. Why not iframes, they are easier?
1. Why is this so complicated? Which approach is best?
1. How can I make generation faster?
1. How do you keep the front ends and back ends in sync?
1. Gen UI with components > Gen UI with DESIGN.md
When coding agents generate frontend code in a repository at build time, markdown style contracts like DESIGN.md are a genuine upgrade. Teams at Google Stitch and Vercel popularized encoding typography scales, Geist spacing tokens, and layout rules into DESIGN.md so coding agents stop inventing random purple gradients on every pull request.
Look closely at how Vercel runs DESIGN.md in practice:
Building the file had taken well over 200 runs, counting full rounds, targeted checks, dry runs, and all of the dead ends. Alongside the human reviewers, a model judge wrote critiques for each round, and every round's feedback went into improving the next run.
…
The pages generated with design.md had 39 of those failures. The pages generated without it had 91, which works out to 57% fewer in this test.
This is a success story and I celebrate it. But it is also fragile.
- Errors need to be caught and then added to the DESIGN.md.
- Drift over time is also called out as a concern, if the DESIGN.md differs from the actual design system.
The funniest part of watching teams coax LLMs into mimicking their CSS is that you already built the real thing. Your frontend and mobile engineers probably spent years perfecting dark-mode contrast, RTL layouts, localized date pickers, WAI-ARIA screen-reader attributes, and touch targets in your React, Angular, Lit, Flutter, SwiftUI, or Jetpack Compose library… it’s already there. Just use it.
Keep DESIGN.md in your repository for coding agents building components at commit time. At runtime, A2UI gives agents a contract of pre-built components (catalog.json) they are allowed to use. Designers are in charge of flexibility: 6 big widgets, 20 smaller widgets, 50 atomic components.
2. Streaming raw HTML, JS from an LLM turns prompt injection into XSS
Suppose our agent reads unread Calendar invites, then streams raw HTML, CSS, and JavaScript into your main app DOM. If one external invite hides a prompt injection inside the meeting description, that untrusted text now writes executable markup inside your authenticated session.
Stripping <script> tags with an HTML sanitizer does not close the hole. Crafted CSS rules can float invisible position: fixed click targets over real approval buttons, exfiltrate tokens via background URL fetches, or clobber DOM globals. Security engineers rightly refuse to treat probabilistic model output as trusted client code.
In A2UI 1.0, UI messages are pure declarative data, never executable scripts or raw CSS. An agent can only reference component names (Card, MySpecialCalendarWidget) and functions allowlisted in your catalog.json. Version 1.0 also adds allowedCallers and requiresUserActivation flags on client functions, blocking background streams from triggering external navigation or clipboard actions without a physical user tap.
3. Sandboxed iframes tax memory, state, and layout
Once teams rule out raw HTML in the host DOM, the next step is generating in a sandboxed iframe. Modern extensions like MCP Apps use a double-iframe setup: an outer proxy (sandbox.html) feeding untrusted HTML into an inner srcdoc frame with sandbox="allow-scripts" on an opaque null origin.
For a rich, standalone third-party canvas like a 3D WebGL viewer or custom Kanban board, that trade-off makes total sense (and A2UI 1.0 embeds MCP Apps directly via @a2ui/catalog-mcp). For a chat stream of fifteen interactive cards, however, iframes fight browser physics. Fifteen cards spin up fifteen separate document contexts and duplicate framework JS in memory. Because the origin is null, localStorage and cookies throw SecurityError. Dropdown menus clip at the rectangular frame edge, Tab focus gets trapped, and resizing heights asynchronously over postMessage janks mobile scrolling.
If you control the UI, render everything you can natively, your design system, no iframe tax. Save iframes for the 10% of widgets that truly need an isolated pixel canvas, or someone else’s fully trusted UI.
4. Spectrum of Gen UI
Text is a great input, you can communicate most things, but it isn’t a good output. Humans want UI and with Generative UI, the promise is that we will get UI tailored to the moment, bespoke, personalized, and with just the important bits. We keep talking about a spectrum of options for agents to send UI to users:
- Prebuilt UI, an agent just picks a screen.
- Your page in their chat, inject widgets where needed, from somewhere else.
- Declarative UI, composed from a catalog of components
- Fully coded or rendered UI, on the fly
Use any of them. Use all of them. We do.
A2UI started out as the 3rd option, but we published 3 approaches for MCP Apps + A2UI, and have working versions of A2UI driving iframes with custom rendered HTML templates inside them.
5. LLMs like Express DSL more than nested JSON
Early server-driven UI prototypes (ours included) almost always asked the model to emit raw wire JSON directly. If you inspect the token stream, raw UI JSON is painfully wordy. Most tokens go to "component":, "children":, "id":, quotes, and nested braces, and one stray comma 600 tokens in breaks parsing.
Rabi Shanker Guha (@rabi_guha) and the OpenUI project demonstrated this clearly with OpenUI Lang. They showed that raw UI JSON wastes up to two-thirds of output tokens on structural ceremony and stalls streaming until outer brackets close, whereas a line-oriented positional DSL (identifier = Component(...)) matches how code-trained LLMs naturally generate structure.
That insight inspired A2UI Express, now the default inference format across the 1.0 Python, TypeScript, and Dart Agent SDKs. Inside <a2ui>...</a2ui> tags, the model writes concise positional calls and $/path bindings:
On our 54-sample core_v1_0 benchmark with gemini-3.8-flash (temperature=0.0), Express cuts median prompt tokens by 45.4% (10,980 down to 6,000). Generated UI code tokens drop 63.2% (2.7x) without thinking and 67.3% (3.1x) with unbounded thinking. Customers have used Express to cut clinical dashboard latency from 10 seconds to 5 seconds, and Soverius AI fine-tuned a local Gemma 4 model to stream Express right inside the browser.
We have an Agents SDK which helps you generate skills for your agent, and translate the model output from A2UI Express into JSON for the wire (next section).
6. Flat JSON and JSONL on the wire and for each renderer
Once you see how fast a positional DSL streams, it is tempting to parse that DSL directly inside every iOS, Android, and web app. It’s a trap. Coupling six client renderer SDKs to one LLM syntax means every future prompt format upgrade waits on mobile App Store rollouts. (Anyone who has waited three weeks for stragglers to update an iOS binary knows how painful that gets.)
A2UI 1.0 draws a hard boundary between inference format on the server and wire protocol on the transport. On the server, A2uiGenerator compiles <a2ui> Express blocks into standard A2UI 1.0 JSON and JSONL envelopes.
The same wire format also accepts server-side @macro expansions (keeping private database lookups off the LLM prompt) or structured picks from System 1 decision models like Jev in ByteDance's Lynx playground:
1. createSurface opens a surface and can inline initial components and dataModel in one message.
1. updateComponents streams a flat, ID-addressed component list ("id": "root_child_0") so updates never diff deep trees.
1. updateDataModel sends small RFC 6901 JSON Pointer updates ("/visit/slot") over SSE, WebSockets, A2A, AG-UI, or MCP.
Client renderers only ever parse validated JSON. You can swap models, change inference grammars, or move a tricky card into a deterministic Python @macro without shipping a single client app update.
Our goal is reliable interoperability: protocol & framework
Over the past year, nearly every architecture chat we had with engineering teams across the industry hit some type of consensus: "Wait, we built an internal version of that too." or “We could map our <thing> to A2UI easily.”
OpenUI built a positional DSL and React catalog. ByteDance built streamed native generative UI for Lynx (lynx-ui). Alation built declarative SQL-backed feeds for AIOS that needed to render inside both Alation's Data Products App and Claude. Atlassian built interactive agent cards inside Jira. Bloomberg, CommerceTools, CopilotKit, and teams across Google (including Gemini Notebook and Gemini Enterprise) all are letting agents respond with UIs.
We are building A2UI 1.0 to be open, easy, fast, secure and reliable. You should be able to add it to an existing project, with your existing front end (you don’t need ours) and your existing agents.
Read the launch post and partner showcases on the Google Developers Blog, experiment in the browser at the A2UI Playground, and explore the quickstart, docs, and spec at a2ui.org.
After you see what 1.0 delivers, use discussions or X and tell us what you’d wish for next.
Follow @GoogleCloudTech and @zeroasterisk for more architecture notes from the builder trenches.
