news 2026/9/12 6:05:57

CopilotKit 前端工具(Frontend Tools)实战:以 Claude Agent SDK (TypeScript) 集成的 change_background 为例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CopilotKit 前端工具(Frontend Tools)实战:以 Claude Agent SDK (TypeScript) 集成的 change_background 为例

CopilotKit 前端工具(Frontend Tools)实战:以 Claude Agent SDK (TypeScript) 集成的 change_background 为例

【免费下载链接】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

本篇文章以仓库中 Claude Agent SDK (TypeScript) 集成示例的前端工具(Frontend Tools)QA 文档为主线,完整讲解「Agent 调用浏览器端工具、在客户端执行并把结果回传给 Agent」这一能力的机制、验证步骤与底层原理。读完本文,你将掌握useFrontendTool的注册方式、前端工具如何经由 AG-UI 协议抵达 Claude 后端,以及如何通过手动 QA 与 Playwright 端到端测试双重验证「工具在客户端执行、Agent 感知结果」的完整链路。

前置条件:Demo 已部署、Agent 后端健康

QA 文档的第一部分是两条前置条件,它们是整个验证流程能否开始的基础:

  • Demo 已部署并可访问:即 Next.js 应用正常运行,/demos/frontend-tools页面可以被浏览器打开;
  • Agent 后端健康:Claude Agent SDK (TypeScript) 后端进程可被 CopilotKit Runtime 访问。

在仓库中,这两条前提有明确的代码支撑。CopilotKit Runtime 路由 src/app/api/copilotkit/route.ts 中定义了:

// The Claude agent backend runs as a separate TypeScript process on port 8000. // This runtime proxies CopilotKit requests to it via AG-UI protocol. const AGENT_URL = process.env.AGENT_URL || "http://localhost:8000";

后端默认监听8000端口,可通过AGENT_URL环境变量覆盖。route 的GET分支还提供健康探针:它请求${AGENT_URL}/health(3 秒超时),并把agent_statusreachable/error/unreachable)、ANTHROPIC_API_KEY是否已设置等信息以 JSON 返回。因此在开始手动验证前,可以先访问/api/copilotkit检查后端连通性与密钥配置,这正是 QA「Agent backend is healthy」的自动化化表达。

核心机制:useFrontendTool 如何把浏览器变成 Agent 的工具箱

理解change_background之前,先看它背后的架构。示例后端是「pass-through(透传)」模式——route.ts 的注释明确指出:

The Claude Agent SDK (TypeScript) backend is a pass-through: it forwards whatever tools the AG-UI client provides (frontend-registered via useFrontendTool / useRenderTool ...) to Claude. So distinct agent behaviour across demos comes from the frontend, not a per-demo backend graph.

也就是说:工具的「所有权」在前端。前端通过useFrontendTool注册工具,工具定义随 AG-UI run 输入一起发给 Runtime;Runtime 转发给后端进程;后端进程把 AG-UI 工具定义转换为 Anthropic Messages API 的toolsschema 后交给 Claude;Claude 决定何时调用该工具,调用请求再沿原路返回前端,由handler在浏览器中执行。

这个「AG-UI 工具定义 → Anthropic 工具 schema」的转换实现在 src/agent_server.ts 的buildTools函数(@region[frontend-tools-setup]):

function buildTools(tools: RunAgentInput["tools"]): Anthropic.Tool[] { if (!tools || tools.length === 0) return []; return tools.map((tool) => { let inputSchema: Anthropic.Tool.InputSchema = { type: "object", properties: {} }; if (tool.parameters) { try { const parsed = typeof tool.parameters === "string" ? JSON.parse(tool.parameters) : tool.parameters; inputSchema = parsed as Anthropic.Tool.InputSchema; } catch (parseErr) { // Don't silently swap in an empty schema ... console.warn(`[agent_server] failed to parse tool.parameters for ${tool.name}; using empty schema. error=${message}`); } } return { name: tool.name, description: tool.description ?? "", input_schema: inputSchema }; }); }

两个值得注意的实现细节:

  1. schema 解析容错parameters既可能是字符串(JSON)也可能是对象,统一解析为 Anthropic 的input_schema;解析失败时不静默降级为空 schema(那会让 Claude 接受任意输入形状),而是打console.warn大声告警;
  2. 空 schema 兜底:当工具没有声明参数时,使用{ type: "object", properties: {} },保证请求在 Messages API 层面始终合法。

在 agentic loop 中(同文件 L1818-1822),运行时工具(前端注册)与 demo 自带后端工具会被合并,且运行时工具优先级更高。对于前端工具这类「非后端工具」,loop 只在收到 Claude 的 tool_use 后把调用请求透传给客户端执行,而不会在服务端自行执行(见 L2196-2197 的注释)。

一步步验证:QA 文档五步测试的逐条拆解

QA 文档给出了 5 个测试步骤,下面结合源码逐条展开,说明「测什么、为什么这么测、底层对应什么」。

步骤 1:导航到 /demos/frontend-tools

页面入口是 src/app/demos/frontend-tools/page.tsx,顶层结构为:

export default function FrontendToolsDemo() { return ( <CopilotKit runtimeUrl="/api/copilotkit" agent="frontend_tools"> <Chat /> </CopilotKit> ); }

runtimeUrl="/api/copilotkit"指向上一节介绍的 Runtime 路由,agent="frontend_tools"指定 agent id。这个 id 在 route.ts 的agentNames注册表中("frontend_tools"出现在 "newly ported demos" 分组),并被映射到同一个 pass-through 后端——再次印证「各 demo 的行为差异来自前端,而非各自的 backend graph」。

步骤 2:发送 "Change the background to a sunset gradient"

用户通过CopilotSidebaragentId="frontend_tools"defaultOpen)输入这条自然语言指令。为了让用户一键触发,demo 还通过 src/app/demos/frontend-tools/suggestions.ts 的useConfigureSuggestions预置了三个建议 pill:

suggestions: [ { title: "Sunset theme", message: "Make the background a sunset gradient." }, { title: "Forest theme", message: "Switch to a deep green forest gradient." }, { title: "Cosmic theme", message: "Make it a navy → magenta cosmic gradient." }, ], available: "always",

其中 "Sunset theme" 的消息正是 QA 文档要验证的「sunset gradient」场景。

步骤 3:验证 change_background 前端工具执行、页面背景发生改变

这一步是核心。工具注册代码在 page.tsx:

const [background, setBackground] = useState<string>(DEFAULT_BACKGROUND); useFrontendTool({ 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" }; }, });

可以拆解出四个要素:

配置项作用
namechange_background工具唯一标识,也是 Claude 发起 tool_use 时使用的名字
description接受任意合法 CSS 背景值(颜色、线性/径向渐变等)给 LLM 的工具说明,直接影响其调用准确度
parametersZod schema:{ background: string }声明入参类型,供 LLM 生成结构化参数,并用于前端校验
handlerasync ({ background }) => setBackground(background)在浏览器端实际执行:把 CSS 值写入 React state

handler返回{ status: "success" },这个返回值会经 AG-UI 协议回传给后端,最终作为tool_result让 Claude 感知执行结果——这正是 QA「expected results」里「Frontend tool executes on the client and the agent sees the result」的底层含义。

背景的呈现与默认值在 src/app/demos/frontend-tools/background.tsx:

export const DEFAULT_BACKGROUND = "#4f46e5"; // solid indigo // <div>test("background container starts with the solid indigo default", async ({ page }) => { const bg = page.locator('[data-testid="frontend-tools-background"]'); const initial = await bg.getAttribute("style"); expect(initial ?? "").toContain("#4f46e5"); }); test("Forest theme pill mutates the background inline style", async ({ page }) => { await page.getByRole("button", { name: /Forest theme/i }).click(); const bg = page.locator('[data-testid="frontend-tools-background"]'); await expect.poll(async () => { const s = (await bg.getAttribute("style")) ?? ""; return !s.includes("#4f46e5"); }, { timeout: 45000 }).toBe(true); }); test("Sunset theme pill triggers a gradient change", async ({ page }) => { await page.getByRole("button", { name: /Sunset theme/i }).click(); const bg = page.locator('[data-testid="frontend-tools-background"]'); await expect.poll(async () => { const s = (await bg.getAttribute("style")) ?? ""; return /linear-gradient|radial-gradient/.test(s); }, { timeout: 45000 }).toBe(true); });

解读这三条测试的验证逻辑:

  • 默认态:背景内联样式含#4f46e5,确认初始画布干净;
  • Forest theme:点击 pill 后轮询内联样式,直到其不再包含默认值——说明change_background已被调用且setBackground生效;
  • Sunset theme:轮询到linear-gradientradial-gradient出现——说明 LLM 理解了「sunset gradient」并生成了合法渐变 CSS 值。

expect.poll的 45 秒超时覆盖了「前端注册 → 后端转换 → Claude 推理 → 工具回传 → handler 执行」的整条链路延迟。测试文件还注释了验证环境的分工:aimock feature-parity fixture 覆盖 "sunset-themed gradient" 提示词,真实 LLM 在 Railway 上处理自由文本提示词。

延伸:异步前端工具 query_notes 与更多组合场景

同一集成下还有一个异步版本 QA 文档 qa/frontend-tools-async.md,用于验证带asynchandler 的前端工具。其测试步骤为:导航到/demos/frontend-tools-async→ 让 Agent 查询笔记(如 "Look up my note about project kickoff")→ 验证query_notes工具触发并解析 → 验证 Agent 用解析出的笔记内容回复 → 无 console 错误。预期结果是「异步工具解析被正确等待并呈现,无 UI 错误」。

实现见 src/app/demos/frontend-tools-async/page.tsx,它与同步版的关键差异有三点:

  1. async handlerhandler: async ({ keyword }) => { await sleep(500); ... },模拟 500ms 的客户端数据库往返,返回{ keyword, count, notes }
  2. 本地假数据库fake-notes-db.ts中的NOTES_DB提供笔记数据,query_notes在标题、摘要、标签上进行大小写不敏感的模糊搜索并截取前 5 条;
  3. render 回调:额外的render: ({ args, result, status }) => ...让前端工具在「执行中(loading)」与「完成」两个状态渲染出NotesCard卡片,把工具状态可视化。

对应的 e2e 测试 tests/e2e/frontend-tools-async.spec.ts 与query_notes一起,构成了「异步前端工具」的完整验证闭环。由此可以推断,同一套useFrontendTool机制既支持同步副作用(改背景),也支持异步数据查询(查笔记),还可结合useRenderTool实现更复杂的生成式 UI 渲染;在 route.ts 的注册表中,「gen-ui-interrupt」等 demo 还用带 async handler 的useFrontendTool模拟 LangGraph 的interrupt()语义,说明这一机制足以承载「中断/恢复」类交互。

故障排查指引

当 QA 步骤失败时,可以按链路顺序排查:

现象可能原因排查入口
页面打不开Demo 未部署 / 路由错误确认/demos/frontend-tools可访问,检查 Next.js 部署状态
发送消息无响应Agent 后端不健康访问/api/copilotkit的 GET 探针,查看agent_statusANTHROPIC_API_KEY是否 set
工具不触发描述/schema 不佳检查change_backgrounddescription与 Zodparameters是否清晰
背景无变化handler 未执行或结果未回流观察浏览器 console;后端启用SHOWCASE_ROUTE_DEBUG=1查看每请求日志
Claude 收到空 schemaparametersJSON 解析失败查看后端console.warnbuildTools的失败告警)

其中SHOWCASE_ROUTE_DEBUG开关在 route.ts 中定义(默认关闭,设置为1true开启逐请求日志),而设置AGENT_URL可把代理指向任意后端实例(如本地调试端口)。

总结

从这篇 QA 文档出发,我们完整走通了 CopilotKit 前端工具(Frontend Tools)在 Claude Agent SDK (TypeScript) 集成中的全链路:前端用useFrontendTool注册工具与 handler(page.tsx),工具定义随 AG-UI run 输入经透传 Runtime(route.ts)到达后端,由buildTools转换为 Anthropic Messages API schema(agent_server.ts),Claude 决策调用后在浏览器端执行并把tool_result回流,最终由 Agent 总结确认。手动 QA 文档与 Playwright e2e 测试(frontend-tools.spec.ts)互为镜像,分别覆盖「人工体验」与「自动化回归」两种验证维度——这种「QA 文档 → 源码 → e2e 测试」三位一体的组织方式,本身就是前端工具类特性落地的最佳实践样板。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 6:05:27

人岗智能匹配实战:从排序问题到LightGBM精排模型

简介&#xff1a;第二届阿里巴巴大数据智能云上编程大赛的智联招聘人岗智能匹配赛题资料包&#xff0c;由荣获初赛、复赛、决赛均为第4名的OTTO团队整理&#xff0c;面向大数据竞赛爱好者与算法工程师&#xff0c;完整呈现了从数据预处理到模型调优的人岗匹配解决路径。包内共2…

作者头像 李华
网站建设 2026/9/12 6:04:45

MATLAB实现RBF分类器:从原理到工业应用实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 6:03:36

Radarr 电影海报管理:4 个最常踩的坑,项目里都给了默认解法

Radarr 电影海报管理&#xff1a;4 个最常踩的坑&#xff0c;项目里都给了默认解法 【免费下载链接】Radarr Movie organizer/manager for usenet and torrent users. 项目地址: https://gitcode.com/GitHub_Trending/ra/Radarr Radarr 是一款面向 Usenet 和 BitTorrent…

作者头像 李华