docs/content/docs/(root)/generative-ui/open-generative-ui.mdx
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
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:
<script> tagsEnable Open Generative UI by setting openGenerativeUI: true in your runtime configuration. That's it — the middleware handles the rest.
```npm
npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime
```
```typescript title="app/api/copilotkit/route.ts"
import {
CopilotRuntime,
createCopilotEndpoint,
InMemoryAgentRunner,
} from "@copilotkit/runtime";
import { BuiltInAgent } from "@copilotkit/runtime/v2";
import { handle } from "hono/vercel";
const agent = new BuiltInAgent({
model: "openai/gpt-5.4",
prompt: "You are a helpful assistant.",
});
const runtime = new CopilotRuntime({
agents: { default: agent },
runner: new InMemoryAgentRunner(),
// Enable Open Generative UI
openGenerativeUI: true,
});
const app = createCopilotEndpoint({
runtime,
basePath: "/api/copilotkit",
});
export const GET = handle(app);
export const POST = handle(app);
```
You can also pass options instead of `true`:
```typescript
openGenerativeUI: {
instructions: "Always use a dark color scheme.",
}
```
The `instructions` string is appended to the tool description, letting you customize what the agent generates.
```tsx title="app/page.tsx"
"use client";
import { CopilotKit } from "@copilotkit/react-core/v2";
import { CopilotChat } from "@copilotkit/react-core/v2";
import "@copilotkit/react-ui/v2/styles.css";
export default function Page() {
return (
<CopilotKit runtimeUrl="/api/copilotkit">
<CopilotChat />
</CopilotKit>
);
}
```
No special frontend prop is needed — Open Generative UI rendering is built in.
That's it. Ask the agent to "build a calculator" or "show me a bar chart of sales data" and it will generate and stream the UI live.
Sandbox functions let the generated UI call back into your host application. This enables two-way communication — for example, a generated settings panel that can toggle your app's theme, or a product card that adds items to your cart.
Pass sandboxFunctions to the openGenerativeUI prop on CopilotKit:
"use client";
import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2";
import "@copilotkit/react-ui/v2/styles.css";
import { useState } from "react";
import { z } from "zod";
export default function Page() {
const [theme, setTheme] = useState<"light" | "dark">("light");
return (
<CopilotKit
runtimeUrl="/api/copilotkit"
openGenerativeUI={{
sandboxFunctions: [
{
name: "setTheme",
description: "Switch the app theme between light and dark mode.",
parameters: z.object({
mode: z.enum(["light", "dark"]).describe("The theme mode to set"),
}),
handler: async ({ mode }) => {
setTheme(mode);
return `Theme set to ${mode}`;
},
},
],
}}
>
<CopilotChat />
</CopilotKit>
);
}
Each sandbox function has:
| Property | Type | Description |
|---|---|---|
name | string | Function name, callable from the sandbox |
description | string | Tells the agent what this function does |
parameters | Zod schema | Validates arguments passed from the sandbox |
handler | (args) => Promise<string> | Runs in the host app, returns a result string |
Inside the generated UI, the agent calls these functions via:
// Inside the sandboxed iframe
const result = await Websandbox.connection.remote.setTheme({ mode: "dark" });
The function descriptions are automatically included in the agent's context, so it knows which functions are available and how to use them.
The agent generates parameters in a specific order optimized for the user experience:
placeholderMessages — shown immediately while generatingcss — all styles generated first; the preview starts once CSS is completehtml — streams live into the preview as it's generatedjsFunctions — reusable helper functions injected before expressionsjsExpressions — executed one by one; the user sees each take effectThe middleware parses the tool call arguments incrementally and emits activity events as each parameter completes, so the frontend can show progressive updates.
The sandboxed iframe can load external libraries from CDNs. Include <script> or <link> tags in the generated HTML <head>:
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="myChart"></canvas>
</body>
Libraries like Chart.js, D3, Three.js, x-data-spreadsheet, and any other CDN-hosted library work out of the box.
If you prefer to apply the middleware to specific agents rather than globally, use OpenGenerativeUIMiddleware directly:
import { OpenGenerativeUIMiddleware } from "@copilotkit/runtime";
const agent = new BuiltInAgent({
model: "openai/gpt-5.4",
prompt: "You are a helpful assistant.",
}).use(
new OpenGenerativeUIMiddleware({
instructions: "Use a modern, minimal design.",
}),
);