基于Cloudflare边缘计算构建AI Agent运行环境实战

发布时间:2026/10/28 4:15:41
基于Cloudflare边缘计算构建AI Agent运行环境实战 1. 从cloudflare-os这个标题说起它到底在指什么第一次看到cloudflare-os这个词我下意识以为是某个把操作系统搬到浏览器里的项目。毕竟OS这两个字母太容易让人联想到内核、进程调度、文件系统那一套。但把关键词里的 Cloudflare Workers、AI、agent、open source 摆在一起看方向就清楚了这里的OS不是传统意义上的操作系统而是面向 AI Agent 的一套运行底座——把 Cloudflare 的边缘网络当成硬件把 Workers 当成进程运行时把各类 AI 能力当成系统调用最终给 agent 提供一个可以长期驻留、随时被唤醒、按需调用工具的操作系统式环境。这个理解不是凭空来的。Cloudflare 这几年在边缘计算上的布局本质上就是在做一层分布式操作系统Workers 负责计算Durable Objects 负责有状态的对象和协调KV 负责键值存储R2 负责对象存储D1 负责关系型数据Queues 负责消息AI Gateway 负责模型调用的统一入口Vectorize 负责向量检索。把这些拼起来你会发现它天然就是一套给 agent 用的系统资源。所谓 cloudflare-os我倾向于把它理解成一套约定和编排方式让 agent 能像程序调用操作系统 API 一样去调用这些边缘能力。为什么这个方向值得关注因为现在做 agent 的人普遍卡在同一个地方本地跑个 demo 很爽一旦要 7x24 在线、要处理并发、要保存记忆、要接各种工具就得自己搭服务器、配数据库、搞定时任务、做鉴权。这套运维成本对个人开发者和小团队来说非常劝退。而边缘运行时的出现恰好把部署这件事压缩成了一条命令。你写的是一个函数部署完它就在全球几百个节点上待命冷启动在毫秒级按调用次数计费没人访问就不花钱。对 agent 这种平时安静、偶尔爆发的负载来说计费模型和运行模型都对得上。所以这篇内容我想聊的不是某个具体仓库的源码逐行解读而是如何用 Cloudflare 这套边缘能力搭出一个真正能用的 agent 运行环境。我会把架构拆开讲把每一步为什么这么做讲清楚也会把我自己踩过的坑摊开说。适合已经写过简单 agent demo、想把它变成能长期跑的服务的开发者也适合对边缘计算感兴趣、想找个真实场景上手的人。基础概念我会补但不会从什么是 HTTP讲起。2. 为什么 agent 需要一个操作系统而不是一个脚本2.1 脚本式 agent 的天花板在哪里大部分人写 agent 的起点是一个 Python 脚本读用户输入拼 prompt调模型解析工具调用执行工具把结果塞回去循环。这个结构在单轮、单用户、短任务场景下完全够用。但只要需求稍微真实一点问题就成串冒出来。第一个问题是状态无处安放。脚本跑完进程就没了对话历史、任务进度、中间结果全在内存里下次启动一切归零。你可能会说那就存文件或者存数据库但一旦涉及多用户并发文件锁、连接池、事务隔离这些事就全来了你写的已经不是 agent而是一个后端服务。第二个问题是调度。agent 经常需要等一会儿再做——等一个外部 API 回调、等一个长任务完成、等定时触发。脚本模式下你只能sleep进程挂着占资源或者上 cron但 cron 的粒度、时区、失败重试都是坑。第三个问题是工具调用的隔离与鉴权。agent 要调搜索、调数据库、调第三方 API每个工具都有自己的密钥。密钥放哪放环境变量在本地还行部署到服务器就得考虑密钥管理、权限最小化、调用审计。第四个问题是成本与弹性。agent 的流量极不均匀可能一天没人用也可能某一小时涌进来几千次调用。常驻服务器要么闲置浪费要么峰值被打爆。2.2 边缘运行时为什么天然适合当这层底座把上面四个问题对照 Cloudflare 的能力看会发现对应关系非常整齐。状态问题对应Durable Objects。它是有状态的单实例对象同一个 ID 永远路由到同一个实例天然适合存会话、做协调、当每个用户一个 agent 实例的载体。你不需要自己搞分布式锁DO 本身就是串行处理请求的。调度问题对应Workers 的 Cron Triggers 和 Queues。定时任务直接配 cron 表达式消息队列做异步解耦和重试长任务拆成消息一步步推进不用挂着进程等。工具鉴权对应Workers 的 Secrets 和 Service Bindings。密钥加密存储运行时注入内部服务之间用 binding 直连不走公网天然隔离。成本弹性对应按请求计费 全球边缘。没有请求就没有计算冷启动毫秒级峰值自动分摊到全球节点。提示Durable Objects 的计费里有一项持续时间长连接或长时间持有会持续计费。如果你的 agent 需要长时间等待优先用 alarm 唤醒而不是保持连接。2.3 OS这个比喻的边界我得说清楚把它叫 OS 是类比不是等价。真正的操作系统管的是 CPU 时间片、内存页、文件描述符、进程间通信这些底层资源。Cloudflare 这套东西管的是请求路由、状态持久化、消息传递、模型调用。它没有抢占式调度没有统一的内存模型也没有真正的进程概念——Worker 是无状态的函数DO 是有状态的对象两者是分开的。但这个类比有用因为它帮你建立正确的心智模型写 agent 的时候你不再想我要起一个服务而是想我要定义几个有状态的对象给它们配上能调用的系统资源然后让请求路由到正确的对象上。这个思维转变一旦完成架构就清晰了。3. 拆解 cloudflare-os 的核心组件与它们各自的角色3.1 Workers无状态的进程Worker 是整个体系的入口和计算单元。它接收 HTTP 请求或队列消息执行 JavaScript/TypeScript也支持其他编译到 WASM 的语言返回响应。它的关键特性是无状态——每次调用都是全新的隔离环境上一次调用的内存不会保留。这个特性对 agent 来说是把双刃剑。好处是天然的水平扩展和故障隔离坏处是你不能把对话历史放在 Worker 的全局变量里。所以 Worker 的定位应该是编排层解析请求、决定路由、调用模型、调度工具、把状态读写委托给 DO 或 KV。它自己不该持有任何跨请求的状态。我见过不少人把 agent 的整个循环塞进一个 Worker 里用全局变量缓存对话历史本地测试没问题一上线就发现历史随机丢失。原因就是请求可能落到不同节点全局变量根本不共享。这个坑一定要提前避开。3.2 Durable Objectsagent 的记忆与身份DO 是这套架构里最容易被低估、也最关键的部分。你可以把它理解成有唯一名字的对象通过 ID 寻址同一个 ID 的请求永远进同一个实例实例内部串行执行。这给了你两个宝贵的东西强一致的会话状态和天然的并发控制。对 agent 来说一个 DO 实例可以代表一个会话、一个用户、一个任务。对话历史、任务状态机、工具调用记录、待办队列全放进去。因为串行执行你不用担心两个请求同时改状态导致覆盖。因为按 ID 路由你可以放心地让全球用户各自连到自己的实例。DO 还支持alarm可以给自己定一个未来的唤醒时间。这个能力对 agent 太重要了任务需要等 30 秒再重试、需要每天凌晨做一次总结、需要在用户不活跃 10 分钟后清理上下文全都可以用 alarm 实现不需要外部调度器。3.3 KV、R2、D1、Vectorize四种存储各司其职存储这块很多人会混用我建议按访问模式来选。存储访问模式适合存什么不适合存什么KV读多写少最终一致配置、提示词模板、静态知识频繁更新的计数、需要强一致的会话R2对象存储S3 兼容文件、图片、大文本、模型产物需要低延迟随机读的小数据D1关系型SQL结构化记录、日志、用户表高频写入的热点数据Vectorize向量检索语义记忆、RAG 索引精确匹配、事务性数据选错存储的代价很直接。我早期把对话历史放 KV结果因为最终一致用户刚发完消息刷新页面就看不到自己的话体验很差。后来改成 DO 存活跃会话、KV 存归档问题就没了。活跃状态进 DO冷数据进 KV/R2/D1这是我总结出来最省心的一条线。3.4 AI Gateway 与模型调用统一入口的价值agent 免不了调模型而模型调用有几个绕不开的麻烦多个供应商的 API 格式不一样、密钥要管理、要限流、要缓存、要观测成本。AI Gateway 这类统一入口的价值就在于把这些横切关注点收拢到一层。从架构角度我建议永远不要让业务代码直接调模型 API而是走一个内部封装层。这层负责统一请求格式、注入密钥、失败重试与降级、记录 token 消耗、按用户限流。这样将来换模型、加供应商、调参数只改一处。这个封装层本身可以是一个 Worker也可以是一个 DO 方法看你的调用模式。3.5 把它们串起来一次 agent 请求的完整路径假设用户发来一条消息完整路径大致是这样请求打到入口 Worker做鉴权和限流。Worker 根据用户 ID 计算出 DO 的 ID把消息转发给对应的 DO 实例。DO 加载会话历史把新消息追加进去构造模型请求。DO 通过 AI Gateway 调用模型拿到回复或工具调用指令。如果需要工具DO 调用对应的工具 Worker通过 Service Binding 直连。工具结果回填DO 再次调用模型直到得到最终回复。DO 把回复写回状态返回给入口 Worker再返回给用户。如果任务没结束DO 设置一个 alarm到点继续推进。这条路径里Worker 是薄的DO 是厚的存储是分层的模型调用是收口的。记住这个形状后面所有细节都是往这个骨架上填肉。4. 动手搭一个最小可用的 agent 运行环境4.1 环境准备与项目初始化先把工具链装好。你需要 Node.js建议 18 以上、npm 或 pnpm以及 Wrangler CLI。Wrangler 是官方命令行工具负责本地开发、部署、管理资源。npm install -g wrangler wrangler login登录会打开浏览器授权完成后本地就存了凭证。接着初始化项目npm create cloudflarelatest my-agent-os cd my-agent-os创建过程中会问你模板选 Hello World 的 Worker 起步就行后面自己加 DO。项目结构大概是src/index.ts加一个wrangler.toml新版可能是wrangler.jsonc。配置文件是整个项目的核心资源绑定、DO 声明、cron 全在这里。4.2 声明 Durable Object 与绑定资源在配置文件里声明一个 DO 类并绑定需要的存储。下面是一个精简示例name my-agent-os main src/index.ts compatibility_date 2024-09-23 [[durable_objects.bindings]] name AGENT class_name AgentSession [[migrations]] tag v1 new_sqlite_classes [AgentSession] [[kv_namespaces]] binding CONFIG id your-kv-id [[r2_buckets]] binding FILES bucket_name agent-files [[d1_databases]] binding DB database_name agent-db database_id your-d1-id这里有几个点值得说。new_sqlite_classes表示这个 DO 用 SQLite 存储后端适合需要查询的场景如果只是简单键值用默认的 KV 后端也行。migrations 的 tag 一旦发布就不要改改类名或存储类型要新增 migration否则线上数据会出问题。绑定名binding是代码里访问资源的变量名起名要语义化。4.3 写一个带记忆和工具调用的 AgentSessionDO 类的基本骨架是这样export class AgentSession { state: DurableObjectState; env: Env; constructor(state: DurableObjectState, env: Env) { this.state state; this.env env; } async fetch(request: Request): PromiseResponse { const { message } await request.json(); const history (await this.state.storage.get(history)) || []; history.push({ role: user, content: message }); const reply await this.runLoop(history); history.push({ role: assistant, content: reply }); await this.state.storage.put(history, history); return Response.json({ reply }); } async runLoop(history) { // 调模型、处理工具调用、循环直到收敛 } }state.storage是 DO 自带的持久化存储读写都在实例内强一致。注意fetch是串行处理的同一个 DO 的并发请求会排队这正是我们要的会话一致性。工具调用循环是 agent 的心脏。简化逻辑是把历史发给模型如果模型返回工具调用执行工具、把结果追加到历史、再发给模型直到模型返回纯文本。这里一定要设最大循环次数否则模型可能陷入无限调用。我一般设 8 到 10 次超过就返回任务过于复杂请拆分。4.4 用 alarm 实现延迟任务与自我唤醒alarm 的用法很直接async scheduleFollowUp(delayMs: number) { const wakeAt Date.now() delayMs; await this.state.storage.setAlarm(wakeAt); } async alarm() { // 到点被唤醒继续推进任务 const pending await this.state.storage.get(pendingTask); if (pending) { await this.advance(pending); } }一个 DO 同时只有一个 alarm重复设置会覆盖。如果你的 agent 需要多个不同时间的任务得自己在存储里维护一个任务队列alarm 到点时取出最近的一个执行再设置下一个。这个模式我用了很多次很稳。注意alarm 的精度不是毫秒级官方文档说可能有几秒偏差。对 agent 场景通常够用但别拿它做精确计时。4.5 本地调试与部署上线本地开发用wrangler dev它会启动一个本地运行时DO、KV、R2 都有本地模拟。调试 agent 循环时我强烈建议在关键节点打日志尤其是模型请求和工具调用因为 agent 的行为不确定性很高没有日志根本没法排查。部署用wrangler deploy。首次部署会创建 DO 类之后每次部署会应用 migration。部署完记得用wrangler tail看实时日志线上问题和本地经常不一样尤其是超时和并发相关的。5. 那些文档里不会写的坑与调优经验5.1 DO 的串行特性是双刃剑DO 串行处理请求保证了状态一致但也意味着一个慢请求会阻塞同一个 DO 的其他请求。如果你的 agent 一次模型调用要 10 秒这 10 秒内该用户的其他请求全在排队。对单用户会话这没问题但如果你把 DO 设计成一个 DO 服务多个用户就会互相拖累。我的做法是一个会话一个 DO用户 ID 加会话 ID 组合成 DO 名字。这样不同会话互不影响。代价是 DO 数量多但 DO 是按实际使用计费的空闲的 DO 几乎不花钱。5.2 模型调用的超时与重试要分层模型 API 偶尔会超时或返回 5xx。如果你在 DO 里直接调超时会把整个请求拖死。正确做法是在封装层设超时超时后走重试或降级。重试要有退避别立刻重试否则容易把对方打挂。降级可以是换一个更快的模型或者返回一个稍后重试的提示并设置 alarm 稍后再试。我踩过的坑是重试没有幂等保护结果一次工具调用被执行了两次产生了重复记录。后来所有工具调用都带一个幂等键重复请求直接返回上次结果。5.3 上下文窗口的管理策略对话历史无限增长迟早撑爆模型上下文。常见做法是滑动窗口加摘要保留最近 N 轮原文更早的内容定期用模型压缩成摘要。摘要本身也占 token所以要控制摘要长度。我的经验是摘要触发点设在上下文用量的 70% 左右留出余量给工具调用结果。工具返回的内容往往很长如果历史已经占满工具结果一塞进去就超了。另外把长期记忆放 Vectorize需要时检索相关片段注入比全量塞历史高效得多。5.4 成本控制的几个实操点边缘运行时的成本结构是请求数 计算时长 存储 模型调用。模型调用通常是大头。控制成本最有效的几招给模型调用加缓存相同输入直接返回缓存结果、限制单次会话的最大 token、对简单意图用小模型、对工具结果做截断。我做过一个对比把意图识别从大模型换成小模型后整体成本降了将近一半而准确率只掉了几个百分点。不是所有环节都需要最强模型这个认知能省很多钱。5.5 观测与排错的最小配置agent 出问题时你需要的不是它错了而是它在哪一步、带着什么输入、得到了什么输出。所以日志要结构化至少记录请求 ID、会话 ID、步骤名、输入摘要、输出摘要、耗时、token 消耗。这些字段串起来才能还原一次完整的执行链路。我习惯在 DO 里维护一个环形缓冲的步骤日志出问题时可以导出最近 N 步。这个日志平时不返回给用户只在调试接口里暴露避免泄露内部信息。6. 这套架构适合谁以及可以往哪些方向长6.1 适用场景与不适用场景这套东西最适合需要长期在线、状态密集、流量不均的 agent个人助理、客服机器人、定时任务代理、多轮任务编排。它的优势在运维成本低、弹性好、全球延迟低。但它不适合需要大量本地计算或特殊依赖的场景。比如你要跑一个需要 GPU 的本地模型、要访问内网资源、要用某个只有特定系统才有的库边缘运行时给不了。这时候老老实实用传统服务器更合适。选型的第一原则是匹配不是追新。6.2 从单 agent 到多 agent 协作当任务复杂到单个 agent 搞不定就会想到多 agent 协作。在这套架构里多 agent 可以体现为多个 DO 互相调用一个协调者 DO 负责任务分解把子任务分发给执行者 DO收集结果再汇总。DO 之间可以通过 RPC 直接调用不需要走公网。这里的关键是明确职责边界和通信协议。协调者不该知道执行者的内部实现只通过约定的消息格式交互。否则 agent 一多耦合会失控。我建议一开始就把消息格式定义成类型用 TypeScript 的类型系统约束住。6.3 安全与权限的底线agent 能调工具就意味着它能产生副作用。权限设计要遵循最小化原则每个工具只给完成它职责所需的最小权限敏感操作要二次确认所有工具调用要留审计日志。还有一个容易被忽略的点是提示注入。如果 agent 会读取外部内容网页、文件、用户上传这些内容里可能藏着恶意指令。防御手段包括把外部内容明确标记为数据而非指令、对工具调用做白名单校验、敏感操作不依赖模型判断而是走确定性规则。这块没有银弹但分层防御能挡掉大部分。6.4 后续可以扩展的方向如果这套基础跑通了往上有几个自然的扩展方向。一是接入更多工具把搜索、代码执行、文件处理都封装成标准工具接口。二是做多租户用 DO 的命名空间隔离不同用户的数据和配额。三是加可观测面板把日志和指标可视化方便长期运营。四是做版本化让 agent 的行为可以灰度发布和回滚。我个人最看好的方向是把 agent 的能力做成可组合的模块每个模块是一个独立的 Worker 或 DO通过标准接口拼装。这样换模型、换工具、换策略都不用动核心逻辑整个系统的寿命会长很多。最后分享一个我反复验证的小经验先把单条路径跑通再谈并发和扩展。我见过太多人一上来就设计复杂的多 agent 架构结果连一次完整的工具调用循环都没跑顺。边缘运行时的调试体验其实很好本地模拟加实时日志足够你把核心逻辑打磨扎实。等单路径稳了扩展是水到渠成的事。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询