For two years, "generative UI" was a demo: you'd ask a chatbot for the weather and instead of a sentence it drew a little card with a sun on it. Cute, brittle, and mostly hand-wired. In 2026 it grew up. There are now real repos with real star counts solving the real problem — letting an agent return interface instead of prose, so the user books the flight, edits the row, or approves the diff by clicking, and those clicks flow back into the agent loop.

But the interesting thing about the space isn't that it exists. It's that it split. Underneath the frameworks is one question they answer in opposite ways, and the answer determines everything about which repo you should clone.

The question is: who owns the component the agent renders — your codebase, or the protocol?

Get that straight and the whole landscape organizes itself.

Camp one: your code owns the component#

In this model, the agent is a router, not a designer. You build the components — a <FlightCard>, a <Chart>, an <ApprovalForm> — and register them. The model's job is to pick the right one and fill in its props, which stream in as they're generated. The UI never leaves your application; the model just decides which of your things to show.

Provider-agnostic TypeScript toolkit whose generative-UI layer maps tool-call results to your React/Vue/Svelte components, with streamed props
★ 25.4kTypeScriptvercel/ai
React toolkit: register components with Zod schemas, and the agent selects one and streams its props for the user to interact with
★ 11.2kTypeScripttambo-ai/tambo

The Vercel AI SDK is the default entry point here because most teams already have it in the building for streaming text and tool calls — generative UI is the same tool-result plumbing, just rendered as a component instead of a string. Tambo makes the "model as component-picker" idea explicit: you hand it a registry of components and their Zod schemas, and it treats that registry as an action space the agent chooses from, streaming props in real time.

The virtue of this camp is that it's less machinery and safer. The components are yours, type-checked at build time, and there's no untrusted markup to sandbox — the model can only pick from a menu you wrote. The limitation is the flip side: the UI is trapped in your app. A component registry compiled into your React bundle cannot render inside someone else's surface.

Camp two: the protocol owns the component#

The other camp takes ownership out of your codebase and puts it in a wire format. The agent doesn't pick your component — it emits a declarative description of UI (a JSON payload: "a form with these fields," "a card with this layout"), and any compliant host renders that description using its own native widgets. The UI travels with the message.

Open, framework-agnostic format that lets agents "speak UI" as declarative JSON, rendered by native components across Flutter, Lit, Angular and more — data, not executable code
★ 15.6kTypeScriptgoogle/A2UI
SDK implementing the MCP Apps standard: tools deliver interactive web UI over the Model Context Protocol, rendered in sandboxed iframes on the client
★ 5.0kTypeScriptMCP-UI-Org/mcp-ui

A2UI's whole pitch is portability: the same JSON payload renders across Flutter, Lit, Angular, and web, because the format separates the UI's structure from its implementation. It also makes a deliberate security choice — it ships data, not executable code, so a host is interpreting a description rather than running whatever the agent sent. MCP-UI comes at portability from the Model Context Protocol angle: it lets an MCP tool return a rich web interface that any MCP-Apps-compliant client renders, and it puts that remote UI inside a sandboxed iframe precisely because the payload is untrusted.

That last detail is the tax of this camp. The moment UI becomes portable, it also becomes untrusted — you're rendering something a server or model produced, in a surface you may not control. The portable-description projects are the ones that had to think hardest about sandboxing, and if you roll your own version of this you inherit that problem whether you planned to or not.

The one that spans both#

Full-stack SDK for agentic apps and generative UI across React, Vue, Angular, and chat platforms; authors the AG-UI protocol adopted by Google, LangChain, AWS, Microsoft, Mastra, and PydanticAI
★ 35.7kTypeScriptCopilotKit/CopilotKit

CopilotKit is the most-starred repo in this roundup, and the reason is that it refuses to pick a side. It authors the AG-UI protocol — a wire format for agent-to-frontend events, in the portable-description tradition — and ships a React runtime that renders generative UI directly, in the component-mapping tradition. Its own docs describe three generative-UI modes: static (AG-UI), declarative (A2UI), and open-ended (MCP Apps). It is, in effect, an aggregator of the split.

That breadth is a genuine advantage if you want a batteries-included agent-UI layer and don't want to bet on one mechanism yet. It's also the thing to be honest about: adopting CopilotKit is adopting a framework, with its opinions and its surface area, not a single primitive you can reason about in an afternoon. The narrower repos ask less of you.

How to actually choose#

Start with the geography of where your agent's UI has to appear.

If the agent renders inside one application you own — a support console, an internal ops tool, your own chat product — reach for the component-mapping camp. The Vercel AI SDK if you're already using it; Tambo if you want the component-registry pattern as a first-class idea. You get type safety, build-time checking, and no untrusted-markup problem, because the model only ever picks from components you wrote.

If the same agent must render across surfaces you don't control — a third-party MCP client, an embedded assistant on someone else's page, several frontend frameworks at once — you need a portable description. A2UI if the priority is rendering one payload across many frameworks safely; MCP-UI if your agent's capabilities are already exposed as MCP tools and you want the UI to ride the same protocol. And budget for the sandboxing work — portability and untrust arrive together.

And if you want the whole capability without committing to a camp, CopilotKit is the pragmatic default precisely because it holds both. Just go in knowing you're adopting the framework, not the primitive.

The deeper point is that generative UI is now a distribution decision as much as a rendering one. "Who owns the component" is really "how far does this UI have to travel," and the answer to that question — not the star count — is the one that picks your repo.