你的 React 应用还在让 AI 只输出文字?CopilotKit 可以让它直接渲染组件

你有没有注意到一件事:大多数「AI 接入 React 应用」的教程,最终都止步于同一个地方——对话框里显示一段文字。

问天气,返回「北京今天晴,气温23度」。

问数据,返回一段 Markdown 表格。

问任务状态,返回一坨 JSON。

这没什么问题,能用。但跟你精心设计的 React 组件比起来,差了一个维度。你的 `` 有动画、有图标、有交互——AI 却连碰都碰不到,只能在旁边说话。

CopilotKit 要解决的,就是这个问题。

* * *

## 先说清楚问题在哪

接过 LLM API 的都知道,模型返回的是文字流。你拿到文字,渲染成 Markdown,最多高亮一下代码块,这就是 99% 的 AI 聊天接入方案。

这个方案的上限很低:

**用户问「帮我看下销售数据」**,你能返回一段描述,或者一个纯文本表格。但你不能直接弹出一个带筛选、排序、图表的 `` 组件——因为 AI 不知道你有这个组件,更不知道怎么调它。

本质上,AI 只是在你应用的旁边说话,没有真正进入你的应用。

**CopilotKit 换了一个思路**:把你的 React 组件注册成 AI 可以调用的「工具」,AI 决定什么时候调、传什么数据,你的组件负责渲染。

* * *

## Generative UI 的三种模式

在讲具体代码之前,先把概念理清楚,因为「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:核心 API

`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 }) => {“// 这里调你自己的天气 API“const data = await fetchWeather(location);“return data;“},“render: ({ status, args, result }) => {“// inProgress:AI 正在调用中“if (status === “inProgress” || status === “executing”) {“return ;“}“// complete:有结果了,渲染真实组件“if (status === “complete” && result) {“return ;“}“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 (““{children}““);“}`
**第二步:后端 runtime 路由**

`// app/api/copilotkit/route.ts“import { 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.tsx“import { CopilotChat } from “@copilotkit/react-ui”;“import “@copilotkit/react-ui/styles.css”;“export function ChatPanel() {“// 注册天气工具“useFrontendTool({ /* 上面的配置 */ });“return (““);“}`
就这三步。用户在聊天框问「北京今天天气怎么样」,AI 识别到意图 → 调 `get_weather` 工具 → `handler` 取数据 → `render` 拿到数据渲染 ``。用户看到的不是一段文字,是一个真实的天气组件。

* * *

## render 的状态机值得重点理解

`render` 接收的 `status` 是整个体验质量的关键,很多人只用了 `complete` 就结束了,其实 `inProgress` 更重要。

`render: ({ status, args, result }) => {“// 工具调用中:args 已有,result 还没有“// 这时候 args.location 已经可以用了,可以先渲染 loading 态“if (status === “inProgress”) {“return

正在获取 {args?.location} 的天气…

;“}“// 工具执行中(handler 在跑)“if (status === “executing”) {“return ;“}“// 完成“if (status === “complete” && result) {“return ;“}“return null;“},`
`inProgress` 阶段,AI 已经决定要调这个工具、参数也知道了,但 `handler` 还没执行完。这时候你可以先把城市名展示出来,让用户感觉响应很快——这和普通 loading 转圈体验差很多。

* * *

## 和你现有组件库完全兼容

这是 `useFrontendTool` 被低估的优点:你现有的组件一行不用改。

你已经有 ``、``、`` 这些组件——只要把它们包进 `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” ? : ,“});`

* * *

## 一个容易踩的坑

`handler` 运行在浏览器端,这是好事,但也意味着它能访问你的前端 state——你得想清楚哪些 state 该暴露、哪些不该。

如果你的 `handler` 里有 `const { user } = useAuthStore()` 这种调用,它读到的是当前登录用户的数据。这当然可以用,但如果你同时也在 `description` 里写了「可以查看任意用户的数据」,那就有问题了——AI 可能被诱导调用本不该调的逻辑。

**实践规则**:`handler` 里的逻辑跟普通 React 事件处理一样对待,该鉴权的鉴权,该边界检查的检查,不要因为「是 AI 调的」就放松警惕。

* * *

## 适合用 CopilotKit 的场景

说实话,不是所有 React 应用都需要 CopilotKit。

**适合:**

•数据密集型后台(报表、仪表盘),用户经常需要「帮我看看 XX 数据」•有大量表单的应用,AI 可以帮用户填写、校验•项目管理类工具,AI 可以直接创建、修改任务卡片•任何「用户用自然语言描述需求,系统操作 UI 响应」的场景
**不适合:**

•简单的问答类产品,文字返回就够了•UI 结构极简的工具,没有值得渲染的组件•对 bundle size 极敏感的场景(CopilotKit 有一定体积)

* * *

## 现在的生态位置

CopilotKit 在 2026年完成了 $2700万融资(据行业报道),AG-UI 协议也在 Vercel、LangChain 等生态里逐步被采用。它背后的 AG-UI 和 Google 主导的 A2UI 是同一个问题的不同解法:AI 如何和前端界面安全地双向通信。

目前来看,CopilotKit 的 Controlled 模式(useFrontendTool)是最成熟、最适合生产落地的方案,因为控制权在开发者手里。如果你想探索更开放的模式(AI 直接生成组件描述),可以看他们的 A2UI 集成——但那个还在早期,暂时不建议生产使用。

* * *

## 总结

一句话:**useFrontendTool 把你的 React 组件变成 AI 可以调用的工具,AI 控制触发时机,你控制渲染结果。**

核心三步:

1.用 `` Provider 包裹应用 2.建后端 runtime 路由(换个 adapter 就能换模型)3.用 `useFrontendTool` 注册组件,写好 `handler` 和 `render`
如果你的 React 应用现在的 AI 能力还停在「聊天框里显示文字」,CopilotKit 值得认真评估一下。

企业落地新闻资讯智能营销

从技术跃迁到规则重塑:智能浪潮中的中国广告业新图景

2026-7-3 15:51:06

Agent智能体Openclaw新闻资讯

OpenClaw超级速查表

2026-7-3 16:01:43

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
搜索