generative-ui
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseassistant-ui Generative UI
assistant-ui Generative UI
Always consult assistant-ui.com/llms.txt for the latest API.
Generative UI inverts the usual tool-rendering relationship. Instead of one hand-written component per tool call, you ship a vocabulary of components and let something assemble a tree from it: either the model, through the tool, or your backend, through a message part or a LangGraph event. ships a default vocabulary of 27 components (cards, facts, tables, charts, forms, controls) plus converters that turn the same tree into Slack Block Kit, a Microsoft Teams Adaptive Card, or an A2UI surface, so a composition built once can render in the browser and outside it.
present@assistant-ui/react-generative-ui请始终查阅 assistant-ui.com/llms.txt 获取最新API。
Generative UI 颠覆了常规的工具渲染关系。无需为每个工具调用手写单独组件,你只需提供一套组件词汇表,由模型通过工具或后端通过消息片段、LangGraph事件来组装组件树。内置了包含27个组件的默认词汇表(卡片、事实展示、表格、图表、表单、控件等),同时提供转换器可将同一组件树转换为Slack Block Kit、Microsoft Teams自适应卡片或A2UI界面,一次构建的组件组合可同时在浏览器及外部平台渲染。
present@assistant-ui/react-generative-uiReferences
参考资料
- ./references/vocabulary.md -- the 27 default components and how to add your own with
defineGenerativeComponents - ./references/actions.md -- dispatch,
$action, and thecreateActionRegistryshapes interactive components send back$input - ./references/renderers.md -- and its allowlist, the Slack and Teams converters, and why the two spec shapes do not interchange
MessagePrimitive.GenerativeUI - ./references/a2ui-openui.md -- A2UI surfaces over AG-UI and the third-party OpenUI integration
- ./references/tokens.md -- the shared token arrays and how to restyle or override the vocabulary
- ./references/vocabulary.md -- 27个默认组件介绍,以及如何使用添加自定义组件
defineGenerativeComponents - ./references/actions.md -- 分发、
$action,以及交互式组件返回的createActionRegistry结构$input - ./references/renderers.md -- 及其允许列表、Slack和Teams转换器,以及两种规范结构无法互换的原因
MessagePrimitive.GenerativeUI - ./references/a2ui-openui.md -- 基于AG-UI的A2UI界面,以及第三方OpenUI集成
- ./references/tokens.md -- 共享令牌数组,以及如何重新样式化或覆盖组件词汇表
Which generative UI pattern?
选择哪种Generative UI模式?
Two questions separate the patterns: does the model compose the layout or do you bind it ahead of time, and does the UI originate from a tool call or from a part your backend emits.
| Pattern | API | Best for |
|---|---|---|
The | | The model composes dashboards, cards, and layouts from a vocabulary you ship |
| Tool UI | toolkit | A widget tied to one tool call you already know about |
| Generative UI primitive | | A backend that already emits |
| LangGraph data UI | | LangGraph agents emitting UI on the LangGraph stream, see assistant-ui.com/docs/runtimes/langgraph/generative-ui |
| OpenUI | | Already invested in the OpenUI ecosystem and its component kit |
The first two are tool-driven, so the model decides when UI appears; the LangGraph row is backend-driven, so your agent does. and the generative UI primitive both take a JSON component tree, but in non-interchangeable shapes, see Spec shape differences. A tree built for is also the shape the Slack, Teams, and A2UI converters accept.
presentpresent区分不同模式可通过两个问题:是由模型组合布局,还是提前绑定布局;UI是源自工具调用,还是后端生成的消息片段。
| 模式 | API | 最佳适用场景 |
|---|---|---|
| | 模型从你提供的词汇表中组合仪表盘、卡片及布局 |
| 工具UI | toolkit | 与已知工具调用绑定的小部件 |
| Generative UI原语 | | 已生成 |
| LangGraph数据UI | | LangGraph智能体在LangGraph流中输出UI,详见 assistant-ui.com/docs/runtimes/langgraph/generative-ui |
| OpenUI | | 已投入OpenUI生态系统及其组件库的场景 |
前两种是工具驱动,由模型决定UI何时显示;LangGraph模式是后端驱动,由智能体控制。和Generative UI原语均接收JSON组件树,但结构不可互换,详见 规范结构差异。为构建的组件树同样适用于Slack、Teams和A2UI转换器。
presentpresentQuick start
快速开始
Install the package, add the styled element, and enable the compiler for your framework:
"use generative"bash
npm install @assistant-ui/react-generative-ui
npx assistant-ui@latest add generative-uits
import { withAui } from "@assistant-ui/next";
export default withAui({
/* your Next config */
});Vite and TanStack Start use from (); Expo and bare React Native use in . The directive lets one file declare tools that both the browser and your server route import: the compiler strips the browser-only halves from the server build and the schemas from the client build.
aui()@assistant-ui/viteplugins: [aui({ ... })]const { withAui } = require("@assistant-ui/metro");metro.config.jsJSONGenerativeUIpresenttsx
"use generative";
import { defineToolkit } from "@assistant-ui/react";
import {
JSONGenerativeUI,
defaultGenerativeUILibrary,
} from "@assistant-ui/react-generative-ui";
const generative = new JSONGenerativeUI({
library: defaultGenerativeUILibrary,
});
export default defineToolkit({
present: generative.present({ display: "standalone" }),
});display: "standalone"Register the toolkit on the client through , and set so the run continues once the frontend tool resolves:
AuiConfigsendAutomaticallyWhentsx
"use client";
import { AssistantRuntimeProvider, AuiConfig, Tools } from "@assistant-ui/react";
import { useChatRuntime } from "@assistant-ui/ai-sdk";
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
import toolkit from "./toolkit";
export function MyRuntimeProvider({
children,
}: {
children: React.ReactNode;
}) {
const runtime = useChatRuntime({
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
});
const config = AuiConfig({ tools: Tools({ toolkit }) });
return (
<AssistantRuntimeProvider runtime={runtime} config={config}>
{children}
</AssistantRuntimeProvider>
);
}presentsendAutomaticallyWhenThe route imports the same toolkit module. The compiler resolves that import to the server build, so only the schemas cross over and no browser code enters your server bundle:
ts
import { openai } from "@ai-sdk/openai";
import { AISDKToolkit } from "@assistant-ui/ai-sdk";
import { convertToModelMessages, stepCountIs, streamText } from "ai";
import toolkit from "@/app/toolkit";
const aiToolkit = new AISDKToolkit({ toolkit });
export async function POST(req: Request) {
const { messages, tools } = await req.json();
const result = streamText({
model: openai("gpt-5.6-luna"),
messages: await convertToModelMessages(messages),
stopWhen: stepCountIs(10),
tools: await aiToolkit.tools({ frontend: tools }),
});
return result.toUIMessageStreamResponse();
}When no backend of yours imports the toolkit module, for example a cloud-hosted run, compile with so the client keeps every schema uploadable, including 's:
backendless: truepresentts
export default withAui({ ...yourConfig, aui: { backendless: true } });安装包、添加样式元素,并为你的框架启用编译器:
"use generative"bash
npm install @assistant-ui/react-generative-ui
npx assistant-ui@latest add generative-uits
import { withAui } from "@assistant-ui/next";
export default withAui({
/* 你的Next配置 */
});Vite和TanStack Start使用中的();Expo和原生React Native在中使用。该指令允许单个文件声明浏览器和服务器路由均可导入的工具:编译器会从服务器构建中剥离仅浏览器端的代码,从客户端构建中剥离模式定义。
@assistant-ui/viteaui()plugins: [aui({ ... })]metro.config.jsconst { withAui } = require("@assistant-ui/metro");JSONGenerativeUIpresenttsx
"use generative";
import { defineToolkit } from "@assistant-ui/react";
import {
JSONGenerativeUI,
defaultGenerativeUILibrary,
} from "@assistant-ui/react-generative-ui";
const generative = new JSONGenerativeUI({
library: defaultGenerativeUILibrary,
});
export default defineToolkit({
present: generative.present({ display: "standalone" }),
});display: "standalone"通过在客户端注册toolkit,并设置以便前端工具解析后继续运行:
AuiConfigsendAutomaticallyWhentsx
"use client";
import { AssistantRuntimeProvider, AuiConfig, Tools } from "@assistant-ui/react";
import { useChatRuntime } from "@assistant-ui/ai-sdk";
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
import toolkit from "./toolkit";
export function MyRuntimeProvider({
children,
}: {
children: React.ReactNode;
}) {
const runtime = useChatRuntime({
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
});
const config = AuiConfig({ tools: Tools({ toolkit }) });
return (
<AssistantRuntimeProvider runtime={runtime} config={config}>
{children}
</AssistantRuntimeProvider>
);
}presentsendAutomaticallyWhen路由导入同一toolkit模块。编译器会将该导入解析为服务器构建版本,因此仅模式定义会跨端传输,浏览器代码不会进入服务器包:
ts
import { openai } from "@ai-sdk/openai";
import { AISDKToolkit } from "@assistant-ui/ai-sdk";
import { convertToModelMessages, stepCountIs, streamText } from "ai";
import toolkit from "@/app/toolkit";
const aiToolkit = new AISDKToolkit({ toolkit });
export async function POST(req: Request) {
const { messages, tools } = await req.json();
const result = streamText({
model: openai("gpt-5.6-luna"),
messages: await convertToModelMessages(messages),
stopWhen: stepCountIs(10),
tools: await aiToolkit.tools({ frontend: tools }),
});
return result.toUIMessageStreamResponse();
}当你的后端未导入toolkit模块时(例如云托管运行环境),需使用编译,以便客户端保留所有可上传的模式,包括的模式:
backendless: truepresentts
export default withAui({ ...yourConfig, aui: { backendless: true } });Style it
样式定制
npx assistant-ui@latest add generative-uicomponents/assistant-ui/elements/generative-ui.tsxstyledGenerativeUILibrary"use client""use generative"data-aui上述执行的会安装内置样式表及,该文件导出:将默认纯文本渲染器替换为真实markdown渲染器的27个组件。它是模块,因此在的toolkit文件中引入需遵循下方注意事项中的客户端模块规则;具体覆盖模式、样式钩子及令牌数组详见 tokens.md。
npx assistant-ui@latest add generative-uicomponents/assistant-ui/elements/generative-ui.tsxstyledGenerativeUILibrary"use client""use generative"data-auiBeyond present
进阶功能
- Extend the vocabulary with your own components, or read back a model-produced tree for display: vocabulary.md.
- Let rendered nodes call back into your app through : actions.md.
$action - Render a message part your backend already emits, with
generative-uiand a consumer-provided allowlist: renderers.md.MessagePrimitive.GenerativeUI - Post a tree to Slack or Microsoft Teams, or render an A2UI surface over AG-UI, or wire the third-party OpenUI integration: renderers.md and a2ui-openui.md.
- 使用自定义组件扩展词汇表,或读取模型生成的组件树进行展示:vocabulary.md。
- 通过让渲染节点回调你的应用:actions.md。
$action - 渲染后端已生成的消息片段,使用
generative-ui及用户提供的允许列表:renderers.md。MessagePrimitive.GenerativeUI - 将组件树发布到Slack或Microsoft Teams,或在AG-UI上渲染A2UI界面,或接入第三方OpenUI集成:renderers.md和a2ui-openui.md。
Common Gotchas
常见问题
present- is a frontend tool; without
presentonsendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls, the run never continues after it resolves.useChatRuntime
The model never learns about on a cloud-hosted backend
present- The client build skips uploading frontend and human schemas because it assumes your backend imported the same toolkit module. Compile with when no server of yours does.
aui: { backendless: true }
styledGenerativeUILibrary"use generative"- It is a module. A
"use client"file may reference it only as the inline"use generative"value inside arendercall, never as a spread, a top-level constant, or thedefineGenerativeComponentsoption directly. Passing it straight tolibraryworks only in a plain file with nolibrarydirective; see tokens.md."use generative"
A message part renders nothing
generative-ui- The default shadcn does not wire
Thread. Opt in explicitly in your message renderer; see renderers.md.MessagePrimitive.GenerativeUI
Unknown component name: silent drop versus thrown error
- The tool path drops an unrecognized
presentand warns in development. The generative UI primitive throws a typed$typeunless you passGenerativeUIRenderError. Neither boundary constrains the props those components receive; validateFallback/hrefvalues yourself and never forward agent-supplied props intosrc.dangerouslySetInnerHTML
Slack or Teams output does not match the browser
- Conversion is total but lossy: read the returned array. Only a
warningstree built for$typeconverts; the primitive'spresentshape has no Slack, Teams, or A2UI converter.{ component, props }
useChatRuntimegenerative-ui- The AI SDK maps tool results to parts, not
tool-callparts. Bridge with agenerative-uitool whose result you parse into a spec yourself (the docs call that helperrender_gui; it is not a package export); see renderers.md.parseRenderGuiResult
present- 是前端工具;若
present未设置useChatRuntime,解析后运行不会继续。sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls
云托管后端中模型无法识别
present- 客户端构建会跳过上传前端和人工模式,因为默认假设你的后端导入了同一toolkit模块。当你的服务器未导入时,需使用编译。
aui: { backendless: true }
styledGenerativeUILibrary"use generative"- 它是模块。
"use client"文件仅可在"use generative"调用的内联defineGenerativeComponents值中引用它,不可作为展开值、顶层常量或直接作为render选项。仅在无library指令的普通文件中,才可直接将其传入"use generative";详见 tokens.md。library
generative-ui- 默认的shadcn 未关联
Thread。需在消息渲染器中显式启用;详见 renderers.md。MessagePrimitive.GenerativeUI
未知组件名称:静默丢弃还是抛出错误
- 工具路径会丢弃未识别的
present并在开发环境中发出警告。Generative UI原语会抛出类型化的$type,除非你传入GenerativeUIRenderError。两者均不会限制组件接收的属性;请自行验证Fallback/href值,切勿将智能体提供的属性传入src。dangerouslySetInnerHTML
Slack或Teams输出与浏览器不一致
- 转换是完整但有损耗的:请读取返回的数组。仅为
warnings构建的present组件树可被转换;原语的$type结构无Slack、Teams或A2UI转换器。{ component, props }
useChatRuntimegenerative-ui- AI SDK会将工具结果映射为片段,而非
tool-call片段。需通过generative-ui工具桥接,自行将其结果解析为规范(文档中称该辅助工具为render_gui,并非包导出);详见 renderers.md。parseRenderGuiResult
Related Skills
相关技能
- tools -- toolkit authoring, the compiler, and tool UI for a widget tied to one specific tool call
"use generative" - elements -- installing the styled element and the rest of the catalog
generative-ui - primitives -- and the other unstyled building blocks
MessagePrimitive - runtime -- ,
AuiConfig, and the rest of the config plumbingTools
- tools -- toolkit编写、编译器,以及与特定工具调用绑定的工具UI
"use generative" - elements -- 安装样式元素及其他组件目录
generative-ui - primitives -- 及其他未样式化基础组件
MessagePrimitive - runtime -- 、
AuiConfig及其他配置相关内容Tools