1. 从 "cloudflare-os" 这个名字说起:它到底指什么
第一次看到 "cloudflare-os" 这个词,很多人会下意识以为 Cloudflare 出了一款操作系统,能装到电脑或者服务器上。我一开始也是这么理解的,直到把 Cloudflare 这几年的产品线捋了一遍,才反应过来:它不是一个传统意义上的 OS,而是一套把 Cloudflare 边缘网络当成"运行环境"来用的思路集合。你可以把它理解成一个"没有内核的操作系统"——内核是 Cloudflare 遍布全球的边缘节点,系统调用是 Workers、Durable Objects、R2、D1、KV、Queues、AI Gateway 这些服务,而"应用程序"就是你部署上去的 Worker 脚本和 Agent。
这个理解很关键,因为它直接决定了你该怎么用它。如果你抱着"装个系统"的心态去找 cloudflare-os 的镜像,那注定一无所获;但如果你把它当成"一套把计算、存储、状态、AI 能力全部搬到边缘的运行时",那思路一下子就打开了。关键词里出现的 Cloudflare Workers、AI、agent、Gatekeepers,其实已经把这条线索交代得很清楚了:这是一套围绕边缘计算 + AI Agent 构建的运行时体系,而 Gatekeepers 则是这套体系里负责"守门"的那一层——权限、路由、限流、审计,都归它管。
我写这篇东西的目的,不是给你一份官方文档的复述,而是把我自己在这套体系上折腾 Agent 时踩过的坑、想明白的原理、以及那些文档里不会写的细节,完整地摊开讲一遍。适合谁看?如果你正在做 Agent 开发,尤其是想让 Agent 跑在离用户更近的地方、又不想自己维护一堆服务器,那这套东西值得你花时间。如果你只是想了解"边缘计算 + AI"到底能玩出什么花样,也能从里面拿到不少可复用的思路。
先说结论:cloudflare-os 这套玩法的核心价值,在于它把"Agent 的运行位置"从中心机房挪到了离用户几百毫秒的地方,同时用一套统一的绑定(Binding)机制把状态、存储、AI 推理串了起来。听起来很美,但真上手你会发现,边缘环境的限制比你想的多得多——没有文件系统、没有长驻进程、CPU 时间有硬上限、冷启动虽然快但不是零。这些限制不是 bug,而是这套体系的设计前提,理解它们,你才能写出真正跑得稳的 Agent。
2. 边缘运行时的真实边界:Workers 能做什么、不能做什么
2.1 为什么 Agent 适合放在边缘而不是中心机房
传统 Agent 的部署方式,基本是"一台服务器 + 一个常驻进程 + 一堆依赖"。用户发来请求,请求先到中心机房,Agent 在那边思考、调工具、生成回复,再把结果传回去。这套模式在用户和机房同处一个区域时没问题,但一旦用户分布在全球,延迟就会变得很难看。我实测过一个简单的对话 Agent,用户在国内、机房在美西,光是网络往返就稳定在 180ms 以上,加上模型推理和工具调用,一轮对话轻松超过 2 秒。
边缘运行时的思路正好相反:把 Agent 的"外壳"——路由、鉴权、状态读写、工具编排——放到离用户最近的节点上,只有真正需要大模型推理的那一步才回源。这样一来,网络往返被压到了几十毫秒级别,用户感知到的响应速度会有质的提升。Cloudflare 在全球有三百多个节点,Workers 会在离用户最近的那个节点上执行,这就是它最大的卖点。
但这里有个容易被忽略的点:边缘节点执行的是你的代码,不是你的模型。也就是说,Agent 的"决策逻辑"可以放在边缘,但"思考能力"还是得靠回源到模型服务。所以正确的架构不是"把 Agent 整个搬到边缘",而是"把 Agent 的编排层搬到边缘,把推理层留在能跑大模型的地方"。这个区分想不清楚,后面架构一定会拧巴。
2.2 CPU 时间、内存和"无状态"这三道硬约束
Workers 的运行环境有几个硬性限制,我按踩坑的痛感排序讲。
第一是 CPU 时间。Workers 对单次请求的 CPU 执行时间有上限,免费版和付费版额度不同,但核心逻辑是一样的:你的代码不能长时间占着 CPU 不放。这意味着任何"同步等待"的操作都是灾难——比如你在 Worker 里写一个循环去轮询某个接口,CPU 时间会瞬间打满然后被强制中断。正确做法是把所有 I/O 都做成异步,用await让出控制权,让运行时去调度。
第二是内存。Workers 的内存上限相对宽松,但也不是让你拿来当缓存用的。我见过有人试图在 Worker 里维护一个全局的 Map 当缓存,结果发现不同请求之间根本不共享——因为每个请求可能落在不同的 isolate 里,甚至同一个 isolate 也会被回收。想在边缘做缓存,得用 KV 或者 Cache API,别指望进程内内存。
第三是"无状态"。这是最反直觉的一点。传统后端你可以起一个进程,进程里维护各种全局状态,边缘环境不行。每个请求都是独立的,请求结束,你的执行上下文就没了。那 Agent 需要的"记忆"怎么办?答案是 Durable Objects——它给每个 Agent 实例一个唯一的、有状态的"锚点",所有需要跨请求保持的状态都放在这里。这是 cloudflare-os 这套体系里最关键的一块拼图,后面会专门展开。
2.3 冷启动到底有多快,以及它为什么重要
冷启动是边缘计算绕不开的话题。Workers 用的是 V8 isolate 而不是容器,启动一个 isolate 的开销远小于启动一个容器,官方给的数据是毫秒级。我实测下来,一个不带重型依赖的 Worker,冷启动基本在 5ms 以内,热请求几乎感觉不到额外开销。
但这里有个陷阱:如果你的 Worker 引入了体积很大的依赖包,isolate 的初始化时间会显著上升。我踩过一次坑,为了图方便把一个几百 KB 的工具库整个 import 进来,结果冷启动从 3ms 涨到了 40ms 以上。后来改成按需引入、把不常用的逻辑拆到单独的 Worker 里,才把启动时间压回去。所以给 Agent 写边缘代码,依赖管理要像写前端一样抠——能少引一个包就少引一个。
提示:判断一个依赖该不该引入,先看它的体积和初始化开销。纯函数式的工具库通常没问题,带全局副作用、需要读配置、需要初始化连接的库,尽量别放在边缘。
3. Durable Objects:给 Agent 一个"记得住事"的锚点
3.1 为什么 Agent 的记忆不能放在普通存储里
Agent 和普通 API 最大的区别,是它需要"记忆"。用户上一句说了什么、Agent 之前调过哪些工具、当前任务进行到哪一步,这些都得存下来。用 KV 行不行?行,但很别扭。KV 是最终一致的,你写进去的数据不保证立刻能读到,而且 KV 没有"锁"的概念,两个请求同时改同一份记忆,很容易互相覆盖。
用 D1(Cloudflare 的 SQLite 服务)行不行?也行,但 D1 是关系型存储,适合结构化查询,不适合高频的、按会话隔离的状态读写。而且每次读写都要走一次数据库往返,延迟上不划算。
Durable Objects 解决的正是这个问题。它给每个对象一个全局唯一的 ID,所有对这个 ID 的请求都会被路由到同一个对象实例上,这个实例是有状态的、单线程的。你可以把它理解成"一个永远在线的、只属于某个会话的小服务器"。Agent 的对话历史、任务状态、工具调用记录,全都可以放在这里,读写是强一致的,不用担心并发覆盖。
3.2 单线程模型带来的"免费"并发安全
Durable Objects 最妙的地方在于它的单线程模型。同一个对象实例上的所有请求是串行处理的,这意味着你根本不需要考虑锁的问题——两个请求同时到达,运行时会自动排队,一个处理完再处理下一个。对于 Agent 这种"状态敏感"的场景,这简直是天赐的礼物。
我举个具体例子。假设你的 Agent 支持"多轮工具调用",用户发来一条消息,Agent 可能连续调用三四个工具,中间状态需要保持。如果用普通存储,你得自己实现一套乐观锁或者事务机制,稍不注意就会出现"两个请求同时读到旧状态、各自修改、后写的覆盖先写的"这种经典并发 bug。用 Durable Object,这个问题从根上就不存在——因为同一时刻只有一个请求在处理这个会话。
但单线程也有代价:如果你的处理逻辑很慢,后面的请求就得排队等。所以 Durable Object 里的代码要尽量快,耗时的操作(比如调大模型)应该异步化,或者干脆拆到 Worker 里做,Durable Object 只负责状态管理。
3.3 状态持久化与"休眠"机制的实际影响
Durable Objects 的状态默认是存在内存里的,但 Cloudflare 提供了持久化存储 API,可以把关键状态写进对象自带的存储里。这里有个细节值得说:Durable Object 支持"休眠"——当一段时间没有请求时,对象会被换出内存,下次请求来了再唤醒。唤醒时内存状态会丢失,但持久化存储里的数据还在。
这个机制对 Agent 的影响很直接:你不能假设对象一直活着,所有需要跨休眠保持的状态都必须写进持久化存储。我一开始没注意这点,把对话历史只放在内存里,测试时一切正常,上线后用户隔了几分钟再发消息,历史就没了。后来改成每次更新都写存储,问题才解决。
注意:Durable Object 的存储写入是异步的,但为了保证一致性,建议在返回响应前
await写入完成。否则可能出现"响应已返回、状态还没落盘"的情况,极端场景下会丢状态。
4. Gatekeepers 这一层:Agent 的权限、路由与审计怎么做
4.1 Gatekeeper 在架构里的位置
Gatekeepers 这个词在 cloudflare-os 的语境里,指的是介于用户请求和 Agent 执行之间的一层"守门"逻辑。它不参与 Agent 的"思考",但负责决定"这个请求能不能进来、该路由到哪个 Agent、进来之后能干什么、干完留下什么记录"。
为什么需要单独一层?因为 Agent 和普通 API 不一样,它能调工具、能访问外部资源、能产生副作用。如果没有一层统一的管控,每个 Agent 自己实现鉴权和限流,代码会重复得离谱,而且很容易漏掉某个安全边界。把 Gatekeeper 抽出来,好处是权限策略集中管理,Agent 本身只关心业务逻辑。
我自己的做法是把 Gatekeeper 实现成一个独立的 Worker,所有请求先经过它,它做完鉴权、限流、路由决策后,再把请求转发给对应的 Agent Worker。这样 Agent Worker 可以假设"进来的请求已经是被信任的",代码能简化不少。
4.2 用 Worker 实现限流与鉴权的具体思路
限流这块,边缘环境有个天然优势:请求在离用户最近的节点就被拦下了,不用等到回源。实现上可以用 KV 存计数器,key 是用户 ID 加时间窗口,每次请求先读计数器、判断是否超限、再写回。但 KV 是最终一致的,高并发下计数可能不准。更稳的做法是用 Durable Object 做计数器,每个用户一个对象,单线程模型保证了计数的准确性。
鉴权这块,常见做法是校验请求头里的 token。但要注意,边缘环境里做 JWT 验签是有 CPU 开销的,尤其是非对称加密。如果 QPS 很高,验签可能成为瓶颈。我的经验是:能用对称加密就用对称加密,或者把验签结果缓存一小段时间(比如 60 秒),同一个 token 在缓存期内不重复验签。
路由决策相对简单,根据请求里的 Agent ID 或者用户属性,决定转发到哪个 Agent Worker。这里可以用 Workers 的 Service Binding,直接调用另一个 Worker,不用走公网,延迟更低。
4.3 审计日志:Agent 干了什么,必须留痕
Agent 的审计比普通 API 重要得多,因为它会调工具、会产生副作用。一个用户让 Agent "帮我删掉那封邮件",如果 Agent 真的删了,事后你得能查到"是谁、在什么时候、通过哪个 Agent、调了哪个工具、删了哪封邮件"。
审计日志的写入不能阻塞主流程,否则会拖慢响应。我的做法是把审计事件丢进 Queues,由消费者异步写入 R2 或者 D1。Queues 的好处是它自带重试和削峰,即使写入端短暂不可用,事件也不会丢。日志格式上,我建议至少包含这几个字段:请求 ID、用户 ID、Agent ID、工具名、参数摘要、结果状态、时间戳。参数摘要要注意脱敏,别把敏感信息原样记进去。
5. 把 AI 推理接进边缘:AI Gateway 与模型调用的取舍
5.1 为什么不在边缘直接跑模型
很多人第一反应是"既然边缘节点这么多,为什么不把模型也部署到边缘"。答案很现实:模型太大,边缘节点放不下。一个哪怕量化过的小模型,动辄几百 MB 到几个 GB,而边缘节点的资源是共享的、有限的,不可能给每个节点都塞一个模型。
所以正确的做法是:边缘负责编排,推理回源到模型服务。Cloudflare 提供了 AI Gateway,它的作用是给你的模型调用加一层"代理"——统一入口、缓存、限流、可观测。你可以把它理解成"模型调用的 Gatekeeper"。
5.2 AI Gateway 能省下的那些事
AI Gateway 最实用的功能是缓存。很多 Agent 的请求其实是重复的——比如用户问同样的问题、或者系统提示词固定不变。把这些请求的响应缓存起来,能省下大量推理成本。我实测过一个客服 Agent,开启缓存后,重复问题的命中率大概在 20% 左右,成本直接降了两成。
第二个实用功能是可观测。Agent 调模型不像普通 API 调用那么直观,你很难知道"这次调用花了多少 token、延迟多少、有没有失败"。AI Gateway 把这些指标都记下来了,排查问题时非常有用。我有一次发现某个 Agent 的响应特别慢,查了 Gateway 的日志才发现是某次工具调用的结果太长,把上下文撑爆了,导致模型处理时间飙升。
第三个是限流和重试。模型服务偶尔会抽风,直接调用的话失败就失败了。通过 Gateway 配置重试策略,能显著提升 Agent 的稳定性。但要注意,重试要幂等——如果工具调用有副作用,重试可能导致重复执行。
5.3 上下文管理与 token 成本控制
Agent 的 token 成本是个无底洞。对话历史越攒越长,每次调用都把全部历史塞进去,成本会指数级上升。我的做法是分层管理上下文:最近的几轮对话保留原文,更早的对话做摘要,再早的直接丢弃。摘要可以用一个便宜的小模型来做,成本远低于把原文塞进主模型。
另一个技巧是把系统提示词和工具定义做成"可缓存"的形式。很多模型服务支持 prompt caching,固定的前缀部分只计费一次。把不变的部分(系统提示、工具 schema)放在前面,变化的部分(用户输入、历史)放在后面,能最大化缓存命中率。
6. 多 Agent 协作在边缘的落地方式
6.1 Agent 之间怎么通信
多 Agent 协作听起来很高级,但落到边缘环境,核心问题就一个:Agent 之间怎么通信。常见方案有三种。
第一种是 Service Binding,一个 Worker 直接调用另一个 Worker。这是最快的,因为不走公网,但要求两个 Agent 部署在同一个账号下,耦合度较高。
第二种是 Queues,一个 Agent 把任务丢进队列,另一个 Agent 消费。这是最松耦合的,适合异步任务,但延迟比直接调用高。
第三种是 Durable Objects,多个 Agent 共享同一个对象实例,通过对象的方法互相调用。这适合需要共享状态的场景,比如多个 Agent 协作完成一个任务,中间状态需要互相可见。
我自己的经验是:同步的、需要立即返回的协作,用 Service Binding;异步的、可以慢慢处理的,用 Queues;需要共享状态的,用 Durable Objects。别一上来就追求"全异步架构",很多时候同步调用反而更简单可靠。
6.2 状态共享与冲突避免
多 Agent 协作最容易出问题的地方是状态共享。两个 Agent 同时修改同一份状态,谁赢?如果都用 Durable Objects,单线程模型天然避免了冲突。但如果状态存在 KV 或 D1 里,就得自己处理并发。
我的建议是:把"共享状态"收敛到少数几个 Durable Object 里,让所有 Agent 都通过这个对象来读写。这样虽然牺牲了一点灵活性,但换来的是强一致性和简单的心智模型。Agent 之间的协作协议也尽量简单——能用一个消息类型说清楚的事,别设计成复杂的多轮握手。
6.3 一个可复用的协作模式:编排者 + 执行者
我在实际项目里用得最多的模式是"编排者 + 执行者"。编排者 Agent 负责理解用户意图、拆解任务、决定调用哪些执行者;执行者 Agent 各自负责一类具体能力(比如查数据、发邮件、生成内容)。编排者和执行者之间通过 Service Binding 通信,执行者的状态各自用 Durable Object 管理。
这个模式的好处是职责清晰:编排者不需要知道执行者的内部实现,执行者也不需要理解全局任务。扩展的时候,加一个新的执行者就行,编排者那边改一下路由逻辑。我试过用这个模式搭一个包含五六个执行者的系统,维护起来比"一个大 Agent 干所有事"轻松太多。
7. 部署与调试:那些文档里不会写的细节
7.1 本地开发与线上行为的差异
Workers 有本地开发工具,能在本地模拟边缘环境。但本地和线上永远有差异,我踩过的几个典型坑:本地 KV 是内存模拟的,读写瞬间完成,线上 KV 有延迟;本地 Durable Object 不会休眠,线上会;本地没有真实的网络延迟,线上跨区域调用会慢很多。
所以我的习惯是:核心逻辑在本地开发,但涉及状态、存储、跨服务调用的部分,一定要在线上环境验证。别等到上线才发现"本地好好的,线上全崩了"。
7.2 日志与可观测性的搭建
边缘环境的日志不像传统服务器那么好拿。Workers 有实时日志(tail),但只能看当前正在发生的请求,历史日志得靠 Logpush 推到外部存储。我的做法是:开发阶段用 tail 实时看,生产环境用 Logpush 推到 R2,再用一个查询 Worker 做检索。
可观测性方面,除了日志,还要关注几个指标:请求量、错误率、P99 延迟、CPU 时间消耗、Durable Object 的唤醒次数。这些指标能帮你快速定位问题——比如错误率突然上升,可能是某个依赖挂了;CPU 时间飙升,可能是某段代码写成了同步循环。
7.3 灰度发布与回滚
边缘环境的发布是原子的,一次部署所有节点同时生效。这既是优点也是风险——好处是没有"部分节点旧版本、部分节点新版本"的中间状态,坏处是一旦新版本有问题,影响面是全局的。
我的做法是用 Workers 的版本管理做灰度:先部署一个新版本,把少量流量导过去,观察一段时间没问题再全量。回滚也很简单,把流量切回旧版本就行。这里要注意,如果新版本改了 Durable Object 的存储结构,回滚时旧版本可能读不懂新数据,所以存储结构的变更要向前兼容——新版本能读旧数据,旧版本也能读新数据(至少不崩)。
8. 我在实际项目里踩过的几个坑
第一个坑是"把 Durable Object 当数据库用"。我一开始把所有状态都往 Durable Object 里塞,包括一些需要复杂查询的数据。结果发现查询逻辑写起来极其别扭,而且对象体积越来越大,唤醒越来越慢。后来把"需要查询的数据"挪到 D1,"需要强一致的状态"留在 Durable Object,才理顺。
第二个坑是"忽略 CPU 时间限制"。我写过一个工具调用逻辑,里面有个循环在等外部接口返回,结果 CPU 时间直接打满被中断。后来改成异步轮询加退避,问题解决。这个坑的教训是:边缘环境里,任何"忙等"都是禁忌。
第三个坑是"审计日志写同步"。我一开始在请求处理流程里同步写审计日志,结果日志写入的延迟直接叠加到了用户响应上。改成异步写 Queues 后,响应时间降了一大截。
第四个坑是"多 Agent 共享状态没加锁"。早期我用 KV 存共享状态,两个 Agent 同时写,互相覆盖。后来换成 Durable Object,问题消失。这个坑让我彻底理解了"边缘环境里,强一致状态必须用 Durable Object"这条铁律。
9. 这套体系适合什么样的项目
cloudflare-os 这套玩法不是万能的。它最适合的场景是:用户分布广、对延迟敏感、Agent 逻辑以编排为主、状态需要强一致。典型的例子是在线客服、实时助手、轻量级任务自动化。
它不太适合的场景是:需要大量本地计算、需要长驻进程、需要复杂的关系型查询、对成本极度敏感的大规模推理。这些场景用传统服务器或者容器方案可能更合适。
我的建议是:先用一个小项目试水,把 Workers、Durable Objects、AI Gateway 这几个核心组件跑通,感受一下边缘环境的限制和优势。跑通之后,再决定要不要把核心业务迁过来。别一上来就 all in,边缘环境的坑比你想象的多,小步快跑才是正道。
最后分享一个我自己的判断标准:如果一个 Agent 的"思考"时间远大于"编排"时间,那边缘化的收益有限;如果"编排"和"状态管理"占了大部分开销,那边缘化能带来明显的体验提升。这个标准帮我在多个项目里做了正确的架构决策,也希望对你有用。