---
title: "Open Generative UI"
icon: "lucide/Code"
description: "Let agents generate fully interactive HTML/CSS/JS UIs that stream live into the chat."
snippet_cell: open-gen-ui
---

## What is this?

Open Generative UI lets the agent generate complete, sandboxed UI on the fly
(HTML, CSS, and JavaScript) and stream it live into the chat. The user sees
the interface build in real time: styles apply first, then HTML streams in
progressively, and finally JavaScript expressions execute one by one.

Key benefits:

- **No predefined components** — the agent creates any UI it needs, on demand
- **Live streaming** — HTML streams into a preview as it's generated
- **CDN libraries** — the generated UI can load Chart.js, D3, Three.js, etc. via `<script>` tags
- **Secure sandboxing** — content runs in an isolated iframe without same-origin access
- **Sandbox functions** — optionally expose host functions to the generated UI for two-way communication

<Callout type="info">
  **Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
</Callout>

<InlineDemo demo="open-gen-ui" />

## Minimal setup

Turning on Open Generative UI takes one flag in the runtime plus a plain
`<CopilotChat />` on the frontend; the built-in activity renderer is
auto-registered by `CopilotKit`, so no extra wiring is needed.

### Enable it in the runtime

Add `OpenGenerativeUIMiddleware` to your runtime configuration:

<Snippet region="minimal-runtime-flag" />

The `OpenGenerativeUIMiddleware` then converts the agent's streamed
`generateSandboxedUi` tool call into `open-generative-ui` activity events,
which the built-in `OpenGenerativeUIActivityRenderer` mounts inside a
sandboxed iframe.

### Drop `<CopilotChat />` into the page

Wrap your app in `CopilotKit` and render `<CopilotChat>` — no extra props needed:

<Snippet region="minimal-provider-setup" />

That's it. Ask the agent "build me a simple greeting card" to see HTML
stream into a sandboxed preview live.

## Advanced: With app tool calling

Sandbox functions let the generated UI call back into your host application
— a generated settings panel can toggle your app's theme, a product card can
push items into your cart, or a data view can ask the host to fetch data the
iframe can't reach directly.

<InlineDemo demo="open-gen-ui-advanced" />

### Runtime is unchanged

The server-side flag is identical to the minimal cell; the advanced
behaviour is a pure frontend addition.

<Snippet region="advanced-runtime-config" cell="open-gen-ui-advanced" />

### Register sandbox functions on the provider

Each sandbox function is a Zod-validated, host-side bridge the agent can
invoke from inside the generated iframe via
`Websandbox.connection.remote.<name>(args)`. The handler runs in the host
page and its description is appended to the agent's context, so the agent
knows which bridges are available when generating HTML/JS.

<Snippet region="sandbox-function-registration" cell="open-gen-ui-advanced" />

<Callout type="info" title="How the sandbox calls you back">
  Inside the generated UI, the agent writes JS that calls
  `await Websandbox.connection.remote.notifyHost({ message: "hi" })`.
  The call is proxied back to the host page, where your `handler` runs
  with the validated args.
</Callout>

### Common use cases

- **Theme toggling** — generated UI controls your app's appearance
- **Cart / state management** — product cards push items into host state
- **Navigation** — generated UI triggers route changes in the host app
- **Data fetching** — sandbox asks the host to fetch data the iframe can't reach directly

## How streaming works

The agent generates the tool call's parameters in an order optimized for the
user experience:

1. **`placeholderMessages`** — shown immediately while generating
2. **`css`** — all styles first; the preview starts once CSS is complete
3. **`html`** — streams live into the preview as it's generated
4. **`jsFunctions`** — reusable helpers injected before expressions
5. **`jsExpressions`** — executed one by one; the user sees each take effect

The middleware parses the tool-call arguments incrementally and emits
activity events as each parameter completes, so the preview updates
progressively.

## Using CDN libraries

The sandboxed iframe can load external libraries from CDNs; just include
`<script>` or `<link>` tags in the generated HTML `<head>`. Chart.js, D3,
Three.js, and any other CDN-hosted library work out of the box.

```html
<head>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
  <canvas id="myChart"></canvas>
</body>
```

<IntegrationGrid path="generative-ui/open-generative-ui" />
