Generative UI
Render structured agent replies in your product.
When Generative UI is enabled for a project, replies can include openui blocks alongside Markdown. Use them for cards, comparisons, checklists, charts, maps, and tabs. Text and code remain Markdown.
Install
npm install @beeuni/sdk zod @openuidev/lang-core@0.3.1
# React:
npm install react
Install the optional peers before importing the parser or React renderer. The root SDK and React hooks do not load these dependencies.
Entry points
| Import | API |
|---|---|
@beeuni/sdk/genui/fence |
Fence detection without the optional peers |
@beeuni/sdk/genui |
Parser, catalog, and Markdown conversion |
@beeuni/sdk/genui/react |
Headless React renderer and default HTML components |
Render a block
Detect the fence in your Markdown renderer with genuiVersionFromClassName(className). A null result means it is an ordinary code block. Load the renderer lazily only when a Generative UI block appears.
import type { ReactNode } from 'react';
import { GenuiBlock, defaultGenuiComponents } from '@beeuni/sdk/genui/react';
import { genuiVersionFromClassName } from '@beeuni/sdk/genui/fence';
type Props = {
code: string;
className?: string;
streaming: boolean;
renderMarkdown: (markdown: string) => ReactNode;
};
function StructuredReply({ code, className, streaming, renderMarkdown }: Props) {
const version = genuiVersionFromClassName(className);
if (version === null) return <pre><code>{code}</code></pre>;
return (
<GenuiBlock
code={code}
version={version}
streaming={streaming}
components={defaultGenuiComponents}
renderMarkdown={renderMarkdown}
/>
);
}
Pass your own components through components, or use defaultGenuiComponents to start. Keep renderMarkdown stable. streaming describes this block: set it to false as soon as its fence closes, even if the reply continues.
For large unfinished nodes, renderPending can reserve space. enabled={false} renders a Markdown fallback. onSettled reports the outcome and timing once per block, without its content.
Plain text and compatibility
Use genuiToMarkdown(text) for text-only hosts. Charts become tables; maps become place lists; tabs and accordions expand. While a reply streams, pass { streaming: true } to avoid a premature truncation notice.
import { genuiToMarkdown } from '@beeuni/sdk/genui';
const markdown = genuiToMarkdown(reply, { streaming: true });
Invalid or unsupported blocks show a fallback instead of executing content. Keep the SDK up to date to support new block types. Checklist selections stay in the component; Beeuni does not save or submit them.
Safety
Blocks contain data, not executable code. Links and image URLs must be absolute http or https URLs. Generated UI cannot run tools or change application state.