· Agentic AI · 7 min read
The Architecture of Generative UI: Declarative vs Open-Ended
When to return structured JSON cards vs streaming raw html to the frontend.

The web has been static for a long time. We build dashboards, we wire them to databases, and we ship them. If a user wants to view their analytics, they navigate to /analytics. If they want to view their billing history, they navigate to /billing. The interface is fixed. It was drawn by a designer, implemented by a frontend developer, and compiled into Javascript before the user ever visited the site.
But as AI agents enter the workplace, this paradigm is beginning to crack. If an agent can dynamically decide which tools to execute and what data to retrieve, why should the interface be static? Why can’t the agent draw the interface on the fly?
This is the promise of Generative UI (GenUI). The interface should adapt to the context of the conversation, not just the text. If the agent finds a table of financial data, it should draw a chart. If it finds a list of pending tasks, it should draw a Kanban board.
Building GenUI requires making a fundamental architectural decision. Do you use Declarative GenUI (returning structured JSON cards) or do you use Open-Ended GenUI (streaming raw HTML or React Server Components to the client)?
Let us examine both from first principles.
Declarative GenUI: The Safe Path
In a Declarative GenUI architecture, the agent never touches HTML or Javascript. It does not decide what a button looks like. It does not decide how a chart is rendered.
Instead, the agent returns structured data. It returns a JSON object that says, “I want to display a bar chart with these data points.”
The frontend application (the React or Vue client running in the user’s browser) intercepts this JSON object. The client application already contains pre-compiled, beautiful, accessible UI components. The client reads the JSON schema and decides how to render the bar chart using its own library.
Let us look at what the agent returns in a Declarative system:
{
"ui_type": "chart",
"chart_type": "bar",
"title": "Q3 Revenue by Region",
"data": [
{"label": "North America", "value": 45000},
{"label": "Europe", "value": 32000},
{"label": "Asia", "value": 15000}
]
}The frontend reads this JSON. It passes the data array into its own <BarChart /> component. The user sees a beautiful, interactive chart that perfectly matches the site’s dark mode, its typography, and its spacing scales. We see this today in platforms like Perplexity or search assistants—the model outputs structured data, and the platform renders a locked-down, visual card.
Why Declarative Wins
The primary advantage of Declarative GenUI is safety. You are not letting a non-deterministic neural network generate code that runs in your user’s browser. If the LLM hallucinates a field in the JSON, the client-side component can ignore it or render a fallback error state. Your application does not crash.
Second, speed. Sending a five hundred byte JSON object over the wire is faster than sending a fifty kilobyte text stream of HTML and CSS. The client renders the UI instantly because the layout logic is already compiled in the browser.
Third, accessibility and design consistency. Your designers control the spacing, the colors, and the semantic HTML tags. You ensure that the dynamic UI is screen-reader friendly and responsive. The agent is simply a data supplier.
Open-Ended GenUI: The Infinite Canvas
Open-Ended GenUI throws out the guardrails. In this architecture, the agent is given raw painting tools. It can return HTML, Tailwind CSS classes, or even React Server Components.
The client application receives the stream of raw code and uses a dynamic parser (like dangerouslySetInnerHTML or a dynamic runtime compiler) to render it directly to the viewport.
Let us look at what the agent returns in an Open-Ended system:
<div class="p-6 bg-slate-900 border border-slate-800 rounded-xl shadow-lg">
<h3 class="text-xl font-semibold text-white mb-4">Q3 Revenue by Region</h3>
<div class="flex items-end h-64 space-x-4">
<div class="w-1/3 bg-blue-500 h-[70%] rounded-t-lg"></div>
<div class="w-1/3 bg-blue-600 h-[50%] rounded-t-lg"></div>
<div class="w-1/3 bg-blue-400 h-[20%] rounded-t-lg"></div>
</div>
</div>The agent is drawing the div, setting the background colors, deciding the rounding of the corners, and setting the heights of the bars using Tailwind arbitrary values. The canonical example of this is Anthropic’s Claude Artifacts or tools like Vercel v0—the AI literally writes the code that renders live in front of the user.
The Power (and Danger) of Open-Ended
The advantage of Open-Ended GenUI is infinite flexibility. You do not need to pre-build every possible UI component in your frontend codebase. If the agent needs to draw a Venn diagram, it can. If it needs to draw a custom timeline with specific hover effects, it can. You don’t need a frontend release cycle to ship a new visual interactive experience.
But this power comes with terrifying trade-offs.
First, security. If you are rendering raw HTML or Javascript returned by an LLM, you are opening the door to Cross-Site Scripting (XSS). If an adversary tricks your agent into returning <script>steal_passwords()</script>, your client will run it. You must run aggressive sanitization filters on the client, which slows down rendering.
Second, fragility. Non-deterministic models are terrible at closing HTML tags when they are interrupted. If the LLM stops streaming mid-way through an open <div>, your entire page layout can break. The sidebar disappears, the footer moves to the top, and the page becomes unusable.
Third, design decay. Letting an LLM decide on margin and padding scales inevitably leads to visual drift. Your application begins to look inconsistent. Some cards are teals, others are greens. Some use rounded corners, others are sharp.
Deciding the Architecture
Choosing between Declarative and Open-Ended is a choice between reliability and flexibility.
If you are building an enterprise SaaS platform (a system where reliability is non-negotiable), you should use Declarative GenUI. You should define a tight contract using JSON Schema. Tell the model exactly what visual components are available. “You can display a TextBlock, a DataTable, or a LineChart.” If the agent wants to display data, it must coerce that data into one of those three shapes.
This forces structure on the model. It prevents visual drift, and it ensures safety.
If you are building a creative playground (an experimental workspace or a personalized agentic builder), Open-Ended GenUI might be worth the risk. It allows for emergent user experiences that you could never anticipate as a developer. But you must implement it in a sandboxed iframe. Do not let the open-ended code touch your primary application DOM. Treat it like untrusted user code.
The Hybrid Approach
The most successful production applications in 2026 use a hybrid approach.
They rely on Declarative UI for standard enterprise objects (graphs, tables, metrics, forms). This handles 90% of use cases safely and efficiently.
For the final 10% (the edge cases where the agent needs to visualize a concept that does not fit a standard template), the application defaults to a sandboxed Open-Ended canvas. But it only unlocks the Open-Ended canvas when the agent explicitly requests it via a specific tool call, allowing the platform to apply heavy security filters and visual sandboxing before loading the bytes. This is exactly how tools like Claude Artifacts operate: standard conversation remains declarative, but it spins up an isolated iframe only when a custom visual sandbox is needed.
The web shouldn’t be static, but it shouldn’t be chaotic either. The future isn’t about letting a model re-write your CSS from scratch every time a user types a prompt. It is about using the model to assemble your beautiful, pre-built components in a logical order that serves the immediate human context. Rely on structure first.



