首页 / 资讯中心 / 文章详情

Cloudflare Workers 构建 AI Agent 边缘运行时实战指南

Cloudflare Workers 构建 AI Agent 边缘运行时实战指南 ★ FEATURED ARTICLE
1. 从标题说起cloudflare-os 到底是个什么东西第一次看到cloudflare-os这个标题我下意识以为 Cloudflare 又出了什么操作系统级别的产品。翻了一圈资料才反应过来这其实是一个基于 Cloudflare Workers 构建的、面向 AI Agent 场景的轻量级运行时框架。名字里带 “os”但它不是传统意义上管理硬件资源的操作系统更像是一套“给 AI 代理用的工作台”——把模型调用、任务编排、状态管理、工具接入这些事统一收拢到边缘节点上跑。这个定位很有意思。过去我们做 AI 应用习惯性思路是后端起一个服务部署到某台服务器或者容器里前端调接口。但 Cloudflare Workers 的模型是“边缘函数”代码跑在全球各地的节点上冷启动极快按请求计费天然适合那种“来一个请求、处理一下、返回结果”的 AI 交互场景。cloudflare-os想做的事就是把这套边缘能力包装成 AI Agent 的“操作系统层”让开发者不用自己从零搭调度逻辑。它解决的核心问题有三个。第一AI Agent 的响应延迟。传统架构里用户请求要绕一大圈到中心服务器再排队等模型返回边缘节点能把这个链路缩短。第二状态管理。Agent 需要记住上下文、维护会话Workers 生态里的 Durable Objects、KV、D1 这些存储组件刚好能接上。第三工具调用的统一入口。Agent 要调外部 API、读文件、执行代码cloudflare-os提供了一层抽象把这些能力标准化。适合谁来参考如果你正在做 AI 应用尤其是那种需要快速响应、全球分布、按量付费的产品这套思路值得研究。前端开发者想往全栈 AI 方向走Workers 生态的学习曲线也比传统后端友好。当然如果你只是本地跑个小脚本那没必要上这套杀鸡用牛刀。2. 整体设计思路拆解为什么是 Workers AI Agent2.1 边缘计算和 AI 推理的天然契合点AI Agent 的工作模式本质上是“感知—决策—行动”的循环。用户输入一句话Agent 要理解意图、决定调哪个工具、执行、把结果组织成自然语言返回。这个循环里最耗时的通常是模型推理和外部 API 调用但最影响体验的往往是网络延迟。Cloudflare Workers 的节点分布在全球数百个城市用户请求会被路由到最近的节点。这意味着 Agent 的“决策层”可以跑在离用户很近的地方只有真正需要大模型推理的那一步才回源到中心。实测下来这种架构能把首字节时间压到几十毫秒级别比传统“用户→中心服务器→模型→返回”的链路快不少。另一个契合点是计费模型。Workers 按请求数和 CPU 时间计费没有闲置成本。AI Agent 的流量往往有波峰波谷半夜没人用的时候传统服务器照样在烧钱Workers 则完全按实际消耗算。对于早期项目或者流量不稳定的场景这个成本结构友好很多。2.2 为什么选 pnpm 和 wrangler 这套工具链cloudflare-os的工程化部分绕不开 pnpm 和 wrangler。pnpm 是包管理器wrangler 是 Cloudflare 官方的 CLI 工具。为什么是这两个pnpm 的核心优势是磁盘空间和安装速度。它用硬链接的方式共享依赖同一个包在磁盘上只存一份多个项目引用时不会重复下载。对于 Workers 项目来说依赖体积直接影响部署包的冷启动时间pnpm 的严格依赖树也能避免“幽灵依赖”问题——就是那种你没在 package.json 里声明、但代码里能 import 到的包换环境就崩。wrangler 则是部署和本地开发的入口。它支持wrangler dev本地模拟 Workers 运行环境wrangler deploy一键发布到边缘。配置文件wrangler.toml里能定义路由、环境变量、KV 命名空间绑定、Durable Objects 等。这套工具链的成熟度是cloudflare-os能落地的前提。注意pnpm 在 Windows 环境下经常出现“无法将 pnpm 项识别为 cmdlet”的报错这不是 pnpm 本身的问题而是环境变量没配好。后面会专门讲排查方法。2.3 AI Agent 在边缘运行的核心挑战把 Agent 放到边缘节点不是没有代价。最大的挑战是状态一致性。Agent 需要记住对话历史、用户偏好、任务进度这些状态如果存在边缘节点的内存里用户下次请求路由到另一个节点就丢了。cloudflare-os的解法是用 Durable Objects——一种有状态的 Worker 实例每个对象有唯一 IDCloudflare 保证同一 ID 的请求总是路由到同一个节点。这样 Agent 的会话状态就能持久化同时保持边缘的低延迟。第二个挑战是模型调用的网络开销。边缘节点离用户近但离模型服务可能远。如果模型部署在某个中心区域边缘节点调用它还是要走公网。实践中常见的做法是轻量级意图识别、路由决策放在边缘重量级推理回源到模型所在区域。这种分层设计能平衡延迟和成本。第三个挑战是工具调用的安全性。Agent 要调外部 API密钥不能暴露在客户端。Workers 的环境变量机制可以把密钥存在服务端代码里通过env.SECRET_KEY读取不会打包进前端产物。这一点比纯前端方案安全得多。3. 核心细节解析与实操要点3.1 环境准备pnpm 安装与常见报错处理先把工具链搭起来。Node.js 版本建议 18 以上然后装 pnpm。官方推荐用 corepackcorepack enable corepack prepare pnpmlatest --activate如果 corepack 不可用用 npm 全局安装npm install -g pnpmWindows 用户最常见的报错是pnpm : 无法将“pnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。或者pnpm 不是内部或外部命令也不是可运行的程序或批处理文件。这说明 pnpm 的安装路径没加到系统 PATH 里。排查步骤先运行npm config get prefix看全局包安装到哪个目录然后把这个目录加到系统环境变量的 Path 里。Windows 上通常是C:\Users\你的用户名\AppData\Roaming\npm。加完之后重启终端不是新开标签页是彻底关掉重开。Ubuntu 下安装 pnpm 更简单curl -fsSL https://get.pnpm.io/install.sh | sh -装完记得source ~/.bashrc或者重开终端。如果网络环境导致下载失败可以用 npm 的镜像源或者直接下载 pnpm 的独立二进制包手动放到 PATH 目录。实操心得pnpm 离线安装的场景比如内网环境可以在一台有网的机器上pnpm store path找到存储目录整个拷过去然后pnpm install --offline。这个技巧在 CI/CD 流水线里很实用能省掉每次构建的下载时间。3.2 wrangler 配置与 Workers 项目初始化装好 pnpm 之后创建项目pnpm create cloudflarelatest my-agent这个命令会引导你选择模板。选 “Hello World” 起步就行后面自己加逻辑。生成的目录结构大概是my-agent/ ├── src/ │ └── index.ts ├── wrangler.toml ├── package.json └── tsconfig.jsonwrangler.toml是核心配置文件几个关键字段name my-agent main src/index.ts compatibility_date 2024-01-01 [[kv_namespaces]] binding AGENT_STATE id 你的KV命名空间ID [[durable_objects.bindings]] name SESSION class_name SessionObjectcompatibility_date决定 Workers 运行时的行为版本建议设成当前日期往前推一两个月避免用到还没稳定的特性。KV 命名空间用来存 Agent 的长期状态Durable Objects 用来存会话级的短期状态。本地开发用pnpm wrangler dev这会启动一个本地服务器模拟边缘环境。改代码会自动热重载。部署用pnpm wrangler deploy第一次部署会要求登录 Cloudflare 账号浏览器授权一下就行。3.3 Agent 核心逻辑的代码结构一个最简的 Agent 处理流程入口文件大概长这样export default { async fetch(request: Request, env: Env): PromiseResponse { const url new URL(request.url); if (url.pathname /chat) { const { message, sessionId } await request.json(); // 获取或创建会话对象 const session env.SESSION.get(env.SESSION.idFromName(sessionId)); // 读取历史上下文 const history await session.getHistory(); // 调用模型 const reply await callModel(message, history, env); // 保存上下文 await session.appendHistory(message, reply); return new Response(JSON.stringify({ reply }), { headers: { Content-Type: application/json } }); } return new Response(Not Found, { status: 404 }); } };这里的关键设计是会话隔离。每个sessionId对应一个 Durable Object 实例不同用户的上下文互不干扰。callModel函数里封装模型调用密钥从env读取不硬编码。注意Durable Objects 的idFromName方法同一个名字总是映射到同一个对象 ID这是保证会话一致性的基础。但名字不能太长也不能包含特殊字符建议用 UUID 或者用户 ID 的哈希值。3.4 状态存储的选型逻辑cloudflare-os涉及的状态分三层选型逻辑不一样状态类型存储方案适用场景读写延迟会话上下文Durable Objects对话历史、任务进度极低同节点用户配置KV偏好设置、API 密钥低全球缓存结构化数据D1用户表、日志、统计中等SQL 查询大文件R2图片、文档、模型文件低对象存储Durable Objects 适合“强一致、高频读写”的场景比如对话历史每次请求都要读要写。KV 适合“读多写少”的配置类数据它的全球缓存能让读取几乎无延迟但写入有最终一致性延迟。D1 是 SQLite 的托管版适合需要复杂查询的场景。R2 兼容 S3 API存大文件比 KV 便宜。选型的时候先问自己这个数据多久变一次变了之后多久必须生效需不需要跨会话查询回答完这三个问题方案基本就定了。4. 实操过程与核心环节实现4.1 从零搭建一个最小可用的 AI Agent假设我们要做一个“旅游助手” Agent用户问“帮我规划三天北京行程”Agent 要能调外部 API 查景点、查天气然后组织成回答。完整流程拆解第一步初始化项目pnpm create cloudflarelatest travel-agent cd travel-agent pnpm add honoHono 是一个轻量级 Web 框架在 Workers 上跑很合适路由和中间件写起来比原生 fetch 舒服。第二步定义 Agent 的“工具”Agent 要调外部 API先把工具函数写好async function searchAttractions(city: string, env: Env) { const resp await fetch( https://api.example.com/attractions?city${city}, { headers: { Authorization: Bearer ${env.TRAVEL_API_KEY} } } ); return resp.json(); } async function getWeather(city: string, date: string, env: Env) { const resp await fetch( https://api.example.com/weather?city${city}date${date}, { headers: { Authorization: Bearer ${env.WEATHER_API_KEY} } } ); return resp.json(); }密钥都存在 Workers 的环境变量里通过wrangler secret put TRAVEL_API_KEY命令设置不会出现在代码仓库里。第三步实现意图识别和工具路由用户输入是自然语言Agent 要先判断该调哪个工具。这里可以用一个小模型做意图分类也可以用规则匹配。规则匹配的版本function routeIntent(message: string): string { if (message.includes(景点) || message.includes(玩)) return attractions; if (message.includes(天气) || message.includes(下雨)) return weather; return general; }规则匹配简单但不够灵活适合早期验证。后面可以换成小模型做分类把意图识别的准确率提上去。第四步组装上下文并调用大模型async function callModel(message: string, context: any[], env: Env) { const systemPrompt 你是一个旅游助手根据以下信息回答用户问题。 景点数据${JSON.stringify(context.attractions)} 天气数据${JSON.stringify(context.weather)}; const resp await fetch(https://api.openai.com/v1/chat/completions, { method: POST, headers: { Authorization: Bearer ${env.OPENAI_API_KEY}, Content-Type: application/json }, body: JSON.stringify({ model: gpt-4o-mini, messages: [ { role: system, content: systemPrompt }, { role: user, content: message } ] }) }); const data await resp.json(); return data.choices[0].message.content; }这里用gpt-4o-mini是因为它在边缘场景下延迟和成本的平衡比较好。如果对质量要求更高可以换更大的模型但延迟会上去。第五步部署和验证pnpm wrangler deploy部署完会得到一个*.workers.dev的域名直接 curl 测试curl -X POST https://travel-agent.你的子域.workers.dev/chat \ -H Content-Type: application/json \ -d {message:北京三天怎么玩,sessionId:test-001}第一次请求会稍慢因为要初始化 Durable Object。后续同一 sessionId 的请求会快很多。4.2 多 AI 协作的编排模式单个 Agent 能力有限复杂任务需要多个 Agent 协作。cloudflare-os的架构里可以用 Durable Objects 做“协调者”把任务拆给不同的子 Agent。比如一个“写报告”的任务一个 Agent 负责查资料一个负责写初稿一个负责审校。协调者维护任务状态按顺序调用子 Agent把上一个的输出作为下一个的输入。class Coordinator { async run(task: string) { const research await this.callAgent(researcher, task); const draft await this.callAgent(writer, research); const review await this.callAgent(reviewer, draft); return review; } async callAgent(name: string, input: string) { const agent this.env.AGENTS.get(this.env.AGENTS.idFromName(name)); return agent.process(input); } }这种编排模式的好处是每个 Agent 可以独立部署、独立扩缩容。坏处是链路变长延迟增加。实践中要权衡简单任务单 Agent 搞定复杂任务才上多 Agent。实操心得多 Agent 协作时上下文传递容易丢信息。我的做法是在每个 Agent 的输出里强制包含一个summary字段用一两句话概括核心结论下一个 Agent 优先读 summary需要细节再读全文。这样能控制 token 消耗也能避免上下文窗口溢出。4.3 性能优化的几个关键参数Workers 的 CPU 时间有限制免费版每次请求 10ms付费版 30s可配置到 5 分钟。AI Agent 的模型调用是网络等待不计入 CPU 时间但 JSON 解析、字符串处理这些是算的。优化方向减少不必要的序列化。上下文传递时能传引用就不传完整对象。用流式响应。模型返回是流式的Workers 支持ReadableStream边收边发给用户首字节时间能大幅降低。缓存高频结果。天气、景点这类数据变化不频繁用 KV 缓存设置合理的 TTL。控制上下文长度。对话历史不能无限增长超过一定轮数就做摘要压缩。流式响应的代码示例const stream new ReadableStream({ async start(controller) { const modelStream await callModelStream(message, env); for await (const chunk of modelStream) { controller.enqueue(new TextEncoder().encode(chunk)); } controller.close(); } }); return new Response(stream, { headers: { Content-Type: text/event-stream } });这个改动对用户体验的提升很明显用户不用等完整回答生成完才看到内容。5. 常见问题与排查技巧实录5.1 pnpm 相关报错速查报错信息原因解决方法pnpm 不是内部或外部命令PATH 未配置把 npm 全局目录加到系统 Path重启终端pnpm install卡住不动网络问题换镜像源pnpm config set registry https://registry.npmmirror.comERR_PNPM_NO_MATCHING_VERSION版本冲突删掉pnpm-lock.yaml和node_modules重装pnpm store占用过大缓存累积pnpm store prune清理未引用的包离线安装失败store 不完整确保 store 目录完整拷贝用--offline标志Windows 上还有一个坑如果同时装了 npm 和 pnpm有时候命令会冲突。建议用 corepack 管理它能确保每个项目用对应版本的包管理器。5.2 Workers 部署常见错误错误一Script exceeded memory limitWorkers 有 128MB 内存限制。如果 Agent 加载了太大的依赖或者处理了超大 JSON就会触发。解决方法是拆分逻辑把重活放到 Durable Objects 或者外部服务。错误二Durable Object reset because its code was updated每次部署新代码Durable Objects 会重启内存里的状态丢失。所以重要状态必须持久化到 storage不能只放内存。错误三KV PUT failed: 429 Too Many RequestsKV 写入有频率限制同一 key 每秒最多写一次。如果 Agent 高频更新状态改用 Durable Objects 的 storage它没有这个限制。错误四CORS error前端直接调 Workers 域名会遇到跨域。在 Worker 里加 CORS 头const corsHeaders { Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET, POST, OPTIONS, Access-Control-Allow-Headers: Content-Type };OPTIONS 请求直接返回 204别走后面的逻辑。5.3 AI Agent 特有的坑上下文污染。多轮对话里如果历史消息里有错误信息模型会跟着错。我的做法是每轮对话后做一次“事实校验”把明显矛盾的内容标记出来下一轮提示模型忽略。工具调用死循环。Agent 调工具失败后重试如果没设上限会无限循环烧钱。必须设最大重试次数比如 3 次超过就返回兜底回答。模型输出格式不稳定。要求模型返回 JSON它有时候会加 markdown 代码块标记。解析前先做清洗function cleanJSON(text: string): string { return text.replace(/json\n?/g, ).replace(/\n?/g, ).trim(); }密钥泄露风险。永远不要把密钥写在前端代码或者公开仓库里。Workers 的env机制是安全的但要注意wrangler.toml里不要明文写密钥用wrangler secret put命令设置。踩过的坑有一次我把 API 密钥写在wrangler.toml的[vars]里以为没问题结果部署后发现这个文件会被打包进产物。后来改成wrangler secret put才解决。[vars]只适合放非敏感的配置比如功能开关、环境名称。6. 这套架构的边界与扩展方向cloudflare-os这套思路不是万能的。它的优势在“轻量、快速、全球分布”但如果你要做的是重计算任务比如本地跑大模型推理、处理超大文件Workers 的限制就会成为瓶颈。这时候更合适的方案是混合架构边缘做路由和轻量处理重活回源到传统服务器或者 GPU 集群。扩展方向上有几个值得关注的点。一是AI Agent 的可观测性现在调试 Agent 很痛苦不知道它为什么调了某个工具、为什么给出某个回答。可以在 Workers 里加日志埋点把每步决策记录到 D1后面做分析。二是Agent 之间的通信协议多 Agent 协作时消息格式、任务描述、结果返回需要标准化不然每接一个新 Agent 就要改协调者代码。三是成本控制Agent 调模型是按 token 计费的要有机制监控每个会话的消耗超预算就降级到小模型或者直接返回缓存结果。我个人在实际操作中的体会是这套东西最适合快速验证想法。以前搭一个 AI 应用原型要几天现在用 Workers Durable Objects半天就能跑起来一个能用的版本。但要从原型走到生产状态管理、错误处理、成本控制这些细节一个都不能少。边缘计算给了我们很好的起点但终点还是要回到工程化的老路上来。
阅读完成 · 觉得有帮助?
咨询建站