The Problem It Solves
AI agents are getting smarter, but their output is still mostly plain text. When agents try to generate rich UI—forms, dashboards, interactive elements—they either produce boring text or dangerous executable code. There's no safe middle ground.
Agents return plain text, or worse, raw HTML and JavaScript that could contain anything. Want a booking form? The agent generates <script>fetch('https://...')</script> that runs directly in your app.
That means code injection attacks, visual inconsistency across platforms, broken accessibility, and iframes that look nothing like your app. You trade security for expressiveness.
Boring text or dangerous code. No safe middle ground.
Agents describe what they want to show using a catalog of approved components—buttons, cards, date pickers, charts, forms. Your app renders them with its own styling and security controls.
Like ordering from a menu: the agent picks items, but your kitchen controls what gets served. No code execution, no injection attacks, no visual inconsistency.
Rich UI without code execution. Security by architecture.
How It Works at Runtime
- App publishes a Component Catalog. Your app declares which UI elements agents can use—buttons, forms, date pickers, charts. This is the menu. Agents can only pick from what's on it.
- Agent decides the user needs rich UI—a booking form, a dashboard, a multi-step wizard. Plain text won't cut it.
- Agent builds a
surfaceUpdate. It assembles a JSON message listing component IDs, types, and properties—only picking from the catalog. No code, no HTML, just data describing intent. - Your app's renderer receives the JSON. It maps each component to a native UI element from your design system and renders it on screen—with your styling, your accessibility features, your brand.
- User sees a native interface. A fully styled, accessible form that looks identical to every other screen in your app. No iframes, no visual dissonance.
- User interacts. Picks a date, fills a field, clicks Submit. Each interaction fires an Action—structured data sent back to the agent.
- Agent receives the action and responds. It processes the input (confirms a booking, runs a calculation) and can send a new
surfaceUpdatewith updated UI. The cycle continues.
Where A2UI Shows Up
A2UI shines whenever an AI agent needs to show more than just text. Here's where declarative UI from agents makes the biggest difference.
Booking & Reservations
Instead of a 10-message back-and-forth asking for date, time, party size, and name, the agent generates a complete booking form in one response. The user fills it out and submits.
Enterprise Dashboards
Google uses A2UI in Gemini Enterprise to generate approval workflows, data visualizations, and multi-step wizards—all rendered natively in the company's existing UI framework.
Cross-Platform Apps
One A2UI response renders natively on iOS, Android, web, and desktop—automatically matching your app's look and feel. No separate UI logic for each platform.
Third-Party Agent Marketplaces
When untrusted agents from a marketplace need to display UI in your app, A2UI ensures they can only use components you've approved. No code injection, no security surprises.
Accessible Interfaces
Because A2UI uses your app's native components, accessibility features come for free. Screen readers, keyboard navigation, and contrast settings all work automatically.
Dynamic Data Entry
Agents generate context-aware forms based on what the user needs. A photo analysis agent shows tagging controls; a finance agent shows expense entry fields—all custom, all safe.
Why It Matters
"Safe like data, but expressive like code"—that's the design philosophy. A2UI achieves both by separating what to show from how to show it.
Your app publishes a component catalog—the menu of UI elements agents can request. Agents can only use what's on the menu. Everything else is rejected. This means third-party agents can generate rich, interactive UI without any security risk to your app.
The same agent response renders natively on every platform—iOS, Android, web, desktop—automatically matching your brand's look and feel. No iframes, no CSS battles, no visual dissonance.
Released by Google in December 2025 under the Apache 2.0 license, A2UI is already in production across Opal, Gemini Enterprise, and the Flutter GenUI SDK. It's also integrated with CopilotKit for React-based applications.
Key Concepts in Plain Language
- Component Catalog: A menu of approved UI elements (buttons, forms, charts) that your app trusts. Agents can only request components on the menu—everything else is rejected.
- Declarative Rendering: Agents describe what they want to show (a date picker, a card, a table) as data, not code. Your app decides how to render it using its own components.
- Surfaces: Named canvases where components appear. An agent might put a form on one surface, a chart on another, and a summary on a third—all in one response.
- Data Binding: Components can connect to shared state. When a user picks a date, the value is stored centrally and other components can reference it. The agent doesn't need to manage the data flow.
- Actions: When a user clicks a button or submits a form, the action is sent back to the agent as structured data. The agent processes it and can generate new UI in response.
- Trust Boundary: The critical line between what the agent controls (what to show) and what your app controls (how to show it). A2UI makes this boundary explicit and secure.
The Standard
A2UI separates what to show from how to show it. Agents describe intent, your app controls rendering. Security, brand consistency, and cross-platform support—by design, not by accident.
What It Looks Like
An agent sends a surfaceUpdate message describing what UI to show. Your app renders it using its own components:
{
"surfaceUpdate": {
"surfaceId": "booking-form",
"components": [
{
"id": "title",
"component": {
"Text": { "text": "Make a Reservation" }
}
},
{
"id": "date-picker",
"component": {
"DatePicker": {
"label": "Select Date",
"dataBinding": "/reservation/date"
}
}
},
{
"id": "submit-btn",
"component": {
"Button": {
"label": "Confirm",
"action": { "name": "confirm_booking" }
}
}
}
]
}
}
The agent describes a title, a date picker, and a button. Your app renders them using its own native components—matching your brand, your security rules, and your platform. The agent never touches your UI directly.
On the client side, rendering is straightforward. Here's a Web Components example:
import { A2UIRenderer, DefaultCatalog } from '@a2ui/web';
const renderer = new A2UIRenderer({
catalog: DefaultCatalog,
container: document.getElementById('app')
});
// Parse and render the A2UI message
renderer.render(a2uiMessage);
Flutter and Angular renderers follow the same pattern—create a renderer with your component catalog, then call render().
How to Apply This
- • Choose A2UI when agents need to generate rich UI across trust boundaries—especially with remote or third-party agents
- • Think of your component catalog as a contract—it defines exactly what agents can and can't do visually in your app
- • Start with standard components (cards, forms, text, buttons) and expand the catalog as your needs grow
- • For the best of both worlds: use Open-JSON-UI for AI generation (simpler, fewer tokens), then translate to A2UI for rendering (precise, secure)
- • Evaluate available renderers: Flutter, Angular, and Lit (Web Components) are stable today, with React coming soon
- • Pair A2UI with AG-UI: A2UI defines what UI components to display, AG-UI handles the real-time transport layer
- • If using CopilotKit, you get A2UI rendering support out of the box through their React components
What to Watch Out For
Honest Limitations
- • A2UI is at v0.8 Public Preview—the specification is functional but still evolving. Expect breaking changes before v1.0.
- • A2UI is verbose compared to simpler formats, costing more tokens when LLMs generate it directly. The recommended pattern is to generate with Open-JSON-UI and translate to A2UI for rendering.
- • Renderer support is limited today. Flutter, Angular, and Lit (Web Components) are the three stable renderers. React is in development, and SwiftUI/Jetpack Compose are planned for Q2 2026.
- • LLMs find A2UI's deep, explicit structure challenging to generate directly. The translation layer (SimpleA2UI) exists specifically because direct generation is error-prone.
- • For simple text responses, A2UI is overkill. If the agent just needs to answer a question, plain text works fine.
Get Started
- A2UI Website — Official specification, component catalog, and getting-started guide
- What is A2UI? — Introduction and architecture overview
- A2UI GitHub Repository — Source code, renderers for Flutter, Angular, and Web Components
- Build with A2UI + AG-UI — CopilotKit guide for combining A2UI rendering with AG-UI transport