实战:让 LangGraph TypeScript Agent 调用你 React 应用里的函数)
CopilotKit 前端工具In-App Actions实战让 LangGraph TypeScript 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本文以 CopilotKit 仓库中 LangGraph TypeScript 集成下的 Frontend Tools 演示为蓝本讲解“前端工具又称 In-App Actions”的完整机制如何在 React 组件中通过useFrontendTool注册一个浏览器端可执行的工具、CopilotKit 如何自动将该工具“宣告”给 Agent、以及 LangGraph 后端如何把这些前端工具绑定进模型调用。读完本文你可以掌握前端工具的注册参数、运行时转发链路、后端图代码的接入点以及如何用 Playwright 端到端测试验证工具触发的真实副作用。这个演示展示什么Frontend Tools前端工具a.k.a. “in-app actions”让 Agent 能够调用运行在你 React 应用内部的函数。Agent 基于自然语言对话自主推理“何时”调用它们——你不需要在 Prompt 里手写调用逻辑也不需要把函数部署到服务端。在这个演示演示目录中注册的唯一定制工具是change_background它接收一个 CSSbackground值纯色或渐变把整页背景改成该值。README 中给出的交互方式是尝试对 Agent 说Change the background to a blue-to-purple gradient把背景改成蓝紫渐变Make the background a sunset theme换成日落主题背景Set the background to black把背景设为黑色此外演示还通过建议卡片suggestion pills暴露了三个可一键发送的预设提示词见后文 suggestions.ts。前端用 useFrontendTool 注册工具核心实现位于 page.tsx。页面顶层是一个Chat客户端组件它用useState持有当前背景值然后调用useFrontendTool注册工具use client; import React, { useState } from react; import { CopilotKit, CopilotSidebar, useFrontendTool, } from copilotkit/react-core/v2; import { z } from zod; import { Background, DEFAULT_BACKGROUND } from ./background; import { useFrontendToolsSuggestions } from ./suggestions; function Chat() { const [background, setBackground] useStatestring(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 }; }, }); useFrontendToolsSuggestions(); return ( Background background{background} CopilotSidebar agentIdfrontend_tools defaultOpen / /Background ); } export default function FrontendToolsDemo() { return ( CopilotKit runtimeUrl/api/copilotkit agentfrontend_tools Chat / /CopilotKit ); }对照 README 中的最小示例这里有几个值得注意的参数细节字段作用本演示中的取值要点name工具名Agent 通过它识别和调用该工具change_backgrounddescription给模型看的工具说明直接决定 Agent 何时调用它明确说明“接受任何合法 CSS background 值——颜色、线性/径向渐变等”parameters用 Zod schema 声明参数类型与约束最终会被转成工具 schema 转发给 Agentbackground: z.string()并用.describe(Prefer gradients)引导模型优先输出渐变handler实际执行的客户端函数接收解析后的参数返回结果会作为工具结果回传调用setBackground更新 React state返回{ status: success }几个从源码可以直接确认的设计点handler 在浏览器端执行。handler闭包捕获了Chat组件的setBackground所以工具调用成功后直接改写 React 状态页面内联样式随之更新整个过程不经过任何自定义服务端代码。工具由 CopilotKit 自动宣告给 Agent。你只需在组件里调用useFrontendTool工具的名称、描述、Zod 参数 schema 会被序列化后随请求转发给运行时和 Agent——README 原话即“CopilotKit automatically advertises the tool to the agent”。外层CopilotKitProvider 的agentfrontend_tools与CopilotSidebar的agentIdfrontend_tools指向同一个后端 Agent。这个对应关系在后端路由里显式注册见下文。背景容器与默认值背景渲染封装在 background.tsxexport const DEFAULT_BACKGROUND #4f46e5; // 默认纯色 indigo export function Background({ background, children }: { background: string; children?: React.ReactNode; }) { return ( div >useConfigureSuggestions({ 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, });点击任意一个 pill对应的 message 会作为用户消息发送给 AgentAgent 再决定是否调用change_background。运行时链路前端工具如何到达 Agent前端注册的useFrontendTool只是一个“本地声明”真正把工具送到 Agent 手里的是 CopilotKit 运行时。在本集成中链路如下各环节均有源码可查前端 → 运行时CopilotKit runtimeUrl/api/copilotkit把请求发到 Next.js 的 runtime 路由。该路由用createCopilotRuntimeHandler构造 handlermode: single-route其中agents表把前端 agent 名映射到具体的LangGraphAgent。Agent 名映射route.ts 中demoAgents显式注册了frontend_tools: frontend_tools即前端agentfrontend_tools会绑定到名为frontend_tools的图。LangGraphAgent通过deploymentUrl默认http://localhost:8123可用LANGGRAPH_DEPLOYMENT_URL覆盖经 AG-UI 协议与独立进程中的 LangGraph CLI 服务通信。图注册langgraph.json 中frontend_tools: ./frontend-tools.ts:showcaseGraph声明了图入口server.mjs 中同样有frontend_tools: ./frontend-tools.ts:graph的注册项另有frontend_tools_async对应异步版演示属于另一个 demo本文不展开。运行时 → AgentCopilotKit 把前端工具 schema 放进状态通道state.copilotkit.actions转发给 Agent。Agent 侧用convertActionsToDynamicStructuredTools把它们转成 LangChain 工具再bindTools到模型上——详见下一节。后端LangGraph 图中绑定前端工具Agent 图代码位于 frontend-tools.ts。文件开头的注释概括了整个机制“The demo is about frontend tools — the agent has no custom backend tools. CopilotKit forwards the frontend tool schemas to the agent at runtime viastate.copilotkit.actions; the agent binds them when invoking the model, and the handler executes in the browser.”关键实现frontend-tools.tsimport { convertActionsToDynamicStructuredTools, CopilotKitStateAnnotation, } from copilotkit/sdk-js/langgraph; // CopilotKitStateAnnotation 为图状态加上 copilotkit.actions 通道 const AgentStateAnnotation CopilotKitStateAnnotation; export type AgentState typeof AgentStateAnnotation.State; async function runChatNode( state: AgentState, config: RunnableConfig, model: ChatOpenAI, ) { // 把运行时转发来的前端工具 schema 转成 LangChain 工具并绑定给模型 const modelWithTools model.bindTools!([ ...convertActionsToDynamicStructuredTools(state.copilotkit?.actions ?? []), ]); const response await modelWithTools.invoke( [new SystemMessage({ content: SYSTEM_PROMPT }), ...state.messages], config, ); return { messages: response }; }三个要点CopilotKitStateAnnotation给StateGraph的状态增加copilotkit.actions通道这是前端工具 schema 进入图的唯一入口convertActionsToDynamicStructuredTools在“调用模型的那一刻”把 actions 转换成动态的结构化工具列表因此每次请求绑定的工具集都与当前页面实际注册的前端工具一致——图本身没有硬编码任何工具图的编译非常薄StateGraph → START → chat_node → __end__配MemorySavercheckpointerfrontend-tools.ts。模型是ChatOpenAIgpt-4o-minitemperature: 0系统提示仅一句 You are a helpful, concise assistant.。另外文件中导出两个图graph最简版本便于复制粘贴与showcaseGraphfrontend-tools.ts 中通过makeChatOpenAI(config, ...)保留入站x-*头转发供 showcase 的探测链路使用。langgraph.json 注册的正是showcaseGraph。端到端测试断言副作用而非 LLM 文本该演示配有一个 Playwright 端到端测试 frontend-tools.spec.ts其头部注释明确写出了验证策略“We assert on the observable side effect (inline style changes) rather than on any LLM-generated text.” 测试覆盖四件事页面加载后聊天输入框与背景容器[data-testidfrontend-tools-background]均可见初始内联样式包含默认色#4f46e5Sunset / Forest / Cosmic 三个建议按钮均可渲染点击 Forest 或 Sunset pill 后轮询expect.poll45s 超时背景style属性Forest 场景断言样式不再包含#4f46e5Sunset 场景断言样式匹配/linear-gradient|radial-gradient/。这种“断言 DOM 副作用 轮询”的写法是验证前端工具是否真正被 Agent 触发执行的可靠手段不关心 Agent 说了什么只关心change_background的 handler 是否把页面状态改了。小结前端工具的最小契约把 README 与源码放在一起看前端工具In-App Actions的最小契约可以归纳为四层每层都有明确的责任边界注册层React 组件useFrontendTool({ name, description, parameters, handler })parameters用 Zod 描述handler 在浏览器内执行副作用宣告层CopilotKit 客户端/运行时工具 schema 自动随请求转发Agent 无需开发者手工宣告绑定层LangGraph 图CopilotKitStateAnnotation承接state.copilotkit.actionsconvertActionsToDynamicStructuredToolsmodel.bindTools完成每次调用的动态绑定验证层E2E 测试断言工具 handler 造成的可观测副作用内联样式变化而非模型文本。如果你的场景需要异步执行的工具handler 返回 Promise、结果稍后回填仓库中还有配套的frontend_tools_async图与 frontend-tools-async 演示可作为下一篇实践的直接素材。【免费下载链接】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),仅供参考