微信扫码
添加专属顾问
我要投稿
想让AI直接渲染你的React组件,而不仅仅是输出文字?CopilotKit帮你实现真正的生成式UI。核心内容:1. AI接入React应用的现状与局限性2. CopilotKit的Controlled模式与核心API3. 实现生成式UI的具体步骤与优势
你有没有注意到一件事:大多数「AI 接入 React 应用」的教程,最终都止步于同一个地方——对话框里显示一段文字。
问天气,返回「北京今天晴,气温23度」。
问数据,返回一段 Markdown 表格。
问任务状态,返回一坨 JSON。
这没什么问题,能用。但跟你精心设计的 React 组件比起来,差了一个维度。你的 <WeatherCard> 有动画、有图标、有交互——AI 却连碰都碰不到,只能在旁边说话。
CopilotKit 要解决的,就是这个问题。
接过 LLM API 的都知道,模型返回的是文字流。你拿到文字,渲染成 Markdown,最多高亮一下代码块,这就是 99% 的 AI 聊天接入方案。
这个方案的上限很低:
用户问「帮我看下销售数据」,你能返回一段描述,或者一个纯文本表格。但你不能直接弹出一个带筛选、排序、图表的 <SalesDashboard> 组件——因为 AI 不知道你有这个组件,更不知道怎么调它。
本质上,AI 只是在你应用的旁边说话,没有真正进入你的应用。
CopilotKit 换了一个思路:把你的 React 组件注册成 AI 可以调用的「工具」,AI 决定什么时候调、传什么数据,你的组件负责渲染。
在讲具体代码之前,先把概念理清楚,因为「Generative UI」这个词现在被用烂了,不同地方说的其实是不同的东西。
根据 CopilotKit 官方的分类(来自其 generative-ui 仓库),有三种模式:
| 模式 | 控制权 | 代表协议 |
| Controlled(受控) | 开发者写组件,AI 选何时渲染 | AG-UI |
| Declarative(声明式) | AI 生成组件描述,客户端渲染 | A2UI |
| Open-ended(开放式) | AI 生成完整 UI(HTML/代码) | MCP Apps |
这三种模式是一个「控制权 vs 自由度」的光谱。
最右边(Open-ended) 自由度最高,AI 生成什么就渲染什么,但风险高、样式不可控、安全边界模糊。
最左边(Controlled) 最稳,你写好所有组件,AI 只是决定「现在该渲染哪个、传什么数据」——布局、样式、交互全在你掌控里。
这篇聚焦 Controlled 模式,对应 CopilotKit 的 useFrontendTool hook。这是最适合生产环境的用法,也是最容易上手的起点。
useFrontendTool 做的事很简单:把一个 React 组件注册成 AI 可以触发的工具。
安装依赖:
npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime最小可用代码:
import { useFrontendTool } from "@copilotkit/react-core";import { z } from "zod";function WeatherWidget() {useFrontendTool({name: "get_weather",description: "获取某个城市的当前天气,并以卡片形式展示",parameters: z.object({location: z.string().describe("城市名称,例如:北京、上海"),}),handler: async ({ location }) => {// 这里调你自己的天气 APIconst data = await fetchWeather(location);return data;},render: ({ status, args, result }) => {// inProgress:AI 正在调用中if (status === "inProgress" || status === "executing") {return <WeatherSkeleton location={args?.location} />;}// complete:有结果了,渲染真实组件if (status === "complete" && result) {return <WeatherCard {...result} />;}return null;},});return null; // 这个组件本身不渲染任何东西}
三个关键字段:
handler:AI 调用工具时执行的逻辑,运行在浏览器里(不是服务端),可以直接访问前端状态•render:根据执行状态渲染不同的 UI,status 有 inProgress / executing / complete 三种•description:AI 靠这个判断什么时候该调这个工具,写清楚,别写废话光看 API 不够,把整个链路串起来:
第一步:Provider 包裹应用
// app/layout.tsx(Next.js 示例)import { CopilotKit } from "@copilotkit/react-core";export default function RootLayout({ children }) {return (<CopilotKit runtimeUrl="/api/copilotkit">{children}</CopilotKit>);}
第二步:后端 runtime 路由
// app/api/copilotkit/route.tsimport { CopilotRuntime, GoogleGenerativeAIAdapter } from "@copilotkit/runtime";const runtime = new CopilotRuntime();export const POST = async (req: Request) => {const { handleRequest } = runtime.process({serviceAdapter: new GoogleGenerativeAIAdapter({model: "gemini-2.0-flash",}),});return handleRequest(req);};
CopilotKit 支持 OpenAI、Anthropic、Google 等主流模型,换 adapter 就行。
第三步:注册工具 + 渲染聊天界面
// components/ChatPanel.tsximport { CopilotChat } from "@copilotkit/react-ui";import "@copilotkit/react-ui/styles.css";export function ChatPanel() {// 注册天气工具useFrontendTool({ /* 上面的配置 */ });return (<CopilotChatinstructions="你是一个智能助手,当用户询问天气时,调用 get_weather 工具展示天气卡片。"labels={{ title: "AI 助手", initial: "有什么需要帮忙的?" }}/>);}
就这三步。用户在聊天框问「北京今天天气怎么样」,AI 识别到意图 → 调 get_weather 工具 → handler 取数据 → render 拿到数据渲染 <WeatherCard>。用户看到的不是一段文字,是一个真实的天气组件。
render 接收的 status 是整个体验质量的关键,很多人只用了 complete 就结束了,其实 inProgress 更重要。
render: ({ status, args, result }) => {// 工具调用中:args 已有,result 还没有// 这时候 args.location 已经可以用了,可以先渲染 loading 态if (status === "inProgress") {return <div>正在获取 {args?.location} 的天气...</div>;}// 工具执行中(handler 在跑)if (status === "executing") {return <WeatherSkeleton />;}// 完成if (status === "complete" && result) {return <WeatherCard {...JSON.parse(result)} />;}return null;},
inProgress 阶段,AI 已经决定要调这个工具、参数也知道了,但 handler 还没执行完。这时候你可以先把城市名展示出来,让用户感觉响应很快——这和普通 loading 转圈体验差很多。
这是 useFrontendTool 被低估的优点:你现有的组件一行不用改。
你已经有 <DataTable>、<Chart>、<TaskCard> 这些组件——只要把它们包进 useFrontendTool 的 render 里,AI 就能调用它们。不需要专门为 AI 重写一套组件,也不需要改变组件的 props 结构。
// 你已有的组件,不用改function SalesChart({ data, period, region }) { /* ... */ }// 只需要在 useFrontendTool 里引用它useFrontendTool({name: "show_sales_chart",description: "显示销售数据图表,支持按时间段和地区筛选",parameters: z.object({period: z.enum(["day", "week", "month"]),region: z.string().optional(),}),handler: async ({ period, region }) => fetchSalesData(period, region),render: ({ status, result }) =>status === "complete" ? <SalesChart data={result} /> : <ChartSkeleton />,});
handler 运行在浏览器端,这是好事,但也意味着它能访问你的前端 state——你得想清楚哪些 state 该暴露、哪些不该。
如果你的 handler 里有 const { user } = useAuthStore() 这种调用,它读到的是当前登录用户的数据。这当然可以用,但如果你同时也在 description 里写了「可以查看任意用户的数据」,那就有问题了——AI 可能被诱导调用本不该调的逻辑。
实践规则:handler 里的逻辑跟普通 React 事件处理一样对待,该鉴权的鉴权,该边界检查的检查,不要因为「是 AI 调的」就放松警惕。
说实话,不是所有 React 应用都需要 CopilotKit。
适合:
不适合:
CopilotKit 在 2026年完成了 $2700万融资(据行业报道),AG-UI 协议也在 Vercel、LangChain 等生态里逐步被采用。它背后的 AG-UI 和 Google 主导的 A2UI 是同一个问题的不同解法:AI 如何和前端界面安全地双向通信。
目前来看,CopilotKit 的 Controlled 模式(useFrontendTool)是最成熟、最适合生产落地的方案,因为控制权在开发者手里。如果你想探索更开放的模式(AI 直接生成组件描述),可以看他们的 A2UI 集成——但那个还在早期,暂时不建议生产使用。
一句话:useFrontendTool 把你的 React 组件变成 AI 可以调用的工具,AI 控制触发时机,你控制渲染结果。
核心三步:
<CopilotKit> Provider 包裹应用2.建后端 runtime 路由(换个 adapter 就能换模型)3.用 useFrontendTool 注册组件,写好 handler 和 render如果你的 React 应用现在的 AI 能力还停在「聊天框里显示文字」,CopilotKit 值得认真评估一下。
官方仓库有完整的 demo 示例:https://github.com/CopilotKit/generative-ui
你现在的应用是怎么接 AI 的?用的是哪个框架?评论区聊聊,看看大家的方案有什么不同。
参考来源: 本文核心内容来自 CopilotKit 官方仓库、文档及行业公开报道,文中代码基于官方示例整理:
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-05-14
LinkedIn高管AI时代生存指南:别卷了,AI时代拼的是做人
2026-05-14
如何用AI提效,又不把脑子用废?
2026-05-11
我终于理解了 datawork:它不是一个 Agent,而是个人的 AI 工作台、上下文中心
2026-05-09
我制作了 Feishu2MD 的桌面应用,帮助你快速批量导出飞书文档
2026-05-07
十年老技术开发的 AI Agent 探索之路
2026-04-25
OpenAI 出圈的「AI 屏幕记忆」,我找到了关于它的最佳答案
2026-04-22
别只盯落地场景了,这5个AI价值模型才是关键!
2026-04-16
从聊天窗口到多 Agent 控制台:一次 AI 编程协作范式的转移
2026-02-24
2026-02-28
2026-02-15
2026-03-21
2026-03-19
2026-02-19
2026-02-19
2026-03-03
2026-02-23
2026-03-10