Frontends used to be fixed: designers sketched them, engineers built them, users received whatever shipped. By 2026 that changed — agents now generate UI in real time from user requests, producing tables, cards or full canvases instead of just textual descriptions.
Generative UI is the layer that enables agents to stop describing and start showing. Three protocols support this space (MCP, A2A, AG-UI), and three architectural patterns have emerged for how apps should consume agent-driven UI. Which pattern you pick matters for token costs, consistency, and scalability.
The protocol stack
- MCP connects agents to tools.
- A2A connects agents to each other.
- AG-UI is the streaming layer that carries tool calls, A2UI schemas, MCP App events and state deltas over SSE. State flows both ways on the same stream: user edits are visible to the agent, agent mutations show up to the user.
A2UI is Google’s spec for agents emitting UI as JSON schema; CopilotKit ships a runtime that decodes the AG-UI stream and handles A2UI.
The three patterns teams often confuse
The spectrum runs from tight frontend control to maximum agent flexibility. Every Gen UI framework sits somewhere on this line.
- Controlled: Pre-built components live in the frontend; the agent selects which one to render.
- Declarative (A2UI): The agent emits a schema; the app maps schema nodes to components from a catalog.
- Open-ended: The agent produces raw HTML or drives a canvas; the app renders it in a sandbox.
Each pattern is an architectural choice — not merely a cosmetic one — and each fails differently at scale.
Pattern 1 — Controlled: frontend owns the UI
Most teams start here. You pre-build components and register them (for example via a hook) with the runtime. The runtime advertises the tool over AG-UI; when the agent calls the tool, its arguments stream down and your component renders inline in chat.
Pros:
- Design system stays in control: consistent visuals, pixel precision.
- Simple integration: one frontend hook, no agent code required for the UI.
Cons:
- Token tax: every registered component description and JSON schema enters the agent’s context before the user asks anything. A typical tool description is ~400 tokens; 25 components are ~10,000 tokens per turn.
- Agent chooses the wrong component when definitions overlap semantically — common after ~15 tools.
When to use Controlled:
- Ten or fewer high-value flows where design precision matters.
When not to:
- If your codebase and component count grows linearly with use cases; 25 components mean 25 tool definitions in every agent turn.
A common mitigation is to move shared state agent-side: have an agent-side tool write session state and let frontend subscribers re-render without an extra LLM call.
Pattern 2 — Declarative (A2UI): agent emits schema
This is what most production agent apps eventually need. The agent emits JSON that describes a component tree and a data model. Your app maintains a catalog that maps catalog component definitions (with Zod-like prop schemas) to renderers. The agent typically issues operations like create_surface, update_components, update_data_model.
Pros:
- Token economics scale: catalog size doesn’t add to token cost per turn.
- Framework-agnostic: it’s just JSON and can be rendered by React, Svelte, Flutter, etc.
Cons:
- The LLM owns layout decisions within the catalog’s constraints. If you need exact pixel placement or legal/marketing text in precise locations, Declarative may be inappropriate.
When to use Declarative:
- You have more use cases than time to pre-build. You care about token costs past prototyping. You need to scale a long tail of card and widget types.
What breaks:
- Catalog ID mismatches between agent and frontend cause silent fallbacks to a basic catalog; the custom card won’t appear and there may be no console error.
Pattern 3 — Open-ended: no catalog, no rules
This is the opposite extreme: full agent control.
Two sub-patterns:
- MCP Apps: an MCP server exposes canvases the agent drives (Excalidraw-like examples). CopilotKit includes MCPAppsMiddleware to integrate MCP Apps servers with agents.
- Sandboxed HTML: the agent writes raw HTML which the client renders inside a sandboxed iframe. The runtime registers an HTML rendering tool and injects it to the agent.
Pros:
- Maximum expressiveness; the agent can create novel visuals and interfaces.
Cons:
- Brand inconsistency: without strict style rules in the agent instruction, rendered UIs can vary wildly. Prompted style constraints help but don’t guarantee uniform brand.
- Operational fragility: iframe sandbox flags can block expected interactions, or be too permissive. Use allow-scripts and allow-forms, but never allow-same-origin.
When to use Open-ended:
- One-shot, disposable visualizations and sandbox experiments. Never as your primary surface.
How to pick
Decision guidance:
- Designer has pixel-perfect mockups for the flow? → Controlled.
- Dozens of card types or widgets? → Declarative.
- One-shot disposable visualization? → Open-ended.
If unsure, default to Declarative. Move a few top flows to Controlled for precision. Avoid making Open-ended your default.
If you’re already shipping and unsure which pattern you used, count render tools: past ~15 suggests you’re in Controlled and approaching the scaling wall; start wiring A2UI.
Three bets
- Controlled bets on pre-built UI and the team’s ability to own visuals; it becomes expensive beyond ~25 components.
- Declarative bets on a schema contract; it scales flat as your catalog grows.
- Open-ended bets on the model’s output; it’s good for throwaway experiences but brittle for repeatable surfaces.
The real mistake is not choosing explicitly. Many teams end up in Controlled because their framework defaults to it, then hit a wall and drift toward Open-ended demos without making a conscious architectural decision.
Pick on purpose: Controlled for exact flows, Declarative for the long tail, Open-ended for disposable experiments.
Resources
The article’s author points to example templates and an "Generative UI Agents" section in awesome-llm-apps as references for implementing all three patterns. Follow @Saboo_Shubham_ for more updates.



