Generative UI: The Rendering Layer Your Agent Is Missing

An AI assistant is asked to book a table. It comes back with the restaurant's phone number, the opening hours, and a note about the walk-in oyster bar at the front. Every fact is correct. The model did the hard part — and the user still has to go make the booking themselves.
Now imagine the same answer rendered as a date field, a time field, and a confirm button. Two taps and it is done. Nothing about the model changed. What changed is the layer between the model's output and something a human can act on — the layer most LLM pipelines never built.
TL;DR — Your agent's raw output is not a user experience. The layer between the model and the screen — now called generative UI, with open specs in Google's A2UI and the MCP Apps extension — is what decides whether the product ships. It has three parts: a contract the model picks components from, streaming so the user sees something in the first second, and a BFF that turns chunks into native widgets. That covers ephemeral output. The durable half — reports, specs, runbooks an agent leaves behind — needs the same three properties, and markdown already has them. MDflow is where that half lives.
That framing comes from Bala Ramdoss, who has spent six years building Amazon Lens — Amazon's suite of camera features for shopping from images, screenshots and barcodes — and gave the AI Engineer talk Agent Output Is Not UX in July 2026. His point is blunt: none of the problems he ran into were model problems. They were delivery problems, and they live between the model output and the pixels.
What is generative UI?
Generative UI is the pattern where the agent describes an interface as data instead of returning prose, and the client renders that description with its own native components. A normal API returns data and the client decides how to draw it. A generative UI response returns what to draw — and the client still owns the drawing.
It is a spectrum, not a single technique. CopilotKit splits it into three tiers:
| Tier | What the model does | Trust required | Example |
|---|---|---|---|
| Controlled | Picks a pre-built component and fills it with data | Lowest | A product card the app already ships |
| Declarative | Composes an interface from a catalog of blocks | Medium | A date field + time field + submit button |
| Open-ended | Generates a novel interface on the fly | Highest | An embedded applet rendered in a sandbox |
Two open specifications now cover the middle and the top:
- A2UI — Agent-to-User Interface, introduced by Google in December 2025. The agent emits a declarative data format, not executable code, and may only reference component types from a catalog the client maintains. One payload renders natively across React, Angular, Flutter and SwiftUI. Version 0.9 landed on 3 July 2026, making the protocol bidirectional and adding resilient streaming that incrementally parses and heals partial model output so components render as they arrive.
- MCP Apps (SEP-1865) — proposed on 21 November 2025 by Anthropic, OpenAI and the MCP-UI maintainers, and shipped as the first official MCP extension on 26 January 2026. UI templates are pre-declared as resources under a
ui://URI scheme, associated with tools through metadata, and rendered inside sandboxed iframes with bidirectional JSON-RPC back to the host.
The common design decision is worth naming, because it is the same one that makes markdown work: the model chooses from a fixed vocabulary; it never invents a component. Ramdoss's own layout contract encodes rules at that level — one to three flights become a swipeable carousel, four or more become a vertical list. The model picks the intent. The client owns the pixels.
Why the rendering layer decides whether the product ships
Because every hard problem in an agentic product turns out to live downstream of the model. Is the experience snappy or slow? Does the user get everything at once or a piece at a time? How does this behave on a two-year-old phone running an app version you shipped in 2024? None of those are model questions. Ramdoss breaks the layer into three patterns.
1. The contract — make the model client-aware
The contract is how the model learns what the client can actually draw. Instead of the renderer squinting at token output and guessing, the model is handed a versioned catalog of components in its context and returns typed blocks: a conversation block for what it says, a UI block for what it wants rendered.
The versioning is the subtle part. If a flight card ships in app version 2.0, it must be surfaced to the model only from 2.0 onwards. That is context engineering pointed at the frontend — and it gets meaningfully harder as one agent serves more surfaces.
2. Streaming — stop measuring total latency
Traditional apps call an API and wait. With a model in the loop, plus safety checks, plus a UI-composition step, that wait becomes unacceptable. Streaming fixes it by rendering in chunks: skeleton first, partial fill, then complete.
This changes what you measure. You stop chasing total latency and start chasing time to first chunk — the first useful thing the user sees. It also kills the loading spinner as a default. Ten seconds is tolerable when the user can see what the agent is doing; two seconds of blank screen is not. Ramdoss's own product example is Lens Live, which lets the user keep tapping objects they are curious about while results are still resolving — the wait becomes part of the interaction instead of an interruption to it.
His caveat on "thinking" UI is worth repeating: use it sparingly. Users have moved out of the forgiving phase and now expect to know what is actually happening.
3. The BFF — let the client stay dumb
The third pattern is a backend for frontend sitting between the model and the app. It is the narrow, practical slice of server-driven UI: it owns the platform-specific rules (Android vs iOS), hydrates each element with data, attaches an action payload to every rendered component — what a tap does, which deep link it opens, which impression metric to log — and carries conversational context across turns so the next response knows what came before.
The payoff is that the client makes fewer decisions and simply draws what it is handed. And critically, it draws it with components the app already ships: the flight row, the product card, the existing design system. You are not bolting an "agentic look" onto your product. Same brand, same density, same familiar feel.
The rule underneath all of it: you cannot patch the client
On the web, a broken renderer is a five-minute fix. On mobile, it is a crash in the hands of hundreds of millions of installs you do not control the update schedule for.
This is the constraint that makes the whole architecture make sense. When a client meets a content type it has never seen, it does not gracefully degrade — it crashes, and it keeps crashing for weeks. Hence the fixed catalog, the version-aware contract, the server-side absorption of anything unfamiliar. Every one of those patterns is really a hedge against a client you cannot reach.
Keep that rule in mind, because it is the one that carries over to the second half of this problem.
Which applications benefit most
- Consumer mobile apps with an AI feature — the talk's home turf. Fragmented versions, uncontrollable update cadence, and a crash budget of roughly zero.
- Booking, ordering and scheduling flows — anywhere the correct answer still leaves the user with work to do. These are the cases where a rendered form beats a perfect paragraph.
- Internal tools and dashboards — where an agent should return a chart, a filterable table or an approve/reject control rather than a description of one.
- MCP servers with a UI story — the MCP Apps extension exists precisely so a server can hand a host something interactive instead of a wall of JSON.
- Agents that produce documents — reports, specs, meeting notes, runbooks. Different half of the problem, same missing layer. That is the rest of this post.
The other half: output that has to last
Generative UI solves the ephemeral half of the rendering problem. A date picker exists for one turn and then it is gone. But a large and growing share of agent output is not a widget — it is an artifact. A research summary. A migration plan. An incident write-up. A PRD. Something a human will read tomorrow, a colleague will read next month, and another agent will read next quarter.
That output needs a rendering layer too, and it needs the same three properties:
| Generative UI needs | Durable output needs | Markdown gives you |
|---|---|---|
| A fixed component catalog the model cannot escape | A fixed structural vocabulary | Headings, lists, tables, code blocks, quotes — and nothing to invent |
| Streaming that renders before it is complete | Partial output that is still readable | A half-written markdown document reads fine; half a JSON object does not |
| A BFF that renders one payload many ways | One artifact, many surfaces | One .md renders as HTML, PDF, slides, a terminal page, or raw text |
| Graceful degradation on an unpatchable client | Never crash on unfamiliar syntax | Unknown syntax falls back to plain text |
That last row is the one that closes the loop with Ramdoss's rule. The most unpatchable client of all is the one you do not control: someone else's agent, someone else's editor, someone else's five-year-old script. Markdown's failure mode is legible text. It is the only widely-used document format whose worst case is still readable.
There is a second reason markdown fits this half specifically: it is what the models already emit. Ask any frontier model for a structured answer and you get headings, bullets and fenced code blocks without being asked. Storing that as markdown is not a conversion — it is the absence of one.
How MDflow fits
MDflow is the durable half of the rendering layer: one markdown artifact, rendered many ways, reachable by every agent. To be clear about the boundary — MDflow does not implement A2UI or MCP Apps, does not render interactive widgets, and is not a BFF for your mobile app. It is where the output that outlives the conversation goes.
What already lines up today
One source, many renderers. A document in MDflow is plain markdown, and the same text is served as: a live preview (with a source view and a split view in the editor), a public share page, a raw .md twin carrying YAML frontmatter with the title, canonical URL and visibility — served with open CORS so another agent can fetch it cross-origin — a print-ready PDF, a fullscreen slideshow split at top-level headings, and the same document in the VS Code extension or the iOS app. That is the BFF pattern applied to documents: one payload, platform-appropriate rendering, no export step in between.
A whole workspace exports as a self-contained archive that renders offline in Obsidian, VS Code or GitHub. Portability is the honest version of "the client you cannot patch" — if MDflow is not the right home tomorrow, the artifacts still render.
Agents write, not just read. Over the remote MCP server (OAuth for Claude and ChatGPT, a Personal Access Token for Cursor, Codex and Claude Code) or the REST API, an agent can create a document, update its body, organise it into folders and share it. So the durable artifact is something the agent produces directly, in the format it already speaks — not a chat message a human then has to relocate by hand.
Folder descriptions are the retrieval contract. Every folder carries a description stating what belongs inside it, and mdflow_get_context ranks those descriptions above folder names and document titles before returning matching markdown. It is the same idea as the component catalog: a small, human-authored vocabulary that tells the model what is available, instead of leaving it to infer structure from raw content. We wrote about that in folder descriptions as agent context.
Version history makes agent output reviewable. Every write — from the editor, the API or MCP — captures the previous version with a line-by-line diff and a non-destructive restore, and the Document Log names the actor, including automated · <token name> for machine writes. When an agent rewrites a runbook, you can see exactly what it changed. (Version history is Pro, and deliberately private to the document owner.)
Discovery is published, not assumed. llms.txt, /docs.md, an OpenAPI spec and an agent card describe the surface so an unfamiliar agent can find its way in — the same instinct as a versioned component contract, applied to an API.
What MDflow does not do. No A2UI renderer, no MCP Apps UI resources, no interactive components, no mobile BFF, no streaming widget protocol. If you need a date picker rendered inside a chat, the tools in this post's first half are the right ones. MDflow is for what the agent leaves behind.
Where we are headed
Direction, not a dated commitment. The interesting frontier for a markdown-native store is richer typed frontmatter — owner, status, freshness — so a document can declare more about itself than its title; serving a whole collection to an agent as one cross-linked bundle rather than a list of separate fetches; and scoped tokens so an agent's reach can be narrowed to the slice its job actually needs.
The bottom line
The model was fine. It has been fine for a while. What is missing in most LLM products is the layer that turns model output into something a human can act on — and that layer has finally acquired a name, a spectrum and two open specifications worth building against.
For the ephemeral half, that means a versioned component contract, streaming measured by time to first chunk, and a BFF that keeps the client dumb and safe. For the durable half — the reports and specs and runbooks agents increasingly write on their own — it means a format with a fixed vocabulary, progressive rendering, many output surfaces, and a failure mode that is still readable.
One of those halves needs new infrastructure. The other has had a working answer since 2004.
Start free · Connect an AI agent · Read the API docs
Frequently asked questions
What is generative UI?
Generative UI is the pattern where an AI agent describes an interface as structured data rather than returning raw text, and the client renders it with its own native components. It sits on a spectrum: controlled, where the model picks from pre-built components; declarative, where the model composes an interface from a catalog of building blocks; and open-ended, where the model produces a novel interface on the fly. Google's A2UI and the MCP Apps extension are the two open specifications for the middle and top of that spectrum.
What is A2UI?
A2UI stands for Agent-to-User Interface. It is an open project Google introduced in December 2025 that lets an agent declare UI intent as a declarative data payload rather than executable code. Agents may only reference component types from a catalog the client maintains, and one payload renders natively across React, Angular, Flutter and SwiftUI. Version 0.9, released on 3 July 2026, made the protocol bidirectional and added resilient streaming that heals partial model output as it arrives.
Why do AI agents need a rendering layer instead of just returning text?
Because raw text pushes the remaining work back onto the user. A restaurant answer that lists a phone number and opening hours is correct but still leaves the person to make the booking; the same answer rendered as a date picker, a time picker and a confirm button finishes the job. The model is not the bottleneck in either case. The delivery layer between the model output and the screen is what decides whether the product works.
Why is markdown a good format for durable AI agent output?
Markdown is a rendering contract with the same properties a generative UI contract needs. It has a small fixed vocabulary the model cannot invent outside of, it streams so a half-finished document is still readable, it renders natively on every client from a web preview to a terminal to a PDF, and unknown syntax degrades to plain text instead of crashing the renderer. That last property matters most for clients you cannot patch.
How does MDflow fit into the agent rendering layer?
MDflow is the durable half. Interactive generative UI is ephemeral — it exists for one turn and disappears. When an agent produces something meant to last, such as a report, a spec or a runbook, MDflow stores it as plain markdown and renders it many ways from one source: a live preview, a public share page, a raw .md twin with YAML frontmatter for other agents, a print-ready PDF, a fullscreen slideshow, and the same document in VS Code or on iOS. MDflow does not implement A2UI or MCP Apps and does not render interactive widgets.
Further reading
- Agent Output Is Not UX: The Rendering Layer Your LLM Pipeline Is Missing — Bala Ramdoss, Amazon Lens (AI Engineer, July 2026) — the talk this post is built on.
- Introducing A2UI and A2UI v0.9 — Google Developers Blog, December 2025 and July 2026.
- SEP-1865: MCP Apps — Interactive User Interfaces for MCP and the announcement post — the first official MCP extension.
- The Generative UI Spectrum — CopilotKit's controlled / declarative / open-ended framing.
- MDflow: building for agents, HTML is the new markdown?, context engineering for AI agents, connecting an agent over MCP.