How to Integrate A2UI with Existing Applications: A Complete Developer Guide
Integrate A2UI by installing the framework-specific renderer and shared @a2ui/web-lib, initializing a MessageProcessor to manage state, rendering a surface component bound to that processor, and connecting to an agent via A2UIClient to exchange JSON payloads that dynamically update your UI.
A2UI is an open-source framework from Google that enables AI agents to generate dynamic user interfaces through JSON payloads rather than executable code. If you are looking to integrate A2UI with existing applications, you will bridge your current frontend stack with the A2UI architecture using framework-specific renderers and the core message processing library. This guide walks through the exact implementation steps, source file references, and code patterns used in the google/A2UI repository.
Understanding the A2UI Integration Architecture
Before writing code, understand how A2UI separates UI generation from rendering. The architecture consists of five distinct layers:
- Agent — Generates A2UI JSON payloads describing component hierarchies and data models.
- Transport — Delivers payloads via Server-Sent Events (SSE), WebSockets, or the A2A protocol.
- MessageProcessor — The core state machine in
@a2ui/web-libthat validatesServerToClientMessageinstances and updates an in-memory surface model tracking surfaces, catalogs, component models, and the data model. - Renderer — Framework-specific packages (Lit, React, Angular, Flutter) that map abstract components to native widgets.
- User Interaction — Captured as A2UI action events and forwarded back to the agent.
Core Components and Source Locations
| Component | Role | Source Location |
|---|---|---|
| MessageProcessor | Validates and applies incoming messages, manages surfaces and data models. | renderers/web_core/src/v0_9/processing/message-processor.ts |
| A2UIClient | Thin wrapper around the A2A JavaScript SDK handling MIME types and message extraction. | samples/client/lit/shell/client.ts |
| Web Library | Shared core library for state management across all web renderers. | @a2ui/web-lib |
| Agent SDK | Python utilities for generating valid A2UI payloads. | agent_sdks/python/README.md |
| Catalog Definitions | Component definitions the client renders. | specification/v0_9/json/catalogs/minimal/README.md |
Step-by-Step A2UI Integration Guide
Follow these eight steps to embed A2UI into an existing web application. These steps assume a Lit-based integration, but the patterns apply to React and Angular with minor syntax adjustments.
1. Select and Install Your Renderer
Choose the package matching your frontend framework. All web renderers depend on @a2ui/web-lib for core functionality.
npm install @a2ui/web-lib lit @lit-labs/signals
2. Initialize the Message Processor
Create a processor instance to hold surfaces and manage data models. In renderers/web_core/src/v0_9/processing/message-processor.ts, the MessageProcessor class implements the validation and state update logic.
import { v0_8 } from "@a2ui/lit";
// Create a signal-based processor (v0.8 API)
const processor = v0_8.Data.createSignalA2uiMessageProcessor();
3. Render the Surface Component
Insert the framework-specific surface component and bind the processor. The surface acts as a canvas for dynamically generated UI.
For Lit:
import { html } from "lit";
import "@a2ui/lit/ui/surface.js";
export const MyApp = html`
<a2ui-surface .processor=${processor}></a2ui-surface>
`;
4. Establish Agent Connection via A2UIClient
Instantiate A2UIClient from samples/client/lit/shell/client.ts with your agent's base URL. The client automatically injects the required A2A-extension header https://a2ui.org/a2a-extension/a2ui/v0.8.
import { A2UIClient } from "./client.js";
const a2uiClient = new A2UIClient("http://localhost:10002");
5. Send User Messages to the Agent
When users submit input, construct an A2UIClientEventMessage and transmit it via A2UIClient.send().
async function sendUserMessage(text: string) {
const msg: v0_8.Types.A2UIClientEventMessage = {
userAction: {
name: "userMessage",
surfaceId: "default",
sourceComponentId: "chatInput",
timestamp: new Date().toISOString(),
context: { text },
},
};
const responses = await a2uiClient.send(msg);
processor.processMessages(responses);
}
6. Process Agent Responses
Pass returned ServerToClientMessage[] arrays to processor.processMessages(). This updates component trees and mutates the data model, triggering automatic UI re-renders via framework-specific signals or observables.
7. Handle Component Actions
Listen for user interaction events emitted by rendered components. In Lit, use the @a2uiaction event; React uses onA2uiAction.
render() {
return html`
<a2ui-surface
@a2uiaction=${async (e: CustomEvent) => {
const { name, surfaceId, sourceComponentId, context } = e.detail.action;
const msg: v0_8.Types.A2UIClientEventMessage = {
userAction: {
name,
surfaceId,
sourceComponentId,
timestamp: new Date().toISOString(),
context,
},
};
const responses = await a2uiClient.send(msg);
processor.processMessages(responses);
}}
.processor=${processor}
></a2ui-surface>
`;
}
8. Complete the Round-Trip
This configuration creates a full agent-to-UI-to-agent loop: the agent generates JSON UI descriptions, the client renders them, user actions generate events, and the agent responds with incremental updates without shipping executable code.
Reference Implementation and Key Files
Study these source files in the google/A2UI repository to see production-ready integration patterns:
samples/client/lit/shell/app.ts— Complete Lit application demonstrating processor initialization, surface rendering, and action handling.samples/client/lit/shell/client.ts—A2UIClientimplementation showing transport setup and A2UI MIME type handling.docs/guides/client-setup.md— Framework-specific setup instructions for React, Angular, and Flutter.docs/concepts/transports.md— Configuration details for SSE, WebSocket, and A2A protocol transports.
Summary
- A2UI integration requires separating UI generation (agent) from rendering (client) using JSON payloads transported over SSE, WebSockets, or A2A.
- Install the framework-specific renderer plus
@a2ui/web-libto access shared state management. - Initialize a
MessageProcessor(fromrenderers/web_core/src/v0_9/processing/message-processor.ts) to validate and applyServerToClientMessageupdates. - Bind the processor to a surface component (
<a2ui-surface>in Lit) to render dynamic UI. - Connect to agents using
A2UIClient, which handles thehttps://a2ui.org/a2a-extension/a2ui/v0.8header and MIME type wrapping. - Handle user actions by listening for renderer events, forwarding them to the agent, and processing subsequent UI updates.
Frequently Asked Questions
What frontend frameworks does A2UI support?
A2UI provides official renderers for Lit, React, Angular, and Flutter. All web renderers share the core @a2ui/web-lib package and differ only in their thin rendering layers that map abstract components to framework-native widgets.
How does the MessageProcessor manage state updates?
The MessageProcessor class maintains an in-memory surface model containing surfaces, catalogs, component models, and a JSON-pointer-addressable data model. When processMessages() receives a ServerToClientMessage array, it validates the messages, creates or deletes surfaces, updates component trees, and mutates the data model, automatically triggering UI re-renders through the bound framework's reactivity system.
Can I use A2UI without the A2A protocol?
Yes. While A2UIClient simplifies A2A integration, the transport layer supports Server-Sent Events (SSE) and WebSockets directly. You can implement a custom transport adapter that conforms to the message format expected by MessageProcessor without using the A2A JavaScript SDK.
Where is the agent-side logic implemented?
The A2UI Agent SDK (Python) located in agent_sdks/python/README.md provides helper utilities for generating valid A2UI payloads, managing component catalogs, and embedding the required A2A-extension header in HTTP requests.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →