Overview
Render rich, declarative UI surfaces from your LangGraph agent using the A2UI protocol.
A2UI (Agent-to-UI) is a Declarative Generative UI specification led by Google, with CopilotKit as a launch and design partner. It lets your agent render structured UI components using a JSON-based schema. Instead of sending plain text, the agent produces surfaces — cards, lists, buttons, images — that render natively in the chat.
You can design and preview A2UI schemas visually using the A2UI Composer.
Setup#
Enable A2UI in your CopilotRuntime by adding a2ui: true, or pass an object to customise:
import { CopilotRuntime } from "@copilotkit/runtime";
// Simple — enable with defaults
const runtime = new CopilotRuntime({
agents: { default: myAgent },
a2ui: true,
});
// Or customise — e.g. inject a render tool into the agent
const runtime = new CopilotRuntime({
agents: { default: myAgent },
a2ui: {
injectA2UITool: true,
},
});This tells the runtime to apply the A2UI middleware to your agents. The middleware intercepts tool results containing A2UI operations and renders them as rich UI surfaces in the chat.
Without a2ui configured in your CopilotRuntime, A2UI surfaces will not render — tool results will appear as plain text.
Approaches#
CopilotKit supports three approaches to A2UI, each with different tradeoffs:
- Fixed Schema — Pre-defined schema loaded from JSON. Agent provides data only. Fastest — no LLM schema generation.
- Fixed Schema (Streaming) — Same pre-defined schema, but cards appear one-by-one as the LLM streams data. Great for lists.
- Dynamic Schema — A secondary LLM generates both the schema and data. Fully flexible — any UI from any prompt.
When to use which?#
| Approach | Schema source | Rendering | Best for |
|---|---|---|---|
| Fixed Schema | JSON file | Instant (all at once) | Known UI patterns (flight cards, product lists) |
| Fixed Schema Streaming | JSON file | Progressive (card by card) | Long lists where you want immediate feedback |
| Dynamic Schema | LLM-generated | Progressive (card by card) | Unknown/varied UI — the agent decides what to show |
All three approaches use the same A2UI protocol and renderer. The difference is where the schema comes from and how data reaches the client.
How it works#
Every A2UI v0.9 surface is built from three operations:
createSurface— initializes the surface with its catalog (must come first)updateComponents— defines the component tree (the schema)updateDataModel— provides the data that populates the components
The CopilotKit Python SDK provides helpers to build these operations:
from copilotkit import a2ui
a2ui.create_surface(surface_id)
a2ui.update_components(surface_id, components)
a2ui.update_data_model(surface_id, {"items": data})
a2ui.render(operations) # wraps in a2ui_operations and serializesContinue to one of the approach guides above to see the full implementation.
