AG-UI and A2UI Protocol Architecture
Why this chapter matters
AG-UI and A2UI sound similar, but they are not interchangeable. Confusing them leads to architectures where the frontend does not know whether it is implementing a transport protocol, an event stream, a component schema, or an agent runtime.
Use this distinction:
- AG-UI: agent-to-user interaction protocol. It describes how agent backends and user-facing apps exchange events, state, tool progress, UI intents, and user interactions.
- A2UI: generative UI specification. It describes how an agent can express UI in a declarative format that a trusted client can render.
They can work together. AG-UI can carry events and lifecycle. A2UI-style payloads can describe generated surfaces or component trees.
CopilotKit's developer-facing taxonomy is a useful practical lens:
| GenUI style | Meaning | Protocol implication |
|---|---|---|
| Static GenUI | The agent selects from predefined UI components or tool-result renderers | AG-UI-style events can identify tool outputs and component intents |
| Declarative GenUI | The agent emits a constrained UI description that a client renders | A2UI-style schemas and component catalogs become central |
| Open-ended GenUI | The system can expose richer application-like surfaces through app/plugin boundaries | Requires much stronger sandboxing, permissions, performance controls, and review |
For most product teams, static and declarative GenUI are the safer path. Open-ended UI generation should be treated like running a third-party app surface, not like rendering a normal message.
Core mental model
AG-UI is the conversation channel. A2UI is the generated interface language.
| Concern | AG-UI-style responsibility | A2UI-style responsibility |
|---|---|---|
| Transport lifecycle | Start, stream, cancel, resume, complete | Usually outside scope |
| Agent state | Shared state, diffs, tool events, progress | Component data bindings may reference state |
| Generated UI | UI intent events and rendering handoffs | Declarative component structures |
| User actions | Send user interaction events to agent | Component events reference allowed actions |
| Debugging | Event traces and protocol messages | Schema validation and render decisions |
| Safety | Event allowlists and state boundaries | Component allowlists and prop validation |
AG-UI event architecture
Agentic experiences do not fit a single request-response shape. A frontend may need to render:
- token streaming
- tool call progress
- retrieved source summaries
- generated components
- state diffs
- approval requests
- cancellation results
- nested sub-agent activity
- final artifacts
An event protocol gives the frontend a stable vocabulary. Instead of parsing arbitrary text like "I am searching now," the app receives a typed event such as tool.started or retrieval.completed.
Recommended event envelope
{
"id": "evt_018",
"workflowId": "wf_491",
"type": "component.proposed",
"timestamp": "2026-05-24T10:00:00Z",
"actor": "renewal-agent",
"payload": {
"surface": "customer-review",
"component": {
"id": "next-best-action",
"type": "approval_action",
"version": "2",
"props": {
"label": "Draft renewal offer",
"requiresConfirmation": true
}
}
}
}
This event is still untrusted. The frontend validates the component before rendering it.
A2UI rendering architecture
A2UI-style systems use declarative UI structures that can be rendered across clients. The important architectural advantage is that the agent does not need to know the internal React, Angular, Flutter, or native implementation. It speaks in abstract components and data.
Renderer responsibilities
| Responsibility | Required behavior |
|---|---|
| Parse | Accept only valid JSON/schema input |
| Validate | Reject unknown components, invalid props, invalid bindings, unsafe URLs |
| Authorize | Check user permission before binding sensitive data or actions |
| Render | Map abstract components to local design-system primitives |
| Instrument | Emit analytics for generated surface impressions and actions |
| Recover | Show fallback UI when part of the generated tree is invalid |
Integration patterns
Pattern 1: Chat plus generated cards
Use AG-UI-style events for the chat/task lifecycle. Use generated component payloads for specific cards such as summaries, tables, recommendations, or approval panels.
This is the best starting point for many products because it preserves a familiar conversation while adding richer interaction where needed.
Pattern 2: Agentic workspace
Use the AI interaction as the main work surface. The agent streams a dynamic workspace: filters, comparisons, generated drafts, data tables, timelines, and approval steps.
This works when the task has many possible shapes, but it requires stronger validation, persistence, and replay.
Pattern 3: Deterministic app with agent sidecar
The main app remains deterministic. The agent observes context and proposes actions through a side panel. Generated UI is limited to suggestions, explanations, and safe previews.
This is useful for regulated, high-risk, or legacy systems.
Protocol boundary decisions
| Question | Decision guidance |
|---|---|
| Should the frontend talk directly to the model? | Usually no. Put model access behind an application backend for auth, cost, prompts, tools, and audit. |
| Should the frontend render arbitrary model content? | No. Render typed content through approved components. |
| Should generated UI be persisted? | Persist enough to replay, debug, resume, and audit. |
| Should every event be user-visible? | No. Show progress that improves trust; hide noisy internal mechanics. |
| Should AG-UI replace REST/GraphQL? | No. It complements normal APIs for agentic interaction flows. |
| Should A2UI replace the design system? | No. It should target the design system through a constrained registry. |
| Should open-ended GenUI be allowed? | Only inside sandboxed, permissioned, observable boundaries with explicit product justification. |
Observability requirements
For every AI interaction, collect:
- workflow id
- user/session id
- agent runtime and version
- model/provider/version
- prompt/template version
- retrieval query and source ids
- event stream timing
- generated component ids and validation results
- user approvals, edits, rejects, and cancellations
- final outcome and cost
Frontend telemetry should connect generated UI behavior to backend traces. Otherwise, a failed AI interaction becomes impossible to debug across protocol, model, retrieval, and rendering boundaries.
End-to-end protocol lifecycle
Think of AG-UI-style interaction as a lifecycle, not a stream of random messages.
| Phase | Typical events | Frontend responsibility |
|---|---|---|
| Initialize | workflow.started, state.snapshot | Create task shell, attach trace id, show cancel affordance |
| Understand | intent.parsed, clarification.requested | Show interpreted goal or ask for missing input |
| Retrieve | retrieval.started, retrieval.completed | Show context gathering and source quality |
| Execute | tool.started, tool.progress, tool.completed | Show named progress and partial results |
| Generate UI | component.proposed, component.updated | Validate, render, patch, or reject generated components |
| Human gate | approval.requested, approval.resolved | Capture approve/edit/reject with audit metadata |
| Commit | mutation.started, mutation.completed | Show durable side-effect status |
| Terminal | workflow.completed, workflow.failed, workflow.cancelled | Preserve outcome, recovery, replay, and next actions |
This lifecycle gives designers and engineers a shared language. It also prevents the common anti-pattern where every stage is represented by the same spinner.
Event taxonomy
Define event classes before defining individual event names.
| Class | Examples | User-visible? |
|---|---|---|
| Lifecycle | started, paused, resumed, completed, failed, cancelled | Usually yes |
| State | snapshot, diff, conflict, restore | Sometimes |
| Retrieval | query, source candidate, source accepted, insufficient context | Often yes |
| Tool | started, progress, output, failed, retried | Often yes, summarized |
| UI | component proposed, patched, rejected, removed | Yes when it changes the surface |
| Approval | requested, edited, approved, rejected, expired | Yes |
| Audit | policy decision, capability denied, budget exceeded | Usually trace-only, sometimes visible |
| Debug | raw model/provider metadata | Trace-only |
The frontend should not expose all protocol events literally. It should translate events into useful user states while preserving trace fidelity for debugging.
A2UI payload validation pipeline
A2UI-style payloads should move through a deterministic pipeline:
raw payload
-> JSON parse
-> envelope validation
-> component allowlist check
-> version normalization
-> prop schema validation
-> permission/data-binding validation
-> design-system/a11y constraints
-> render or fallback
-> telemetry event
Each stage should return a reason code on failure. "Failed to render generated UI" is not enough. Useful reason codes include unknown_component, unsupported_version, invalid_props, unauthorized_binding, unsafe_url, missing_citation, payload_too_large, and client_unsupported.
Compatibility across clients
Generated UI becomes harder when web, mobile, desktop, and embedded clients have different capabilities.
Use a capability handshake:
{
"client": {
"platform": "web",
"appVersion": "2026.05.24",
"supportedComponents": {
"summary_panel": ["1", "2"],
"source_list": ["1"],
"approval_action": ["2"],
"comparison_table": ["1"]
},
"constraints": {
"maxPayloadBytes": 120000,
"supportsStreamingPatches": true,
"supportsFilePreview": false
}
}
}
The agent should receive or be mediated by these capabilities before proposing UI. The renderer still validates, because prompts are advisory and client capability can change.
Protocol security considerations
Protocol events are input. Treat them as hostile until validated.
Controls:
- authenticate the stream and bind it to the user's session
- authorize workflow access before replaying prior events
- prevent event id collision and out-of-order patch corruption
- cap event size and stream duration
- avoid sending secrets, raw prompts, or sensitive tool output to the browser
- sign or server-validate high-risk action requests
- require user approval event to reference the exact payload being approved
- log rejected protocol messages for abuse analysis without storing unnecessary sensitive content
For approval, avoid this weak pattern:
{ "event": "approve", "action": "send_email" }
Prefer this:
{
"event": "approval.resolved",
"workflowId": "wf_491",
"approvalId": "appr_22",
"decision": "approved",
"approvedPayloadHash": "sha256:...",
"editedByUser": false
}
Approval must bind to what the user actually saw.
Failure modes
- A2UI as transport: teams put lifecycle, retries, cancellation, and tool progress inside the UI payload instead of a real interaction protocol.
- AG-UI as UI schema: teams send vague events and expect the frontend to infer component behavior from prose.
- No shared ids: events, traces, generated components, and backend logs cannot be correlated.
- Unversioned schema: a prompt change emits props that older clients do not understand.
- Protocol bypass: one feature uses the official event contract while another invents a private stream.
Verification checklist
- The design explicitly states what AG-UI-style events carry.
- The design explicitly states what A2UI-style payloads describe.
- Generated component schemas are versioned.
- Event streams support cancellation and terminal states.
- Frontend and backend traces share workflow ids.
- Invalid generated UI degrades without breaking the whole task.
Exercises
- Write ten event types needed for a realistic agentic workflow in your product.
- Design one A2UI-style payload for a generated table with filters and citations.
- Create a compatibility plan for mobile clients that do not support a new generated component.
- Decide which events should be visible to the user and which should remain trace-only.
Source lens
This chapter is based on Firecrawl research of the official AG-UI documentation, A2UI sources, and CopilotKit's developer guide to GenUI patterns. The AG-UI docs identify AG-UI as an event-based agent/user interaction protocol and distinguish it from A2UI as a generative UI specification.