Model or dataset
CopilotKit/OpenGenerativeUI avatar
CopilotKit/OpenGenerativeUI

OpenGenerativeUI: streaming AI-generated HTML into a sandboxed iframe

Open-Source Generative UI Framework

1,552 stars201 forksTypeScriptMIT

At a glance

What is it?
CopilotKit's OpenGenerativeUI is an MIT-licensed TypeScript monorepo that turns a chat prompt into live HTML/SVG rendered inside a sandboxed iframe. It is a reference implementation, not a drop-in library, and it needs a strong model and an Anthropic key to do anything at all.
Who is it for?
Adopt it if you are building an agent product where the answer is a diagram, a chart or a small interactive widget, and you already accept a hosted frontier model in the loop. Do not adopt it if you need deterministic output, offline operation, or a cheap per-request bill, because the README is explicit that weaker models produce broken layouts and incomplete visualizations.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 97 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem is that a chat transcript is a bad place to put a binary tree

Most agent frameworks answer in prose. If a user asks how breadth-first search differs from depth-first search, prose is the wrong medium, and so is a static image, because the useful part is watching the frontier expand. OpenGenerativeUI takes the position that the agent should emit a component instead: an interactive explainer, an SVG diagram, a Chart.js dashboard, a WebGL scene. The README lists algorithm visualizations, 3D animations, charts and diagrams, and interactive widgets such as forms and math plots as the target outputs. The audience is therefore narrow and specific. This is for engineers building an assistant where explanation quality depends on visual structure, and who are willing to run a Python agent service and a Next.js frontend side by side. It is not for teams that want a component library they can npm install into an existing React app. The README calls the repository an open-source showcase, and the three-package monorepo layout bears that out: you are meant to read it, run it, and copy the patterns into your own product, with docs/bring-to-your-app.md as the intended exit ramp.

generateSandboxedUi streams the document in a fixed parameter order

The mechanism is the most interesting part of the project and the part most likely to be misread. When the CopilotKit runtime has openGenerativeUI enabled, it exposes a canonical tool named generateSandboxedUi. The agent does not return a finished HTML string. It returns ordered streaming parameters: initialHeight, then placeholderMessages, then css, then html, then jsFunctions, then jsExpressions. That ordering is not cosmetic. Because html arrives before the JavaScript, the frontend can render markup progressively and only attach behaviour at the end, which is what makes the live preview possible. On the runtime side, OpenGenerativeUIMiddleware translates the streaming tool call into open-generative-ui activity events. The frontend subscribes to those events through renderActivityMessages and morphs each partial update into a preview iframe using Idiomorph, so the frame is patched rather than rebuilt and the content does not flicker between chunks. Once streaming completes, the final websandbox iframe boots with the shared design-system CSS and a CDN importmap injected. The generated UI talks back to the host through sandbox functions named sendPrompt and openLink, which the README describes as Zod-validated, and a ResizeObserver inside the iframe reports content height continuously so the frame can autosize. Note the trust boundary this creates: model-authored JavaScript runs in the iframe and is allowed to call back into the host, so the Zod schemas on those two functions are the contract that matters, not the sandbox attribute alone.

Skills are files on disk, loaded only when the agent decides it needs them

The agent is built on LangChain Deep Agents via create_deep_agent, and the design choice worth noting is that visualization instructions are not stuffed into the system prompt. They live as SKILL.md files under apps/agent/skills/ and are pulled in on demand, a pattern the README calls progressive disclosure. Three skills ship in the repository: advanced-visualization for UI mockups, dashboards, Chart.js and generative art; master-playbook for response philosophy, decision trees and narration patterns; and svg-diagrams for SVG generation rules, component patterns and diagram types. Deep Agents also supplies built-in planning through write_todos, filesystem tools, and sub-agent support. The practical consequence is that adding a new output category means adding a directory with a SKILL.md rather than editing a prompt that has already grown unwieldy. The cost is that skill selection becomes a model decision, so a weak model may simply not load the skill it needed. The README also includes a decision matrix mapping user intent to output type and technology, for example a physical explanation of how something works maps to an illustrative SVG diagram, while an abstract explanation maps to an interactive explainer built from HTML and inline SVG. That matrix is the kind of artefact that is easy to skip and then rediscover after your agent has produced its fourth unnecessary pie chart.

Getting it running takes three commands and one API key

The quick start is short. Run make setup to install dependencies and create the .env template, edit apps/agent/.env with a real Anthropic API key, then run make dev to start the frontend, the agent and the MCP server together. The app listens on http://localhost:3000 and the agent on http://localhost:8123. Individual targets exist if you want to run pieces separately: make dev-app for the Next.js frontend only, make dev-agent for the LangGraph agent only, make dev-mcp for the MCP server only, plus make build, make lint, make clean and make help. The same commands are reachable through pnpm directly, for example pnpm dev:app and pnpm dev:agent. Model selection is controlled by the LLM_MODEL variable in the same .env file. The default is claude-fable-5, with claude-opus-4-6 listed as a strong alternative. Setting LLM_MODEL to a gpt-* name routes the request to OpenAI and requires OPENAI_API_KEY instead. For anything else, the README points at apps/agent/src/model.py as the place to swap the chat model, with docs/bring-to-your-app.md covering the wider integration. One caveat on the model table: the default model name claude-fable-5 does not correspond to any Anthropic model identifier I can confirm, so treat the table as the repository states it and check apps/agent/src/model.py for the value that is actually passed to the client before you assume the default will resolve.

The MCP server exposes the design system to clients that never run your app

apps/mcp is a standalone Model Context Protocol server, and it is the part of the repository with the widest reach because it does not require the Next.js frontend at all. It exposes three things: an assemble_document tool that wraps HTML fragments with the full design-system CSS and the bridge JavaScript and returns an iframe-ready document; skill resources browsable through skills://list and skills://{name}; and prompt templates pre-composed for widgets, SVG diagrams and advanced visualizations. Wiring it into Claude Desktop is a stdio configuration with command node, args ["dist/stdio.js"] and cwd pointing at your apps/mcp directory. For Claude Code or any HTTP client, run cd apps/mcp && pnpm dev and register the endpoint as http://localhost:3100/mcp in .mcp.json under the key openGenerativeUI. The consequence is that the same visual vocabulary the demo agent uses becomes available inside an editor, which is a genuinely different distribution model from the chat app. The limitation is that assemble_document returns a document; it does not render it. A client that cannot display HTML in a sandboxed frame gets a string and nothing more, so the usefulness of this server is bounded by the host application's rendering surface. The README directs you to apps/mcp/README.md for full configuration, Docker deployment and the API reference, and that file is where the resource and prompt schemas presumably live.

A strong model is a hard dependency, not a tuning knob

This is the constraint that decides whether the project is usable for you. The README states plainly that generative UI demands high-capability models that can produce complex, well-structured HTML and SVG in a single pass, and that smaller or weaker models will produce broken layouts, missing interactivity, or incomplete visualizations. That is a stronger claim than the usual advice to use a capable model, because the failure mode is not degraded prose. It is a half-closed div and a chart that never draws. Two further consequences follow. First, latency and cost scale with the size of the generated document, since the model is emitting CSS, markup and JavaScript token by token inside a chat turn. Second, the streaming parameter order means a malformed early chunk can poison the preview before the agent has finished, so error handling around the activity renderer matters more than it would for plain text streaming. The project is also the wrong tool when the correct answer is a fixed component. If you already know that a refund request should render as a form with four fields, a hand-written React component registered through useComponent is cheaper, faster and testable. The README itself shows that pattern for pie charts and bar charts, which is a useful signal that generative rendering is meant for the open-ended cases, not for everything.

CopilotKit's own useComponent is the alternative, and the difference is who writes the markup

The clearest comparison is inside the same repository. CopilotKit supports several rendering patterns, and the README tabulates them: openGenerativeUI with renderActivityMessages for streaming sandboxed widgets through generateSandboxedUi; useComponent for generative UI such as pie and bar charts; useFrontendTool for a theme toggle; useHumanInTheLoop for a meeting scheduler; and useDefaultRenderTool for tool execution status. The difference between the first two is where the markup originates. With useComponent, you write the React component and the model's job is reduced to choosing it and filling its props, so the output is typed, styled by your own CSS and covered by your own tests. With openGenerativeUI, the model writes the markup, the CSS and the JavaScript, and your design system is injected into the iframe rather than compiled into the bundle. That buys unbounded output variety at the cost of predictability, and it is why the two patterns coexist rather than one replacing the other. If your product needs a fixed set of visual answers, useComponent is the better fit. If the set of useful visuals is genuinely open, the sandboxed route is the only one that does not require you to anticipate every request in advance.

Maintenance cost, licence, and what to check before you build on it

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are preserved. That is a permissive starting point, but it says nothing about the services the project depends on. The Anthropic API key, the OpenAI key if you route through gpt-* models, and the CDN importmap injected into the sandbox are all external dependencies with their own terms and their own availability, and the importmap in particular means the generated widget may load third-party code at runtime. This is not legal advice; if the generated UI ends up in front of customers, have someone review both the licence text and the third-party terms. On maintenance, the material I have shows no retrieved releases, so there is no version history to reason about and no changelog to consult. The stack is also moving fast on its own: Next.js 16, React 19, Tailwind 4 and CopilotKit v2 in the frontend, with a Python agent service alongside. Upgrades will come from four directions at once, and the repository is a showcase, which usually means the demo path is maintained more carefully than the integration path. Budget for reading source rather than release notes. The concrete next step is to run make setup and make dev, put one prompt through the app, and watch whether the activity renderer survives a deliberately awkward request such as a three-dimensional scene with interactive controls. That single run tells you more about whether your model budget and your latency tolerance can carry this pattern than any amount of reading.

Editorial conclusion

Adopt it if you are building an agent product where the answer is a diagram, a chart or a small interactive widget, and you already accept a hosted frontier model in the loop. Do not adopt it if you need deterministic output, offline operation, or a cheap per-request bill, because the README is explicit that weaker models produce broken layouts and incomplete visualizations. Before committing, verify three things in your own checkout: that apps/agent/.env holds a working Anthropic key, that your chosen LLM_MODEL appears in the supported table, and that the sandbox bridge functions you intend to expose (sendPrompt, openLink) match the Zod schemas your frontend validates against.

Official sources

  1. CopilotKit/OpenGenerativeUI on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Community notes

Community notes