Safe, rich interfaces from AI agents—without letting them run code in your app.
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.
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.surfaceUpdate with updated UI. The cycle continues.A2UI shines whenever an AI agent needs to show more than just text. Here's where declarative UI from agents makes the biggest difference.
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.
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.
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.
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.
Because A2UI uses your app's native components, accessibility features come for free. Screen readers, keyboard navigation, and contrast settings all work automatically.
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.
"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.
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.
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().