尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CopilotKit 工具渲染(Tool Rendering)实战指南:在聊天流中为 Agent 工具调用渲染 React 卡片

CopilotKit 工具渲染(Tool Rendering)实战指南:在聊天流中为 Agent 工具调用渲染 React 卡片 CopilotKit 工具渲染Tool Rendering实战指南在聊天流中为 Agent 工具调用渲染 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/CopilotKit导读当后端 Agent 在对话中调用工具查询天气、搜索航班、获取股价、掷骰子时CopilotKit 允许开发者在前端把这些工具调用渲染成内嵌在聊天流中的 React 组件并区分“工具执行中”与“执行完成”两种视觉状态。本文以仓库built-in-agentTanStack AI 内建 Agent示例中的 Tool Rendering 演示为对象逐条解析其 QA 验收清单背后的实现原理与验证方法。读完本文你将掌握useRenderTool按工具注册专属渲染器、useDefaultRenderTool注册兜底渲染器的完整用法以及如何用 Playwright 对工具卡片做确定性回归测试。Demo 概览与运行环境Tool Rendering 演示位于showcase/integrations/built-in-agent/页面路径为/demos/tool-rendering。根据 QA 文档 tool-rendering.md运行该演示需要满足以下前置条件前置项说明API Key在.env.local或环境变量中设置OPENAI_API_KEY依赖安装在built-in-agent/包目录下执行npm install --legacy-peer-deps启动在built-in-agent/包目录下执行npm run dev访问地址http://localhost:3000/demos/tool-rendering其中--legacy-peer-deps表明该演示依赖树中存在 peer dependency 版本约束需跳过严格 peer 校验这也是仓库内多个示例包的通用安装约定。从页面源码 page.tsx 可以看到Demo 通过CopilotKit组件挂载运行时并通过agenttool-rendering绑定到后端注册的命名 AgentCopilotKit runtimeUrl/api/copilotkit agenttool-rendering CopilotChat agentIdtool-rendering classNameh-full rounded-2xl / /CopilotKit对应的后端路由在 route.ts 中注册为tool-rendering: createBuiltInAgent()由InMemoryAgentRunner在进程内运行。也就是说这个 Demo 的 Agent 与前端同属一个 Next.js 应用工具调用通过/api/copilotkit单路由mode: single-route完成。三层工具渲染架构专属渲染器 兜底渲染器演示 READMEREADME.md概括了核心机制后端 Agent 的工具调用被渲染为聊天流中的 React 组件前端用useRenderTool按工具名注册渲染器接收args、result、status三个输入从而让 UI 同时反映“进行中”与“已完成”两种状态。在 page.tsx 的注释中可以看到该 Demo 的完整注册清单这正是“三层”结构后端工具前端渲染器类型get_weatherWeatherCard /专属渲染器search_flightsFlightListCard /专属渲染器get_stock_priceStockCard /专属渲染器roll_d20D20Card /专属渲染器其他任意工具CustomCatchallRenderer /兜底渲染器专属渲染器useRenderTooluseRenderTool是copilotkit/react-core/v2提供的 Hook用于为特定工具名注册渲染函数。以天气工具为例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} / ); }, }, [], );几个关键点parameters用 zod 描述入参契约与后端inputSchema对应既是运行时校验也是类型推导依据render回调每次工具状态变化时都会重新执行因此loading status ! complete可以在执行期间显示加载态result在完成前通常是原始字符串Demo 通过共享工具函数parseJsonResult位于 parse-json-result.ts将其安全解析为结构化对象注册后传入的依赖数组[]与 React Hook 约定一致需保持引用稳定。航班搜索page.tsx、股价L126-L146、d20 掷骰L150-L169三个工具遵循完全相同的模式分别渲染FlightListCard、StockCard、D20Card。兜底渲染器useDefaultRenderTool并非每个后端工具都值得定制 UI。对于未被专属渲染器认领的工具调用useDefaultRenderTool提供了通配兜底page.tsxuseDefaultRenderTool( { render: ({ name, parameters, status, result }) ( CustomCatchallRenderer name{name} parameters{parameters} status{status as CatchallToolStatus} result{result} / ), }, [], );兜底渲染器 custom-catchall-renderer.tsx 是一个自包含的“通用工具卡”展示工具名、状态徽章streaming/running/done三态、格式化后的参数 JSON 与结果 JSON。CatchallToolStatus类型定义在 custom-catchall-renderer.tsx取值为inProgress | executing | complete其状态描述逻辑在describeStatus函数中实现。这套“专属优先、兜底托底”的设计意味着新增后端工具时前端无需改动即可自动获得可读的工具卡片需要品牌化展示时再补一个专属渲染器即可。QA 一页面加载检查QA 清单的第一组断言聚焦页面初始状态页面标题 Tool Rendering 可见提示文本Try: Whats the weather in Tokyo?可见聊天输入框可见。从体验设计看这组断言对应 suggestions.ts 中通过useConfigureSuggestions配置的 5 个建议药丸suggestion pill药丸标题对应消息Weather in SFWhats the weather in San Francisco?Find flightsFind flights from SFO to JFK.Stock priceWhats the current price of AAPL?Roll a d20Roll a 20-sided die.Chain tools单轮内链式调用东京天气 SFO→东京航班 掷 d20这些药丸是 QA 交互的快捷入口同时也是 e2e 测试的确定性触发源。对应验证逻辑可参见 e2e 用例 tool-rendering.spec.ts其中逐一对 5 个药丸标题做了可见性断言。QA 二快乐路径交互Happy Path快乐路径是工具渲染的核心体验验证QA 文档要求逐步检查三个场景。场景 1执行中状态可见发送 Whats the weather in Tokyo? 后工具执行期间应出现一张内联的 Fetching weather… 进行中卡片。这一行为的实现就在WeatherCard的加载态分支weather-card.tsxloading为真时副标题位置渲染Fetching weather...文本右侧主视觉替换为省略号占位同时隐藏温度、湿度、风力等数据区块weather-card.tsx。也就是说“进行中卡片”与“完成卡片”是同一张卡片组件在两个状态下的切换而不是两套独立 UI。场景 2完成态数据正确Agent 执行完毕后卡片应显示城市名、温度°F、天气状况文本、湿度百分比。WeatherCard渲染的字段与后端返回一一对应server-tools.tsexport const getWeatherTool toolDefinition({ name: get_weather, description: Get the current weather for a given location. ..., inputSchema: z.object({ location: z.string(), }), }).server(async ({ location }) ({ city: location, temperature: 68, humidity: 55, wind_speed: 10, conditions: Sunny, }));后端temperature、humidity、wind_speed、conditions四个字段分别映射到卡片的温度{temperature}°F、湿度{humidity}%、风速{windSpeed} mph与状况文本状况还会被conditionsEmoji映射为 emoji 图标weather-card.tsx。注意这里getWeatherTool返回的是 mock 数据固定 68°F / 55% / 10 mph / Sunny这正是 QA 与 e2e 断言能够确定性的基础。场景 3多次工具调用的隔离继续询问第二座城市如 And what about London?应出现第二张天气卡片且不得干扰第一张。这个“每张卡片独立”的行为源于渲染模型每个工具调用都会以独立的 React 节点挂载到消息流中。d20 卡片是这一点的极端体现——每次掷骰都会产生一张独立卡片e2e 用轮询断言“恰好出现 5 张 d20 卡片且最后一张结果为 20”tool-rendering.spec.ts。而 Chain tools 药丸则验证单轮内多工具并存的场景一次提问同时渲染出天气卡、航班卡和 d20 卡tool-rendering.spec.ts。QA 三边界用例检查边界 1非 weather 工具走兜底渲染器发送触发weather之外工具的消息如 Tell me todays date应渲染通用工具卡——显示工具名、状态和 JSON 载荷——而不是自定义天气卡。这正是useDefaultRenderTool兜底渲染器的工作。CustomCatchallRenderer携带稳定的data-testidcustom-catchall-card与data-tool-name{name}、data-status{status}属性custom-catchall-renderer.tsx便于自动化定位。执行期间结果区显示 waiting for tool to finish…完成后通过parseResult尝试 JSON 解析并美化为缩进展示。这个设计同时印证了一个关键约束当后端新增一个没有专属渲染器的工具时前端不会白屏或丢失信息兜底卡会立即接管展示。边界 2纯对话消息不渲染工具卡发送普通对话消息如 Hi thereAgent 正常回复且不出现任何工具卡片。这验证的是渲染器的触发条件只有存在真实的工具调用流时useRenderTool/useDefaultRenderTool的render才会被调用纯文本回复不经过工具渲染路径。这一行为保证了工具卡片不会误伤正常对话体验。补充状态机视角从兜底渲染器的状态徽章可以反推工具生命周期inProgressstreaming流式输出中→executingrunning工具执行中→completedone完成。专属卡片则把状态折叠为二元判断status ! complete。理解这一状态序列有助于设计自己的卡片加载态与错误态。后端工具契约与渲染器对齐的输入输出工具渲染之所以能“前后端对齐”是因为工具定义集中在 server-tools.ts 中并通过baseServerTools数组挂载到createBuiltInAgent()。除天气外Tool Rendering 相关的还有searchFlightsToolserver-tools.ts入参origin/destination返回 3 条确定性 mock 航班UA231、DL412、B6722供FlightListCard渲染“航空公司 航班号 起降时间 价格”列表getStockPriceToolL93-L109入参ticker返回随机价格与涨跌幅StockCard据此显示$price与带正负号的change%涨绿跌红见 stock-card.tsxrollD20ToolL136-L145入参sides默认 6返回{ sides, result }D20Card在结果为 20 时显示 critical! 徽章并加高亮描边d20-card.tsx。工具描述文本description还承担着提示工程职责例如get_weather的描述提示模型“提到城市时也考虑查航班”search_flights描述规定“未匹配到出发地时默认 SFO”。这解释了为什么 Chain tools 药丸能可靠地触发多工具链式调用。e2e 自动化验证把 QA 清单变成可回归的测试QA 文档的每一条检查项在 tool-rendering.spec.ts 中都有对应的 Playwright 用例形成 6 个测试的完整闭环e2e 用例对应 QA 检查关键断言页面加载与 5 个建议药丸页面加载各药丸标题可见Weather in SF 药丸快乐路径weather-card可见城市为 San Francisco、湿度 55%、风速含 10Find flights 药丸快乐路径flights-card可见SFO → JFK至少 2 行flight-rowStock price 药丸快乐路径stock-card可见ticker 为 AAPL、价格 $338.37、涨跌 -2.96%Roll a d20 药丸隔离性恰好 5 张d20-card最后一张值为 20前 4 张非 20Chain tools 药丸多工具并存同一轮内天气卡、航班卡、d20 卡全部可见测试注脚tool-rendering.spec.ts说明了确定性来源aimock fixtures 位于showcase/aimock/d5-all.json把每个药丸提示固定到确定的工具调用序列卡片则依赖稳定data-testid定位。测试超时分为建议加载15s与工具执行60s两档。这说明 QA 文档并非一次性人工清单而是与自动化回归测试一一对应的“可执行验收规范”。如果你要复现验证只需要在满足前置条件后访问/demos/tool-rendering依次点击药丸并按 QA 清单勾选要自动化则可直接复用上述 spec 的定位策略data-testidweather-card、weather-city、weather-humidity等。变体与延伸工具渲染的进阶形态工具渲染在本仓库内还有多个进阶变体可作为继续深入的方向tool-rendering-default-catchall展示框架内置的默认兜底渲染器shadcn 风格位于 tool-rendering-default-catchalltool-rendering-custom-catchall仅演示自定义兜底渲染器见 tool-rendering-custom-catchalltool-rendering-reasoning-chain在工具渲染之上叠加可见的推理链reasoning展示见 tool-rendering-reasoning-chainheadless-complete的 tools 目录 提供了weather-card.tsx、generic-tool-card.tsx、chart-card.tsx等更丰富的渲染器集合可参考其无头模式下的注册方式。这三个变体各自带有独立的 e2e spectool-rendering-default-catchall.spec.ts、tool-rendering-custom-catchall.spec.ts、tool-rendering-reasoning-chain.spec.ts验证方式与本 Demo 一脉相承。验收核对表一次完整的 QA 执行最后汇总成可直接执行的核对表对应 tool-rendering.md 全量条目准备设置OPENAI_API_KEY→npm install --legacy-peer-deps npm run dev→ 打开http://localhost:3000/demos/tool-rendering页面加载标题 Tool Rendering 可见提示文本 Whats the weather in Tokyo? 可见聊天输入框可见快乐路径发送天气问题后出现 Fetching weather… 进行中卡片完成后卡片显示城市、温度°F、状况、湿度追问第二城市第二张卡片渲染且不影响第一张边界用例触发非weather工具时渲染通用工具卡工具名 状态 JSON 载荷发送纯对话消息正常回复且无任何工具卡片至此你既掌握了 CopilotKit 工具渲染的前端注册机制useRenderTooluseDefaultRenderTool也拥有了完整的验收标准与自动化回归测试方法可以直接迁移到自己的 Agent 前端项目中。【免费下载链接】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),仅供参考
返回列表