AG-UI with CopilotKit: Streaming Agent State into Your App UI
How the AG-UI protocol and CopilotKit connect custom frontends to agents, and why day-zero A2UI support makes multi-agent UI rendering practical.
Published on • October 8, 2026
AI Assistant

Agent frameworks are good at producing text and tool calls. They are much worse at producing user interfaces. Two protocols have emerged to close that gap, and they now overlap in a useful way: AG-UI for streaming agent state into your own frontend, and A2UI for letting agents generate UI components you can render anywhere.
The A2UI ecosystem page documents the intersection directly: AG-UI provides the protocol, CopilotKit provides the primary full-stack framework, and the pair ships with day-zero A2UI compatibility.
What AG-UI is
AG-UI (the Agent-User Interaction protocol) is an event-driven protocol between an agent and a frontend. Instead of the client polling for a finished response, the agent streams typed events — tool calls started and finished, text deltas, state patches, tool messages — and the frontend applies them incrementally.
The core idea, in CopilotKit founder Atai Barkai’s words: “AG-UI excels at creating a high-bandwidth connection between a custom-built front-end and its dedicated agent.”
The events you typically consume:
| Event | Meaning in your UI |
|---|---|
RunStarted | Show a loading state, open a run id |
TextMessageContent | Append a token to the streaming message |
ToolCallStarted | Render “Calling search_docs…” |
ToolCallEnded | Show tool output or a chip |
StateDelta | Apply a JSON patch to your app state |
StateSnapshot | Replace app state wholesale |
RunFinished / RunError | Stop spinners, surface errors |
StateDelta is the interesting one. Rather than forcing you to parse markdown and infer intent, the agent can push a structured diff of your application state — a cart being updated, a ticket being reassigned, a document section being edited — and your UI just renders it.
What CopilotKit adds
CopilotKit is the full-stack framework around AG-UI. It gives you:
- React (and other framework) components for chat, text selection, and generative UI
- Frontend actions the agent can call back into
- Human-in-the-loop approval UI
- Support for React, Vue, Angular and other app surfaces through CopilotKit’s integrations
So the division of labor is: AG-UI defines the wire format, CopilotKit implements the client and the developer ergonomics.
Where A2UI enters
A2UI is the sibling protocol for generated UI. Where AG-UI streams state and events, A2UI lets an agent emit a declarative component description — a form, a table, an approval dashboard — that a renderer turns into native widgets.
On the A2UI ecosystem page, the AG-UI/CopilotKit integration is described as giving developers “the best of both worlds”:
- State synchronization: AG-UI handles app state and chat history.
- A2UI rendering: Render dynamic UIs from third-party agents.
- Multi-agent support: Coordinate UIs from multiple agents.
- Framework integrations: React, Vue, Angular, and other app surfaces through CopilotKit.
Barkai frames it as a multi-agent requirement: developers “can now build rich, state-synced applications that can also render dynamic UIs from third-party agents via A2UI. It’s a perfect match for a multi-agent world.”
That matters because in a multi-agent system your agent A owns the conversation, but agent B — owned by another team, maybe another vendor — wants to show a booking form. A2UI is the handoff format for that form.
The three layers, clarified
It helps to place the protocols relative to each other:
┌─────────────────────────────────────────────┐
│ Your app UI (React / Flutter / Angular) │
├─────────────────────────────────────────────┤
│ AG-UI — streaming state & events │ your agent, your app
│ A2UI — declarative generated widgets │ any agent, any renderer
├─────────────────────────────────────────────┤
│ A2A — agent-to-agent transport │ cross-org delegation
├─────────────────────────────────────────────┤
│ MCP — agent-to-tool connectivity │ databases, APIs, files
└─────────────────────────────────────────────┘
AG-UI is the frontend-facing layer of your own agent loop. A2UI is the portable UI payload that can arrive over AG-UI, A2A, or MCP. They compose rather than compete — exactly the relationship the A2A documentation describes for A2A and MCP, one layer down.
A minimal AG-UI consumer
Conceptually, consuming an AG-UI run looks like this:
import { useAgentChat } from "@copilotkit/react-core";
export function Assistant() {
const { messages, visibleMessages, isLoading } = useAgentChat({
agent: "support_agent",
// AG-UI event stream is consumed internally
});
return (
<aside>
{visibleMessages.map((m) => (
<Message key={m.id} message={m} />
))}
{isLoading && <TypingIndicator />}
</aside>
);
}
On the agent side you emit the event sequence for each run. The important design rule: emit state deltas as structured data, not as prose. A frontend that has to regex a markdown table to find out which row changed will eventually break.
Designing for multi-agent UI
Once you accept that UI can come from more than one agent, three patterns emerge:
1. Owner-wins rendering. The agent that opened the surface keeps rendering it; other agents contribute StateDeltas the owner merges. Simple, but requires a merge contract.
2. Surface handoff. Agent A creates a panel and passes the surface id to agent B over A2A; B renders into it via A2UI. Matches the A2UI “remote agent” story — the ecosystem docs note A2UI “supports remote agent use cases through an orchestrator.”
3. Catalog-bounded generation. Restrict agents to a component catalog your design system approved. AG2’s A2UIAgent does exactly this: “Custom catalogs: extend the component catalog with domain-specific components,” with “built-in schema validation and retry” to keep output valid.
Catalog-bounded generation is the pragmatic choice for production. It gives agents creativity inside a box your design system can actually support.
Failure modes to design for
Event ordering. AG-UI is a stream; replays and reconnects happen. Key your UI on the run id and message id, not array index.
Partial state. A dropped connection mid-StateDelta leaves you with a half-applied patch. Prefer snapshot-then-delta, and re-request a StateSnapshot on reconnect.
Untrusted UI. An agent-generated component is untrusted input. Validate against your catalog schema before rendering, and never let a generated payload reach dangerouslySetInnerHTML or an arbitrary deep link.
Latency illusions. Streaming state into a UI that then blocks on a slow fetch feels worse than no streaming. Buffer deltas and flush on animation frames.
Over-eager tool spam. Emitting a ToolCallStarted for every internal helper makes the UI look busy and noisy. Surface tool events the user can act on; log the rest.
When not to reach for AG-UI
If your agent is a single chat bubble answering questions, plain streaming text (SSE or WebSocket) is simpler and AG-UI is overhead. AG-UI pays off when:
- The agent mutates your application state, not just the transcript
- Multiple tools produce visible intermediate progress
- You need human-in-the-loop approval inside the UI
- More than one agent contributes to the same surface
Wrapping up
AG-UI gives your agent a vocabulary for talking to your frontend: events for progress, deltas for state. CopilotKit implements that vocabulary in a way that works across frameworks. And with day-zero A2UI support, the same frontend can render UI generated by agents it does not own — which is the actual shape of the multi-agent applications being built now.