` 全解析:为 Agent 打造基于 WebSocket 的 RPC 方法层)
【免费下载链接】autoskillsOne command. Your entire AI skill stack. Installed.项目地址https://gitcode.com/gh_mirrors/au/autoskills点击查看免费下载callable()是 Cloudflare Agents SDK 中把 Agent 内部方法通过 WebSocket RPC 暴露给客户端的关键装饰器它让浏览器、移动端乃至外部服务都能以函数调用的形式驱动云端 Agent。本文以仓库中 callable.md 为核心骨架结合 SKILL.md、api.md 与 gotchas.md 等仓库资料完整讲解装饰器用法、客户端调用、流式响应、方法自省与生产级注意事项读完即可在 Workers 上搭建一套带类型安全、可流式返回、可超时控制的 RPC 接口。概览一条注解打通客户端 → Agent的 RPC 通道在 Cloudflare Agents SDK 中每个 Agent 实例实际上是一个 Durable Object天然具备跨网络寻址、持久化状态与长连接能力。callable()的作用就是把这些能力收敛成可被远程调用的方法被它标记的 Agent 方法会被自动注册进 Agent 的 WebSocket RPC 协议客户端连接上之后可以直接按方法名发起调用就像调用本地函数一样。仓库中 SKILL.md 将 Callable RPC ——callable()methods invoked over WebSocket 列为 SDK 的核心能力之一并给出最简单的 RPC 方法写法import { Agent, routeAgentRequest, callable } from agents; type State { count: number }; export class Counter extends AgentEnv, State { initialState { count: 0 }; callable() increment() { this.setState({ count: this.state.count 1 }); return this.state.count; } } export default { fetch: (req, env) routeAgentRequest(req, env) ?? new Response(Not found, { status: 404 }) };这里increment()既能通过 WebSocket RPC 被客户端调用也能在方法体内使用this.setState读写持久化状态还能通过this.state.count读取当前状态——RPC 方法与 Agent 状态系统是天然打通的。最小可运行的 Agent 骨架要支撑上面的代码wrangler.jsonc中需要同时配置 Durable Object 绑定与 SQLite 迁移详见 configuration.md{ name: my-agent, main: src/index.ts, compatibility_date: 2025-01-28, compatibility_flags: [nodejs_compat], durable_objects: { bindings: [ { name: Counter, class_name: Counter } ] }, migrations: [ { tag: v1, new_sqlite_classes: [Counter] } ] }两个关键规则每个 Agent 类都必须同时拥有一个 DO 绑定和一条new_sqlite_classes迁移记录nodejs_compat兼容性标志是必需的。另外SKILL.md 特别警告不要在 tsconfig 中开启experimentalDecorators否则会破坏callable()装饰器的正常工作。基础用法定义可调用的 Agent 方法来自 callable.md 的完整示例展示了最常规的两种方法形态——普通函数调用与承载长耗时任务的方法import { Agent, callable } from agents; export class MyAgent extends AgentEnv, State { callable() async greet(name: string): Promisestring { return Hello, ${name}!; } callable() async processData(data: unknown): PromiseResult { // Long-running work return result; } }要点参数按位置传递客户端调用时以数组形式传入参数服务端方法按声明顺序接收。返回值必须可 JSON 序列化仓库 gotchas.md 专门列出过 callable method returns undefined 这一典型问题根因正是方法返回了不可序列化的值。比如返回new Date()实例会出问题应改为返回{ timestamp: Date.now() }这类纯对象/数组/基本类型// ❌ 返回类实例RPC 无法序列化 callable() async getData() { return new Date(); } // ✅ 返回可序列化对象 callable() async getData() { return { timestamp: Date.now() }; }长任务放在 async 方法里processData这类需要较长时间的处理可以安全地在 Agent 侧异步执行客户端用超时参数控制等待。仓库 api.md 中还有一个将 RPC 与 Workers AI 结合的实战示例展示了callable()方法内部如何访问绑定资源import { Agent, callable } from agents; export class MyAgent extends AgentEnv { callable() async processTask(input: { text: string }): Promise{ result: string } { return { result: await this.env.AI.run(cf/meta/llama-3.1-8b-instruct, { prompt: input.text }) }; } } // 客户端const result await agent.processTask({ text: Hello });这印证了一个重要设计RPC 方法体内可以自由使用this.env绑定的任意资源Workers AI、KV、队列、MCP 等对外暴露的只是一层薄薄的 JSON 接口。客户端调用基本调用与超时控制服务端定义好callable()方法后客户端通过agent.call(methodName, args, options)触发调用// 基本调用 const greeting await agent.call(greet, [World]); // 带超时控制 const result await agent.call(processData, [data], { timeout: 5000 // 5 秒超时 });timeout以毫秒为单位适合对长耗时任务设置合理的等待上限避免客户端无限期挂起。三种客户端形态根据 client-sdk.mdRPC 客户端并不只有agent.call一种1. ReactuseAgent 类型化 stubimport { useAgent } from agents/react; const agent useAgenttypeof MyAgent({ agent: MyAgent, name: default }); const result await agent.stub.myMethod(arg1, arg2);agent.stub是基于typeof MyAgent推导出的类型化 RPC 句柄方法名与参数都能获得编译期校验——这是最推荐的类型安全写法。2. 原生 JSAgentClientimport { AgentClient } from agents/client; const client new AgentClient({ agent: MyAgent, name: default, host: https://my-worker.workers.dev }); client.addEventListener(stateUpdate, (e) console.log(e.state)); const result await client.call(myMethod, [arg]); client.close();适合非 React 环境Node 脚本、移动端、嵌入式 WebView同样使用call(methodName, [args])协议。3. HTTP-onlyagentFetchimport { agentFetch } from agents/client; const response await agentFetch({ agent: MyAgent, name: default, host: https://my-worker.workers.dev, path: /api/data });当不需要长连接、只想做一次性 HTTP 请求时使用。调用前先理解路由客户端能连上 Agent 实例的前提是路由正确。按 routing.md默认 URL 模式为/agents/{kebab-class-name}/{instance-name}例如类Counter对应/agents/counter/user-123。因此客户端useAgent({ agent: Counter, name: user-123 })中的agent与name必须和 DO 绑定类名、URL 中的实例名精确匹配。类名MyAgent在 URL 中会变成 kebab 形式my-agent拼错就会遇到 Namespace not found 错误——该错误通常意味着 wrangler 里的class_name与导出的类名不一致。流式响应用StreamingResponse实现增量推送对于搜索结果、日志流、逐 token 输出这类无法一次性返回的场景callable()支持流式模式。服务端方法签名中第一个参数固定为StreamingResponse后续才是业务参数import { Agent, callable, StreamingResponse } from agents; export class MyAgent extends AgentEnv, State { callable({ streaming: true }) async streamResults(stream: StreamingResponse, query: string) { for await (const item of fetchResults(query)) { stream.send(JSON.stringify(item)); } stream.close(); } callable({ streaming: true }) async streamWithError(stream: StreamingResponse) { try { // ... work } catch (error) { stream.error(error.message); // 向客户端发出错误信号 return; } stream.close(); } }流式模式的生命周期由三个方法控制stream.send(data)向客户端推送一块数据多个分块按顺序到达stream.close()正常结束表示流已完整stream.error(message)主动向客户端发出错误信号后结束客户端会收到onError回调。streamResults展示的是边拉取边转发的数据管道模式例如把上游分页结果逐页推给客户端streamWithError则演示了错误路径一旦中途失败用stream.error明确告知客户端而不是默默断开。客户端消费流await agent.call(streamResults, [search term], { stream: { onChunk: (data) console.log(Chunk:, data), onDone: () console.log(Complete), onError: (error) console.error(Error:, error) } });三个回调与三个服务端方法一一对应每收到一个分块触发onChunk、流正常结束触发onDone、发生错误触发onError。这比轮询式拉取增量要自然得多特别适合聊天补全、日志 tail、实时状态推送等场景。仓库 client-sdk.md 中的流式调用示例与此完全一致。需要提醒的是如果业务是AI 对话逐 token 输出SDK 更推荐直接使用AIChatAgent自动处理流式与断线续传手写streaming: true的callable更适用于自定义协议的增量数据推送。若确需手动实现可续传流gotchas.md 指出stream ID 必须是确定性的续传才能生效。方法自省getCallableMethods为了支持动态发现能力例如构建通用调试面板、自动生成客户端 SDK、实现方法级权限检查Agent 内置了getCallableMethods这个可调用方法客户端无需预先知道方法列表即可枚举// 获取 Agent 上所有可调用方法 const methods await agent.call(getCallableMethods, []); // 返回: [greet, processData, streamResults, ...]返回结果是方法名字符串数组包含所有被callable()标记的方法。它可以配合超时、流式等选项一起使用是构建自描述 Agent的基础设施。何时使用选对 RPC 通道不是所有跨 Agent 通信都要走callable()。callable.md 给出的选型表非常实用场景使用方式浏览器 / 移动端调用 Agentcallable()外部服务调用 Agentcallable()Worker 调用 Agent同一代码库内DO RPC 直连Agent 调用另一个 AgentgetAgentByName() DO RPC判断依据很简单只要调用方是外部浏览器、移动端、第三方服务就应使用callable()因为它把复杂的 WebSocket 握手、序列化、鉴权统一收敛成方法调用而同一部署内的 Worker 之间、Agent 之间直接走 Durable Object RPC 或getAgentByName(env.MyAgent, instance-id)更高效无需绕道 WebSocket 协议详见 routing.md。生产级注意事项1. 类型安全useAgenttypeof MyAgentagent.stub是首选的类型化调用方式若使用原生AgentClient.call则方法名与参数都是字符串/数组形态需要自行保证类型一致。2. 返回值可序列化再次强调RPC 返回值必须是 JSON 可序列化的普通对象/数组/基本类型。避免返回类实例、Date对象、Map/Set、函数或循环引用结构否则会触发 method returns undefined 一类问题见 gotchas.md。3. 鉴权与超时鉴权建议在路由层统一处理routeAgentRequest(req, env, { onBeforeConnect, onBeforeRequest })可在握手与请求前做校验见 routing.md客户端则可通过query参数携带 token。长任务务必设置timeout避免调用方无限等待服务端也要注意 CPU 限额标准 30s最长 300s在wrangler.jsonc中配置。4. 状态更新的不可变写法在callable()方法内修改状态时遵循 gotchas.md 的黄金法则——不要直接 mutate始终用不可变更新// ❌ this.state.count // ✅ this.setState({...this.state, count: this.state.count 1})5. 依赖配置检查清单上线前对照 SKILL.md 与 configuration.md 检查npm ls agents确认agents包已安装未安装则npm install agentswrangler.jsonc中每个 Agent 类都有 DO 绑定 new_sqlite_classes迁移条目且绝不修改旧迁移新增类时追加新 tag未开启experimentalDecorators需要 AI 能力时配置ai: { binding: AI }类型变更后重新生成npx wrangler types。总结callable()是 Cloudflare Agents SDK 面向外部世界的接口层一条装饰器即可让 Agent 的方法通过 WebSocket RPC 被浏览器、移动端和第三方服务安全调用配套的timeout控制调用等待、streaming: trueStreamingResponse支撑增量推送、getCallableMethods提供运行时自省。配合类型化的agent.stub、JSON 可序列化约束以及 Worker 之间走 DO RPC 直连 的选型原则你就能在 Workers 上构建出接口清晰、可远程驱动、可观测的 Agent 服务。相关主题还可继续阅读仓库中的 routing.md路由与鉴权、client-sdk.md全部客户端形态与 streaming-chat.mdAI 对话流式方案。赞分享【免费下载链接】autoskillsOne command. Your entire AI skill stack. Installed.项目地址https://gitcode.com/gh_mirrors/au/autoskills点击查看免费下载相关推荐Cloudflare Agents 的 callable() 方法用 WebSocket RPC 让浏览器与移动端直接调用 AgentCloudflare Agents 的 callable 方法用 WebSocket RPC 让浏览器与移动端直接调用 Agent 导读 callableAI AgentAgent 框架后端云原生MCP 服务实时通信diagrams 自定义节点内置图标库缺什么就用 Custom 节点画什么手把手diagrams 自定义节点内置图标库缺什么就用 Custom 节点画什么手把手 diagrams 是一个用 Python 代码绘制云架构图的库Dia数据可视化开发工具文档Cloudflare Agents 的 cloudflare/think基于 Durable Object SQLite 的全生命周期 Chat Agent 实战指南Cloudflare Agents 的 cloudflare/think基于 Durable Object SQLite 的全生命周期 Chat AgentAI AgentAgent 框架后端云原生MCP 服务实时通信上一篇如何高效开发QSP游戏JavaQuestPlayer终极实战指南下一篇Higress 贡献指南全解从 Issue 提报到 AI 代理贡献门禁的完整协作规范创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考