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

资讯详情

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

CopilotKit 异步前端工具(Frontend Tools Async)实战:基于 Langroid 集成的客户端工具端到端实现与 QA 验证指南

CopilotKit 异步前端工具(Frontend Tools Async)实战:基于 Langroid 集成的客户端工具端到端实现与 QA 验证指南 CopilotKit 异步前端工具Frontend Tools Async实战基于 Langroid 集成的客户端工具端到端实现与 QA 验证指南【免费下载链接】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导读本文围绕 CopilotKit Langroid 集成中的frontend-tools-async示例展开深入讲解如何通过useFrontendTool在浏览器端注册异步前端工具async frontend toolAgent 发起工具调用后由客户端 handler 执行一次真实的异步操作本例为模拟本地笔记数据库查询再将结果交还给 Agent 汇总并渲染到聊天流中。读完本文你将掌握异步前端工具的核心 API 形态、前后端接线方式、加载态渲染策略以及如何依据仓库内的 QA 清单与 E2E 测试对这一链路做端到端验证。本文对应的 QA 清单位于 showcase/integrations/langroid/qa/frontend-tools-async.mdDemo 源码位于 showcase/integrations/langroid/src/app/demos/frontend-tools-async/。一、功能定位什么是异步前端工具CopilotKit 的前端工具Frontend Tools机制允许 LLM Agent 调用注册在浏览器端的函数而不是只能调用服务端工具。当 handler 内部需要等待异步操作如请求 IndexedDB、读取本地缓存、调用浏览器 API、模拟网络往返时就构成了异步前端工具场景——Agent 会等待该 Promise resolve 之后再基于返回结果继续生成回答。在 Langroid 集成中该能力由frontend-tools-async这一 demo 专门演示。从 showcase/integrations/langroid/manifest.yaml 中的功能声明可以看到frontend-tools-async被列为独立的 demo 条目描述为useFrontendTool with an async handler — agent awaits a client-side async operation (simulated notes DB query) and uses the returned result同时该集成也声明了frontend-tools同步版与frontend-tools-async异步版两项能力。两者的核心区别在于同步版 handler 直接返回结果如setBackground而异步版 handler 返回一个Promiserender回调需要经历pending → complete的状态转换从而驱动出加载态 UI。二、Demo 入口与页面装配页面入口位于 showcase/integrations/langroid/src/app/demos/frontend-tools-async/page.tsx整体装配结构如下use client; import React from react; import { CopilotChat, CopilotKit, useConfigureSuggestions, useFrontendTool, } from copilotkit/react-core/v2; import { z } from zod; import { NotesCard, type Note } from ./notes-card; import { NOTES_DB, sleep } from ./fake-notes-db; export default function FrontendToolsAsyncDemo() { return ( CopilotKit runtimeUrl/api/copilotkit agentfrontend-tools-async div classNameflex justify-center items-center h-screen w-full div classNameh-full w-full max-w-4xl Chat / /div /div /CopilotKit ); }要点Provider 配置CopilotKit指定了runtimeUrl/api/copilotkitNext.js API 路由和agentfrontend-tools-async。这个 agent 名称会随请求发送给运行时用于路由到对应的后端 Agent 实例详见下文后端接线。聊天 UI页面使用copilotkit/react-core/v2提供的预置CopilotChat组件agentId与 Provider 的 agent 名保持一致。Schema 校验工具参数使用zod定义CopilotKit 会将其转换为 Agent 可识别的 JSON Schema。页面还通过useConfigureSuggestions预置了三条建议提示suggestion pills方便用户一键发起测试useConfigureSuggestions({ suggestions: [ { title: Find project-planning notes, message: Find my notes about project planning., }, { title: Search for auth, message: Search my notes for anything related to auth., }, { title: What do I have about reading?, message: Do I have any notes tagged reading?, }, ], available: always, });这三条建议分别对应 QA 清单中的验证场景project planning 关键词搜索、auth 关键词搜索以及 reading 标签搜索。三、核心实现useFrontendTool 注册异步工具query_notes工具通过useFrontendTool钩子注册完整代码如下节选自 page.tsxuseFrontendTool({ name: query_notes, description: Search the users local notes database for notes whose title, excerpt, or tags contain the given keyword (case-insensitive). Returns up to 5 matching notes., parameters: z.object({ keyword: z .string() .describe(Keyword or phrase to search notes for (case-insensitive).), }), handler: async ({ keyword }: { keyword: string }) { await sleep(500); const q keyword.toLowerCase(); const matches NOTES_DB.filter((n) { return ( n.title.toLowerCase().includes(q) || n.excerpt.toLowerCase().includes(q) || (n.tags ?? []).some((t) t.toLowerCase().includes(q)) ); }).slice(0, 5); return { keyword, count: matches.length, notes: matches, }; }, render: ({ args, result, status }) { const loading status ! complete; const parsed parseJsonResult{ keyword?: string; count?: number; notes?: Note[]; }(result); return ( NotesCard loading{loading} keyword{args?.keyword ?? parsed.keyword ?? } notes{parsed.notes} / ); }, });对该实现逐项拆解3.1 工具声明name / description / parametersname: query_notesAgent 在推理时使用的工具标识后端 Agent 不需要为它定义任何工具因为实际执行完全发生在浏览器端。description对搜索行为做了精确描述——对标题、摘要、标签做大小写不敏感的子串匹配最多返回 5 条。描述质量直接影响 LLM 选择该工具的准确性。parameters用zod定义单个keyword字符串参数并通过.describe()补充说明。CopilotKit 会将该 schema 注入给 Agent。3.2 异步 handler客户端侧的数据库往返handler: async ({ keyword }: { keyword: string }) { await sleep(500); // 模拟本地 DB 查询延迟 const q keyword.toLowerCase(); const matches NOTES_DB.filter(...).slice(0, 5); return { keyword, count: matches.length, notes: matches }; };handler 是async函数返回Promise这正是异步前端工具的关键特征。await sleep(500)用 500ms 模拟一次本地数据库往返。sleep与模拟数据都定义在 fake-notes-db.tssleep(ms)是对setTimeout的 Promise 封装NOTES_DB是 7 条确定性数据n1–n7文件注释明确说明Demo-only fixture真实应用中应替换为 IndexedDB、缓存拉取或任何客户端自有数据源。固定且确定的数据保证了测试与截图可复现。搜索逻辑对title、excerpt、tags三个字段做小写化后的子串匹配命中后截取前 5 条返回结构包含keyword、count和notes便于渲染层与 Agent 两侧使用。3.3 render 回调加载态与结果态render: ({ args, result, status }) { const loading status ! complete; ... return NotesCard loading{loading} keyword{...} notes{parsed.notes} /; };status会经历非completepending到completehandler resolve的状态转换loading status ! complete即加载态判定。在异步 handler 未返回期间UI 显示加载态resolve 后切换到结果态。这对应 QA 清单中的loading state shows briefly while the async handler resolves验证点。args为 Agent 传入的原始参数此时结果可能还未解析渲染层用args?.keyword ?? parsed.keyword做兜底。四、渲染层NotesCard 与加载态呈现结果卡片定义在 notes-card.tsx文件注释强调它与其它工具渲染 cell 共用同一套渲染路径但notes数组完全来自浏览器端异步 handler 的返回。关键 UI 行为加载态显示Querying local notes DB...文案与...占位符结果态显示匹配数量N matches、关键词标题Matching keyword并逐条渲染笔记标题、摘要、标签 chips空结果显示No notes matched.的斜体空态文案。组件暴露了稳定的测试锚点供 QA 与 E2E 使用testid含义notes-card卡片外层容器notes-keyword关键词标题Matching keywordnotes-list匹配结果ulnote-n1…note-n7每条笔记行五、后端接线CopilotKit Runtime 与 AG-UI 协议前端工具的执行虽然在浏览器完成但工具调用的编排仍由后端 Agent 发起因此需要运行时桥接。Langroid 集成的桥接路由位于 showcase/integrations/langroid/src/app/api/copilotkit/route.tsconst AGENT_URL process.env.AGENT_URL || http://localhost:8000; function createAgent(path /) { return new HttpAgent({ url: ${AGENT_URL}${path} }); }Langroid Agent 后端以独立进程运行在 8000 端口前端通过HttpAgent以AG-UI 协议转发请求。路由注册了frontend-tools-async这个 agent 名称。文件注释明确说明frontend-tools 变体在后端没有专用工具前端通过useFrontendTool注册 handler由 Agent 调用它们。启动方式由cli-startdemo 给出npx copilotkitlatest init --framework langroid。这条链路的工作流为用户提问 → Agent 决定调用query_notes→ 请求经 runtime 路由到前端注册的 handler → 浏览器执行异步查询并返回结果 → 结果回传给 Agent → Agent 基于结果生成回答 →render依据最终状态渲染 NotesCard。六、QA 验证指南逐条解读测试步骤以下是 frontend-tools-async.md 中的完整 QA 步骤结合实现细节逐条解读步骤 1导航到 /demos/frontend-tools-async启动 Langroid 集成开发环境后在浏览器访问/demos/frontend-tools-async路由。页面应展示完整的聊天界面CopilotChat并出现三条建议提示suggestion pills。可验证依据E2E 测试 frontend-tools-async.spec.ts 的第一个用例page loads with composer and 3 pills断言了输入框占位符Type a message与三个按钮Find project-planning notes、Search for auth、What do I have about reading?的可见性。步骤 2提问 Find my notes about project planning.点击第一条建议或直接在输入框输入该消息。Agent 应识别出需要查询本地笔记并调用query_notes前端工具传入keywordproject planning。预期结果异步 handler 对NOTES_DB执行大小写不敏感搜索命中 n1Q2 project planning kickoff与 n5Project planning retrospective notes两条笔记。步骤 3验证 notes-card 渲染出匹配关键词聊天流中应出现NotesCard其标题显示Matching project planning列表包含 n1 与 n5 两条笔记。可验证依据E2E 用例project-planning pill → Notes DB card with project-planning notes断言notes-keyword匹配/Matching\s[“]project planning[”]/i且note-n1、note-n5可见。步骤 4验证加载态在异步 handler 解析期间短暂出现由于 handler 内部await sleep(500)卡片在结果返回前会短暂显示Querying local notes DB...加载文案。验证这一点的要点是卡片必须先以加载态挂载再过渡到结果态。可验证依据harness 探针 d5-frontend-tools-async.ts 使用settled shape断言——卡片挂载后轮询等待其进入两种最终形态之一非空notes-list或No notes matched空态。若异步 handler 卡死未 resolve卡片会永远停留在loadingtrue断言将超时失败从而捕获异步 handler 挂起的回归。步骤 5尝试 Search my notes for anything related to auth 并验证 auth 标签笔记出现点击第二条建议Agent 应调用query_notes(keywordauth)。handler 会命中 n2Planning: migrate auth to passkeystags 含auth卡片显示Matching auth与 n2 笔记。可验证依据E2E 用例auth pill → Notes DB card with auth-related notes断言关键词标题与note-n2可见并额外做了反回归断言通用兜底助手文案Im your showcase assistant不得出现防止其它 fixture 拦截了该提示词。七、自动化验证E2E 测试设计E2E 测试 showcase/integrations/langroid/tests/e2e/frontend-tools-async.spec.ts 共包含 4 个用例覆盖 QA 清单的全部场景页面加载composer 与 3 条建议 pills 可见。project planning 查询点击 pill → NotesCard 可见 → 关键词标题为 project planning → n1、n5 渲染 → 反回归断言通用计划模板文案不出现。auth 查询点击 pill → NotesCard 可见 → 关键词标题为 auth → n2 渲染 → 反回归断言 showcase-assistant 兜底文案不出现。reading 查询点击 pill → 关键词为 reading → 匹配数1 match→ n4 渲染 → 笔记内容Book recommendations、Thinking Fast and Slow 等与reading标签 chip 可见 → 并断言 Agent 的第二轮叙述文案引用该笔记标题与标签的固定措辞。同一线程内连续触发三个 pills每个 pill 各自渲染自己的 NotesCard卡片数量依次 1→2→3验证多轮对话中异步工具链路的健壮性。测试注释还记录了此前的一个 aimock 多 pill 回归 bug 及其修复方式通过toolCallId串联 fixture、移除hasToolResult门控。这些测试通过确定性 aimock fixture 与真实客户端NOTES_DB配合实现了对异步工具端到端往返的真通过验证。八、与同步前端工具的对比Langroid 集成中还有一个同步版前端工具 demofrontend-tools切换页面背景色见 frontend-tools/page.tsxuseFrontendTool({ name: change_background, description: Change the page background. Accepts any valid CSS background value — colors, linear or radial gradients, etc., parameters: z.object({ background: z.string().describe(The CSS background value. Prefer gradients.), }), handler: async ({ background }) { setBackground(background); return { status: success }; }, });两者的差异与选型建议同步场景如修改本地状态、切换 UIhandler 立即返回render通常不需要加载态可参考frontend-toolsdemo 的CopilotSidebar形态。异步场景如查询本地数据库、调用浏览器 API、等待网络往返handler 返回Promise必须处理 pending 状态render中通过status ! complete驱动加载态这正是frontend-tools-asyncdemo 的核心价值。从 manifest 看两者在features列表中分别声明为frontend-tools与frontend-tools-async说明这是 CopilotKit 能力矩阵中的两个独立能力项。九、小结与排查建议异步前端工具让 Agent 在不经过后端网络往返的前提下安全地操作浏览器本地数据与能力是构建个人数据助手类应用本地笔记搜索、文件元数据查询、浏览器书签检索等的高效模式。结合本文的仓库证据做功能验证时可参考以下排查思路卡片未出现检查useFrontendTool的name与后端 Agent 工具约定是否一致以及agentfrontend-tools-async是否在 route.ts 的 agent 注册表中。一直处于加载态handler 的 Promise 未 resolve如异步逻辑抛错或挂起可用 harness 的 settled-shape 断言快速定位。关键词不匹配确认 Agent 传给 handler 的keyword参数与建议提示一致并核对NOTES_DB中对应笔记的字段内容。结果未回传 Agent检查 handler 的返回结构是否可被 Agent 理解建议返回结构化对象便于 LLM 摘要。以上所有验证步骤、源码与测试用例均可从当前仓库中直接复现与深入研读。【免费下载链接】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),仅供参考
返回列表