CopilotKit 实战:用 useRenderTool 将 LangGraph 后端工具调用渲染为 React 聊天组件 📅 发布时间:2026/9/13 15:40:27 👁 浏览次数: CopilotKit 实战用 useRenderTool 将 LangGraph 后端工具调用渲染为 React 聊天组件【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKitCopilotKit 是一个面向 Agents 与 Generative UI 的前端技术栈。本指南围绕其 Tool Rendering工具渲染能力展开后端 Agent 发出的工具调用会在聊天记录中被渲染为一个个 React 组件前端通过useRenderTool按工具名注册渲染器并接收args、result、status三个核心数据来同时表达调用进行中与调用已完成两种状态。读完本文你将掌握从 LangGraph 后端定义工具、到前端为每个工具定制专属 UI 卡片、再到兜底通用渲染器的完整实现链路并看到仓库中配套的 E2E 测试是如何验证这一行为的。该 Demo 的主文档位于仓库的 showcase manifestmanifest.yaml本文以 tool-rendering README 为骨架结合同目录下的源码、后端 Agent 与 E2E 测试做纵深展开。一、Tool Rendering 要解决什么问题传统聊天界面里Agent 的工具调用要么以难以阅读的 JSON 平铺在消息流中要么干脆对用户隐藏。CopilotKit 的 Tool Rendering 思路是把工具调用本身变成一种界面语言——工具名决定用哪个 React 组件来渲染工具参数决定卡片内容工具执行状态决定卡片处于加载中还是已完成。在 page.tsx 的Chat组件中四条映射规则被清晰注释在源码顶部get_weather → WeatherCard / (per-tool renderer) search_flights → FlightListCard / (per-tool renderer) get_stock_price → StockCard / (per-tool renderer) roll_d20 → D20Card / (per-tool renderer) * → CustomCatchallRenderer / (wildcard fallback)也就是说前四个有意思的后端工具各自拥有品牌化的专属 UI而任何未注册的漏网工具都会被通配的 catch-all 渲染器接住保证聊天记录永远不会出现裸 JSON。二、三种渐进实现方案从 showcase manifest 的 cell 列表manifest.yaml可以看到Tool Rendering 主题在仓库中被拆成了三个渐进式 Demo它们共享同一个后端 Agent区别只在前端如何渲染相同的工具调用Cell方案特点tool-rendering-default-catchall前端不注册任何渲染器展示框架默认的兜底渲染效果tool-rendering-custom-catchall只注册一个通配 catch-all所有工具走同一个自定义卡片tool-renderingper-tool catch-all 组合每个工具专属卡片漏网的走兜底另有tool-rendering-reasoning-chain将工具卡片与 reasoning 展示组合在同一聊天界面。这种同一个后端、三种前端渲染策略的设计让开发者能直观对比不同方案的取舍。三、核心 APIuseRenderTool 与 useDefaultRenderTool工具渲染的两个核心 Hook 均来自copilotkit/react-core/v2useRenderTool按name精确匹配为指定工具注册专属渲染器useDefaultRenderTool注册通配渲染器承接所有未被useRenderTool认领的工具调用。3.1 注册一个专属工具渲染器以天气工具为例page.tsxuseRenderTool( { name: get_weather, parameters: z.object({ location: z.string(), }), render: ({ parameters, result, status }) { const loading status ! complete; const parsed parseJsonResultWeatherResult(result); return ( WeatherCard loading{loading} location{parameters?.location ?? parsed.city ?? } temperature{parsed.temperature} humidity{parsed.humidity} windSpeed{parsed.wind_speed} conditions{parsed.conditions} / ); }, }, [], );关键点拆解name必须与后端 Agent 中的工具名完全一致此例对应 Python 端的get_weatherparameters使用zod定义工具入参的结构化描述用于运行时校验与类型推导render回调的三个入参parameters本次调用的实参对象result工具执行结果可能是 JSON 字符串也可能是已被上游解码的对象status工具调用生命周期状态用status ! complete即可表达仍在进行中。注意render返回的是真实 JSX——这正是 Generative UI 的核心模型调用工具前端以组件响应。3.2 注册通配 catch-all 渲染器未匹配到任何 per-tool 渲染器的工具会落入useDefaultRenderToolpage.tsxuseDefaultRenderTool( { render: ({ name, parameters, status, result }) ( CustomCatchallRenderer name{name} parameters{parameters} status{status as CatchallToolStatus} result{result} / ), }, [], );该回调多出name参数便于通配组件知道自己正在渲染哪个工具。四、渲染器的状态感知从加载中到已完成四个专属卡片组件weather-card.tsx、flight-list-card.tsx、stock-card.tsx、d20-card.tsx遵循同一套模式接收loading布尔值与解析后的数据字段。4.1 WeatherCard占位与条件渲染{loading ? Fetching weather... : conditions || —} ... {!loading ( div classNamemt-5 text-4xl ...{temperature ?? --}deg;/div ... / )}进行中只显示城市名与占位文案温度、湿度、风速等数据区在完成后才渲染。4.2 FlightListCard骨架屏与结果列表航班卡片在加载时渲染三个animate-pulse骨架屏完成后渲染航班行并在右上角显示结果数量徽章{loading ? ( div classNamespace-y-2Skeleton /Skeleton /Skeleton //div ) : ( ul classNamespace-y-2...flights.map(...)/ul )}4.3 StockCard 与 D20Card状态差异化的数据表达StockCard 加载时只显示fetching…角标完成后渲染价格与涨跌幅正涨绿色、下跌红色D20Card 使用data-d20-result属性暴露结果供测试断言且掷出 20 时额外显示critical!徽章并带绿色 ring 高亮。4.4 通配组件的三态徽章CustomCatchallRenderer 把工具状态映射为三种徽章status徽章文案视觉含义inProgressstreaming参数流式到达executingrunning工具正在后端执行completedone执行完成展示结果组件主体用两个pre区块分别 pretty-print 参数与结果 JSON并用data-testidcustom-catchall-card、data-tool-name、data-status暴露结构供测试定位。4.5 结果归一化工具由于result可能是字符串或对象Demo 复用了共享工具 parse-json-result.ts 将结果统一归一化为类型化对象export function parseJsonResultT(result: unknown): T { if (!result) return {} as T; try { return (typeof result string ? JSON.parse(result) : result) as T; } catch { return {} as T; } }这让WeatherResult、FlightSearchResult等接口与render回调解耦——无论运行时如何传值都能安全消费。五、后端LangGraph Agent 与工具定义前端渲染的原料来自后端 tool_rendering_agent.py该文件注释明确说明三个 tool-rendering cell 共享同一后端区别只在前端渲染方式。5.1 四个 mock 工具tools[get_weather, search_flights, get_stock_price, roll_dice],get_weather(location)返回温度、湿度、风速、天气状况的固定 mock 数据search_flights(origin, destination)返回三条 mock 航班记录航空、航班号、起飞到达时间、价格get_stock_price(ticker, price_usdNone, change_pctNone)可选参数允许测试脚本注入确定性行情缺省时返回随机值roll_dice(sides6)按面数返回随机点数。5.2 系统提示刻意引导工具链式调用SYSTEM_PROMPT是本 Demo 的精心设计——为了让前端多张工具卡片的渲染模式被直观触发提示词鼓励模型在单个回合内连续调用多个工具例如查东京天气 →get_weather(Tokyo)后再search_flights(originSFO, destinationTokyo)查 AAPL 股价 → 再拉取 MSFT/GOOGL 做对比掷 d20 → 再用不同面数掷一次。提示词描述的是习惯而非固定流程因此每次会话的工具组合都不同恰好能充分压测 per-tool 与 catch-all 两种渲染路径的并存。5.3 中间件接入Agent 通过CopilotKitMiddleware()与create_agent(...)组装from copilotkit import CopilotKitMiddleware模型使用gpt-4o-mini。工具调用事件经中间件流式传导到前端useRenderTool才能实时感知status的流转。六、入口与聊天壳page.tsx 的根组件把 Demo 挂在/api/copilotkit运行时上并指定agenttool-renderingCopilotKit runtimeUrl/api/copilotkit agenttool-rendering CopilotChat agentIdtool-rendering classNameh-full rounded-2xl / /CopilotKit所有渲染器都注册在CopilotChat之外的Chat组件层useSuggestions()则通过useConfigureSuggestions提供五个快捷提问天气、查航班、股价、掷骰、链式调用降低上手门槛suggestions.ts。该 Demo 在 showcase manifest 中注册为Generative UI: Tool Rendering (Custom)路由为/demos/tool-renderingmanifest.yaml。七、E2E 测试渲染行为的确定性验证Tool Rendering 的行为不是靠人肉点验而是由 Playwright E2E 测试钉死tests/e2e/tool-rendering.spec.ts。测试通过data-testid与 fixture 数据断言卡片存在、状态流转与结果正确性weather-card/weather-city/weather-humidity/weather-wind天气卡及其字段flights-card/flight-origin/flight-destination/flight-row航班卡及航班行stock-card/stock-ticker/stock-price/stock-change股票卡三要素d20-card/d20-value/data-d20-result骰子结果fixture 将五次调用脚本化为[7, 14, 3, 19, 20]含一次 20 的 critical 高亮custom-catchall-card/custom-catchall-tool-name/custom-catchall-args/custom-catchall-result/custom-catchall-status通配卡结构。配套测试还包括 tool-rendering-custom-catchall.spec.ts、tool-rendering-default-catchall.spec.ts 与 tool-rendering-reasoning-chain.spec.ts分别锁定三种渲染策略与 reasoning 组合场景。八、如何查看与运行阅读源码按manifest.yaml的 highlight 清单逐个查看 page.tsx、四个卡片组件、custom-catchall-renderer.tsx 与后端 tool_rendering_agent.py即可完整还原实现运行 Demo仓库只读请在本地检出后按 showcase 的常规方式启动 LangGraph FastAPI 后端与 Next.js 前端后端依赖见 requirements.txt入口路由为/api/copilotkit随后访问/demos/tool-rendering通过建议卡片中的 Chain tools 提问即可同时看到天气卡、航班卡与骰子卡在同一回合交错出现验证行为参考 tests/e2e/tool-rendering.spec.ts 编写或运行同类测试把渲染契约固化下来。总结Tool Rendering 把 Agent 的工具调用从日志升级为产品。以本 Demo 为模板你可以为任意后端工具实现三件事用useRenderTool绑定专属 React 组件、用useDefaultRenderTool兜底未知工具、用status/result驱动加载态与终态的差异化 UI。从源码结构看这套机制与后端框架解耦——同一套 LangGraph 工具集仅靠切换前端渲染策略就能衍生出默认兜底、自定义兜底、逐工具定制三种体验这正是 CopilotKit Generative UI 的可组合性所在。【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考