A2UI Protocol: Secure Streaming UI for AI Agents
Resumo
Pixel’s announcement explores A2UI, a protocol that streams structured layout events instead of HTML or generated code. It covers schema-validated components, event types, and native rendering with React, Flutter, SwiftUI, or Jetpack Compose. This approach strengthens security boundaries, supports multiple platforms, and helps preserve design consistency in real-time agent interfaces.
DEV Community
A2UI Protocol: How Agents Stream Layout Data Instead of HTML to Native UI Components
Most agent UIs stream markdown or generate HTML strings. A2UI streams layout data that native framework adapters translate into platform components. The agent emits structured events describing buttons, cards, and forms. The client renders them using React, Flutter, SwiftUI, or Jetpack Compose without a WebView or eval(). This separation creates strict capability boundaries. The agent cannot inject arbitrary code. It composes from a fixed catalog of components defined by the application. The protocol is event-based and optimized for low-latency streaming, making it viable for real-time agent interactions across web and mobile platforms. Why Layout Data Instead of Code Generative UI typically means an LLM writes JSX or HTML, then the client renders it. This works for demos but creates three production problems: Security boundary: Executing agent-generated code requires sandboxing or trusted execution contexts. Cross-platform cost: An agent that generates React code cannot target Flutter or SwiftUI without retraining or prompt engineering. Visual consistency: Generated code may not respect design systems, accessibility rules, or platform conventions. A2UI solves this by treating UI as data. The agent outputs a schema-validated stream of layout primitives. The client maps those primitives to native components. The agent never sees platform-specific rendering logic. The client never executes agent-generated code. This is the same separation used in server-driven UI frameworks like Litho or Epoxy, but extended to agent-generated content. Protocol Shape A2UI uses an event-based protocol. The agent emits a stream of JSON events. Each event describes a UI operation: adding a component, updating state, or signaling completion. Core Event Types Event Type Purpose Payload component_add Append a component to the layout tree Component type, props, parent ID component_update Modify existing component props Component ID, updated props state_sync Synchronize application state State key, value stream_end Signal completion of the UI stream Optional metadata The agent sends these events over HTTP streaming, WebSocket, or server-sent events. The client maintains a layout tree and applies events incrementally. Example Wire Format JSONL format (one JSON object per line): {"type": "component_add", "id": "card-1", "component": "Card", "props": {"title": "Flight Options", "variant": "elevated"}, "parent": "root"}
{"type": "component_add", "id": "button-1", "component": "Button", "props": {"label": "Book Now", "action": "submit_booking"}, "parent": "card-1"}
{"type": "stream_end"}
The client receives these events, validates them against the component catalog schema, and renders them using the native framework adapter. Component Catalog and Capability Boundaries The application defines a component catalog. This is a schema that lists available components and their props. The agent can only compose from this catalog. If the agent references an undefined component or passes invalid props, the client rejects the event. This enforces capability boundaries at the protocol level. The agent cannot: Render arbitrary HTML or execute JavaScript Access components outside the catalog Bypass validation rules defined in the schema The catalog is versioned. Agents and clients negotiate protocol versions during handshake. This allows safe evolution of the component library without breaking existing agents. Sample Catalog Schema const catalog = {
components: {
Card: {
props: {
title: { type: 'string', required: true },
variant: { type: 'enum', values: ['flat', 'elevated'] }
}
},
Button: {
props: {
label: { type: 'string', required: true },
action: { type: 'string', required: true },
disabled: { type: 'boolean', default: false }
}
}
}
};
The agent SDK validates outgoing events against this schema before transmission. The client validates incoming events before rendering. Both sides ...
Powered by Readybot.io