Cloudflare 编码工程实践:统一编码「规则库」让 Codex 监工,四个月拦下 1.6 万次代码合并

规矩先改写成机器能读的结构,再让 Agent 去查;批准了只提示,显式提升到强制才真拦人
作者:The Cloudflare Blog08-05 · 12 分钟⚑ 方法教程
🎧 听播客版0:00 / --:--
0:00 / --:--
深度 · 小互解读
一分钟速览
  • Cloudflare 把散在文档、聊天记录和老员工脑子里的工程规矩,重做成了 Agent 能直接读的结构化数据。
  • 四个月,AI 代码审查器标出近 25 万处违规、拦下 1.6 万次合并;另一个 Agent 在动工前审了近 600 份设计文档。
  • 最值得抄的是那个两级开关:规矩批准了只提示,得再显式提升一次才真的拦人。
  • 60 多份规范全塞给模型会把上下文撑爆,他们的解法是先派个 Agent 把规矩压成 JSON。
⚑ 立场提示:这篇是 Cloudflare 官方博客写自家做法的实践复盘,文中的违规数、拦截数、采纳率都是他们自评口径,没有第三方核验。为了把机制讲透,我另外抓了 Cloudflare 之前两篇相关博文(AI 代码审查器、内部 AI 工程栈)来补背景,这部分内容逐处标注了出处。
起点

Codex 之前,Cloudflare 的工程规范散在四个地方

Cloudflare 8 月 4 日发了一篇工程实践复盘,讲他们怎么把工程规范交给 AI 来执行,过去四个月,他们的 AI 代码审查器标出了近 25 万处违规、拦下 1.6 万次代码合并,另一个 Agent 在动工之前审过近 600 份技术设计。这篇值得读的地方,是它把「文档里的规矩怎么变成合并时真能拦住你的闸门」这条路的每一段都写了出来,其中有一个可以直接抄的设计:规矩批准了先只提示,要再显式提升一次才真的拦人。

先看没有 Codex 的时候是什么样。开发指引散在四个地方:正式文档、仓库里的文件、聊天记录,还有工程师自己脑子里攒的经验。

这带来两层不同的麻烦。

第一层 · 找不着

工程师花在翻规矩上的时间,比花在真正要解决的那个问题上还多。

第二层 · 找着了也不敢信

就算翻到一条答案,你也说不准它是不是最新的、是不是权威的、适不适用于眼下这个情况。

公司一大,这套模式就撑不住了。三个具体后果:没有哪个工程师能读完所有规范;审查者也没法可靠地逐条核对每个要求;人一换团队,攒下来的经验就找不回来了。规矩没人持续提醒、也没人强制执行,项目之间就开始各走各的,出现所谓的漂移(drift):同一套规矩下,不同项目的做法越差越远。

改造前 正式文档 仓库文件 聊天记录 某人脑子里 找规矩 四处来回跑,找着了还得判断能不能信 改造后 一份 Codex 有域主治理,有状态 审代码 审设计 审事故报告 Agent 在干活现场取用 人的时间花在处理它报出来的结果上
本站示意图,据原文对改造前后的描述绘制。
组织方式

Codex 按域划分,每个域有一个负责人

Codex 是一套有人治理的工程规范集合,Agent 可以在需要的时候取出来、用在当下这件事上。同一份规范,现在能同时喂给代码审查、技术设计审查、事故报告审查这些场景。

它按域切开,每个域覆盖一块工程领域:架构类的(比如前端、控制平面)、横切各处的(安全、可靠性)、具体语言的(TypeScript、Rust),还有其他若干块。每个域有一个域主,对自己那批文档的内容、一致性和整体质量负责。

规矩怎么写:RFC 格式,用 SHOULD 和 MUST 分轻重

Codex 的规范用 RFC 格式写。RFC 是从互联网标准圈来的一种写法:一份提案公开征求意见、多轮修改、最后定稿成为大家遵守的东西。

要求只用两个关键词:SHOULD 和 MUST,定义直接沿用 RFC 2119,这是一份真实存在的互联网标准文档,专门规定这几个词在技术规范里的严格含义。

这两个词的分量差在哪

MUST 是必须做到,没有商量余地。SHOULD 是应该做到,但在特定情况下,如果你完全理解后果并权衡过,可以不做。后面你会看到,这两个词的区别直接决定了 Agent 是给个建议、还是把你的代码拦下来。

文档开头还要有一段 front matter 元信息,就是最前面一小段用来描述这份文档本身的内容,写清它属于哪个域、当前是什么状态,这段是给机器读的。

谁能提规矩?任何一个有兴趣、在这个领域有能力的 Cloudflare 员工,都可以按规定的结构提一个 merge request。提案要过好几轮反馈,参与评审的人越来越多,最后由域主拍板批准,这份 RFC 才进 Codex,并发布到一个用 Astro 搭的内部站点上。

Cloudflare Codex 架构类 前端 · 控制平面 域主 1 人 横切关注点 安全 · 可靠性 域主 1 人 具体语言 TypeScript · Rust 域主 1 人 还有其他若干域 共 60+ 份 RFC 每份 RFC 里的要求只用两个词:MUST(必须) 和 SHOULD(应该) 员工提案 → 多轮评审 → 域主拍板 → 进 Codex
本站示意图。域的分类和 60+ 份 RFC 来自原文;每域「1 人」是示意,原文只说每个域有一位域主,未给人数明细。
机制 · 重点

规范从提案到能拦下代码合并的五个步骤

规矩写好了不等于就能拦人。从一份提案到真的能挡住别人的代码,中间有五步。

Cloudflare Codex 工作流图:从 RFC 提案到强制执行的五个阶段

Cloudflare 官方工作流图。五个阶段从左到右:撰写、自动检查、治理、已批准、已强制。图的副标题点出了这套设计的关键,「RFC 和它的机器可读规则走同一个评审流程」。来源:blog.cloudflare.com。

第一步 · 撰写作者写一份新 RFC 或者更新一份旧的,开一个 merge request。
第二步 · 自动检查两件事并行:CI 校验文档的结构、元数据和签署是否合规;同时一个 Agent 把里面的 SHOULD 和 MUST 语句提取出来,产出一份 JSON diff。
第三步 · 治理人来评审,注意评审的是 RFC 和 JSON 两样,然后由域主批准。不合格就打回去改。
第四步 · 已批准RFC 和 JSON 一起合进 Codex,发布到内部站点。客户端和 Agent 立刻开始标记违规,但只提示,不阻断。
第五步 · 已强制RFC 状态被显式提升到 enforced 之后,客户端才可以拦下 MUST 违规。
撰写 写 RFC · 开 MR 自动检查 CI 校验结构 Agent 抽 JSON 治理 评审 RFC + JSON 域主批准 已批准 合入 · 发布 已强制 显式提升一次 标记违规,但不拦 拦下 MUST 违规 同一条规矩,第四步和第五步之间隔着一次人为的显式提升
本站示意图,据官方工作流图重绘。

为什么要多加「显式提升」这一步

Cloudflare 给的理由有两条,都很实在:一是给团队时间去消化新要求;二是有些情况下,「让它真能拦住」这件事本身还需要额外的工程工作。

这一步的价值

规范推不动,常见的死法是两种:太软了没人当回事,或者太硬了上线当天全公司代码都合不进去。

把「这条规矩生效了」和「这条规矩开始拦人」拆成两个开关,就有了一段缓冲带:新规矩先跑一阵,大家看得到自己有多少处违规,团队按自己的节奏改;等改得差不多了,再由人显式扳下第二个开关。

还有一处值得单独拎出来。工作流图的副标题写着「RFC 和它的机器可读规则走同一个评审流程」,人读的那份文档和机器读的那份 JSON,是一起写、一起审、一起合入的。这样两者就不会各自漂移:不会出现文档改了但机器规则还是老的,也不会出现机器在按一条谁都没审过的规矩拦人。

机制 · 重点

60 多份规范怎么压缩成模型读得进的 JSON

Cloudflare 已经有 60 多份 RFC,而且还在涨。一个偷懒的做法是把整个 Codex 原样喂给大模型,但他们明确写了这样做的后果:这个体量会给上下文窗口很大压力,还会拖坏模型的输出质量。

他们的解法是派一个专门的 Agent,自动把 SHOULD 和 MUST 语句抽出来,压缩成一个专用的 JSON 结构,再加上一批支持「懒发现」和渐进披露的元数据。

渐进披露是什么意思

不一次把所有规矩塞给模型,先只给一份目录式的清单,每条规矩一句话;等模型判断出这次任务要用哪几条,才把那几条的详细内容读进来。像一本书先只给目录,翻到哪章才展开哪章。

抽出来的东西长这样(JSON 是一种给机器读的数据格式,用大括号和字段名把信息一条条列清楚):

Codex 机器可读规则 · 控制平面 RFC 节选(原文一字未改)
{
  "rfc": 14,
  "title": "Control Plane Services",
  "status": "approved",
  "domain": "control-plane",
  "statements": [
    {
      "slug": "use-quicksilver-for-edge-configuration-propagation",
      "section": ["Proposal", "Infrastructure"],
      "level": "SHOULD",
      "text": "If you need to propagate system or customer configuration to the edge, use Quicksilver via the outbox pattern",
      "href": "/rfcs/014-control-plane-services/#infrastructure"
    },
    {
      "slug": "api-schemas-must-be-documented-in-openapi-spec",
      "section": ["Proposal", "API Gateway"],
      "level": "MUST",
      "text": "API request and response schemas MUST be documented using an OpenAPI spec",
      "href": "/rfcs/014-control-plane-services/#api-gateway"
    }
  ]
}
拆开看:rfc 是编号,status 是这份规范当前的状态(这里是 approved,所以还不拦人),domain 是它属于哪个域。statements 数组里每一条就是一条规矩:level 标着它是 MUST 还是 SHOULD,text 是规矩本身,section 记着它在原文档的哪一节,href 是回原文的链接,Agent 报违规时可以直接把这个链接甩给你。

每条规矩有一个不会变的编号

上面那个 slug 字段是关键:它是一个稳定的标识符,RFC 更新时这个标识符不变。

为什么这件事重要?因为同一条规矩会被好几个系统引用,代码审查器报了它、监控在统计它触发了多少次、某个团队申请了针对它的例外。如果规矩的编号跟着文档改动漂来漂去,这些引用就全断了。有了稳定 slug,同一条规矩才能跨系统、跨时间被追踪。

60+ 份 RFC 整份喂给模型 = 撑爆上下文 提取 Agent 只挑 SHOULD 和 MUST 语句 statements[] MUST API 请求响应结构必须写 OpenAPI 规格 slug: api-schemas-must-be-documented…(永不变) SHOULD 配置往边缘传播,走 Quicksilver 的 outbox 模式 slug: use-quicksilver-for-edge-config…(永不变) …每条都带 section(在原文哪一节)和 href(回原文的链接) 模型先只看这张清单,需要哪条才去读它的完整 RFC 正文 最初抽成的是更简洁的 Markdown,后来才换成 JSON,Agent 需要更精确地过滤自己要用的内容
本站招牌示意图,据原文的 JSON 节选与提取流程描述绘制。两条规矩的中文是译文,字段结构照原文。

还有一段演进值得记下来:他们一开始抽出来的是一个更简洁的 Markdown 文件,后来才改成结构更丰富的 JSON。换的原因是 Agent 需要更精确地过滤自己要用的内容。接下来还打算加更多元数据,比如标注这条规矩适用于软件生命周期的哪个阶段,设计、实现,还是运行时。

同一堵墙,另一家公司的解法
Stripe 公司内部 Agent 开发实践:一个工程师一周开发出来的公司内部 AI 助手,几乎人人都在用
Stripe 撞上的是 1000 个技能装不进一个上下文,解法同样是「先给目录、选中了才展开」。两家独立走到了同一条路上,而且都实测出了规模天花板。
应用

三个 Agent 用同一份 Codex:审代码、审设计、审事故报告

规矩变成数据之后,能吃它的地方就多了。目前有三个 Agent 在日常工作里用 Codex。

一、AI 代码审查器

每次审查,它先取回 RFC、解析出 Codex statements,只有在模型或协调器需要更多上下文时,才去加载完整的 RFC 正文。大多数情况下,光是那些 statements 就够解释清楚一处违规了。

它怎么反应,由两件事共同决定:这条要求是 SHOULD 还是 MUST,以及这份 RFC 处在什么状态。

RFC 状态SHOULD 要求没满足MUST 要求没满足
已批准(approved)非阻断的建议非阻断的建议
已强制(enforced)非阻断的建议扣住批准,或直接拦下合并请求(看严重程度)

数据:Codex 建立以来,AI 代码审查器标出了接近 23 万处违规,其中将近 1.6 万处导致批准被扣住,也就是撞上了已强制 RFC 的 MUST 条款。

这里有个口径要留意:文章开头写的是「近 25 万处违规、拦下 1.6 万次合并」,代码审查器这一节写的是「接近 23 万处、将近 1.6 万处扣住批准」。两组数字对不太上,Cloudflare 没有解释差异,可能是统计时点或范围不同。另外,「扣住批准」和「拦下合并」严格说也不是一回事,前者可能在补救之后就放行了。

二、spec 审查器:在写代码之前抓架构错误

Cloudflare 的工程师在动手实现之前会写设计文档和技术规格,简称 spec,就是方案书:打算怎么做、为什么这么做、有哪些取舍。Codex 里有相当一部分内容正是关于设计和架构的。

spec 审查器会自己去发现新的 spec,然后拿相关的 Codex 要求去评估它。它跑在什么上面挺有意思,全是 Cloudflare 卖给客户的那些产品:

Cloudflare WorkerAgent 本体跑在上面。
D1存评审结果和状态。
AI Gateway模型请求都从这里走。
Cron Trigger定时触发,去扫有没有新的 spec。

流程是这样:先按域和章节过滤 Codex,只留跟设计相关的(比如讲语言特性、偏实现细节的 RFC 就不看了);几段引导提示词告诉模型怎么做评估、怎么组织结果;报出来的问题按严重程度打分,分数受 SHOULD 和 MUST 影响,同时还会给一般性的质量和架构建议。跑完在 spec 文档上留一条备注,链到一个自定义看板去看细节。

近 600

份不重复的开放 spec 被评审过(2026 年 5 月初以来)

3200+

次评审调用,含按需触发和 spec 改动引发的重跑

65 / 29 / 6

报出问题的严重度分布(%):major / minor / critical

Cloudflare spec 审查器的界面截图

spec 审查器的界面。顶部一排筛选器:最近评审时间(7 天/30 天/90 天)、严重程度(Critical+/Major+/全部)、搜索、团队、是否已解决。被评审的这份 spec 叫「Temporal Resiliency for Platform Workflow Automation」,编号 RM-24741,标着「1 处违规 / 4 条笔记」,最后评审时间 2026 年 7 月 25 日。意见分两大块,架构笔记(再分 ARCHITECTURE / SCALE / OPEN QUESTIONS 三档)和 Codex 违规。来源:blog.cloudflare.com。

这张截图值得多看两眼,因为它回答了一个关键问题:Agent 报出来的意见到底有多具体。

那条标红的 critical 架构意见说:这份 spec 没有定义多集群部署下的命名空间策略,然后列了四个具体该补的问题,命名空间是在两个集群之间复制、还是各集群独有;某个命名空间里的工作流能不能在两个集群都跑;故障切换时命名空间的隔离怎么维持;两地同名的命名空间,是同一个逻辑命名空间还是各自独立的。最后点明这会影响工作流隔离、多租户和故障切换行为。

下面那条 Codex 违规挂在 RFC-013「依赖故障行为未定义」上,MAJOR 级:这份 spec 说 worker 可以在两个集群之间故障转移,但没定义集群故障时的架构行为,缺的五点是,worker 在自己那个集群不可用时是 fail-open 还是 fail-closed;什么触发切换(自动还是手动);worker 怎么发现并连上备用集群;切换对运行中的工作流是否透明、还是需要重启;集群不可用时飞行中的工作流会怎样。它还引用了文档页评论里同事提出的复制延迟担忧,作为「这里确实需要明确的故障模式设计决策」的佐证。

每条意见右侧还有「Recurring」标签(这个问题反复出现过)和「Feedback」按钮。

接下来他们打算把 spec 审查器接得更紧:把意见直接评论到 spec 文档上、把人和 Agent 的对话嵌进去让它能反过来影响评审结论、把高影响的提案标出来交给人额外审一遍。

三、事故报告审查器

同一套路数用在事故报告上(也叫复盘报告,postmortem,线上出事之后写的那份:发生了什么、为什么会发生、怎么解决的、以后怎么防)。

除了检查报告完不完整,它还评估这份报告有没有讲清楚发生了什么、有没有指出促成因素、有没有记录解决过程、有没有提出有意义的后续行动。这些期望写在一份专门的 Codex RFC 里,连「一份合格的事故报告长什么样」本身,都变成了一条可以被机器检查的规矩。

它用的是跟 spec 审查器同一批开发者平台组件,这个共享架构正在成为 Codex 系 Agent 的通用模式。

2026 年 5 月以来,它评估了 200 多份事故报告,找出的缺口包括漏掉的后续行动项、不完整的时间线、遗漏的检测信号。这些报告里 93% 覆盖的是低影响、仅限内部或者预防性声明的事故。对高严重度事故,走这个审查器是强制的,属于中央审查流程的一部分,所有问题处理完之前,报告不算完成。

速度

另外两条更快的检查路径:linter 和本地命令行

跑起来之后,工程师开始抱怨慢。

一次完整的 AI 代码审查通常要几分钟,因为中间有协调器框架和子 Agent 在跑。Cloudflare 在这里写得很坦率:这笔钱(或者说 token)常常花得值,但工程师确实在反映两件事,一是等待的延迟,二是改完问题还得再跑一轮的来回成本。

于是他们补了两条路。

路线一 · linter 配置包

那些能机械验证的语言类要求,做成 linter 规则包(linter 是自动检查代码写法的小工具,规则是死的,跑起来极快),跟 Codex 规范对齐,毫秒级就能报出问题。

TypeScript 是第一个拿到支持的语言,同时统一改用 oxlint 来跑,oxlint 背后的 VoidZero 团队最近加入了 Cloudflare。Rust 的 linter 在做,Go 会跟上,凑齐他们最常用的三门语言。

路线二 · 本地命令行

把持续集成(CI)那一段从审查循环里直接砍掉。这个命令行工具复刻了 CI 里协调器的功能,用同一批(基于 OpenCode 的)Agent 去跑自动算出来的 diff 集合,结果直接显示在终端里。

Cloudflare 自己的判断是:linter 对几乎所有开发者和代码库都有用,而命令行属于给偏好这种方式的工程师的可选项。

同一条 Codex 规矩,三条路查它 linter 毫秒级 只能查不用理解意思就能判断的问题 本地命令行 同样几分钟,但省掉 CI 那一趟来回 CI 上完整审查 几分钟
本站示意图。「毫秒级」和「几分钟」是 Cloudflare 给的量级,条形长度为示意,不代表精确比例。
这里有条可复用的分界

同样一条规矩,交给谁去查取决于它需不需要理解语义:能机械验证的(命名、格式、某个 API 必须带什么参数)交给 linter,毫秒级出结果;需要读懂上下文才能判断的(这个设计有没有考虑故障切换)才值得花几分钟让模型看。

把两类混在一起,要么慢得没人愿意用,要么漏掉真正重要的问题。

同一个思路,在小得多的尺度上
Anthropic 官方教你把手动代码检查写成技能,让它自己查自己修
Cloudflare 做的是公司级:规范变数据、Agent 来执法。同样的做法在单人尺度上怎么落,这篇讲的是把你自己每次手动做的检查固化成机器能跑的东西。
收尾

Cloudflare 接下来的计划,和几处对不上的数字

他们给的路线图有三条:

铺到整个软件生命周期让 Agent 在设计、实现、运维各个阶段都能一致地报出问题,而不只是现在这三个环节。
从发现问题走到提出修复更长期的目标是让 Agent 不只是指出问题,还能提出修复方案,自主程度逐步提高;工程师继续负责审查和批准这些改动。
扩到工程之外产品、安全、合规、信任与安全团队已经开始往 Codex 里加自己的标准,让 Agent 能拿设计和实现之外的考量来评估工作。

几处我核出来的口径问题

三处,都不影响主线,但引用数字时值得知道:

违规数有两个口径开头是「近 25 万处违规、拦下 1.6 万次合并」,代码审查器那节是「接近 23 万处、将近 1.6 万处扣住批准」。差异原因没有交代。
「扣住批准」不等于「拦下合并」前者可能在补救之后就放行了。这两个说法在同一篇里混用,严格说分量不同。
意见的采纳率没给spec 审查器报出的问题里 major 占 65%、critical 占 6%,但没有基线可比,也没说这些意见有多少真被改了,「报出来」和「被修掉」之间还隔着一段。

一句来自他们自己的总结

Cloudflare 在另一篇讲内部 AI 工程栈的博文里,有一段话,分量比上面任何一个数字都重:

这些零件单拿出来都不算新鲜。很多公司都有服务目录、都发过审查机器人、都发布过工程规范。区别在于接线方式。

Cloudflare《我们的内部 AI 工程栈》,本站译

同一篇还给了整套体系的采纳数据:从启动这件事到研发团队 93% 采纳,用了不到一年;2026 年 2 月 5 日到 4 月 15 日期间,活跃用户 3683 人,占公司 60%。

对开发和技术管理的三条启示

把这套东西拆完,有三条经验是脱离 Cloudflare 这个具体场景也成立的。

一、别直接把长文档丢给大模型

规范放在那里是给人读的,模型读不动,60 多份 RFC 原样喂进去,上下文被撑满,输出质量反而掉下来。中间必须加一道结构化:把「必须做什么」抽成一条条独立语句,转成 JSON,每条配一个不随文档改动而变的 slug 编号。

结构化之后才谈得上按需投喂:模型先只看一句话一条的清单,判断出这次要用哪几条,才去读那几条的完整正文。准确率上去了,token 也省了。

二、规则要分级,更要给缓冲期

先分级:SHOULD 是建议,MUST 是强制。这一步决定了机器该给个提醒还是该拦人。

再给缓冲:新规矩批准之后先只提示不阻断,团队看得见自己有多少处违规,按自己的节奏改;等改得差不多了,再由人显式扳下第二个开关,正式开始拦。跳过这段缓冲直接强制,换来的就是研发一片怨声。

三、检查要往前挪,别等代码写完

Cloudflare 真正的杀手锏在于铺开的位置:同一套规矩,被放在三个不同的时间点上查,越靠前的那次成本越低。

方案设计阶段,spec 审查器在动手写代码之前就评审设计文档,这时候改一个架构决策只要改几行字;本地开发阶段,linter 毫秒级报错、命令行工具在本地跑完整审查,不用等 CI;提交合并阶段,最后才是 CI 上那次几分钟的完整审查。

这个思路在工程界叫「左移」(shift left,把质量检查从流程末端往前挪)。等代码写完再发现架构错了,返工成本是设计阶段的几十倍。

✅ 除了上面三条,这几个具体做法也能直接抄
Codex 是 Cloudflare 内部系统,外人用不了;但它用到的零件全是公开的,RFC 2119 定义 MUST/SHOULD,oxlint 跑 TypeScript 检查,OpenCode 撑起审查 Agent,这三样你今天就能装上试。
来源
How Cloudflare enforces engineering standards using AITimo Reimann · The Cloudflare Blog·blog.cloudflare.com·2026-08-04
本站说明
两张截图(工作流图、spec 审查器界面)来自主线原文。「区别在于接线方式」那段引语、93% 研发采纳率与 3683 名活跃用户,来自 Cloudflare 另一篇《内部 AI 工程栈》博文,主线原文未提。JSON 节选照原文一字未改,图中两条规矩的中文为本站译文。标为「本站示意图」的均为本站绘制,不是原文配图。数字口径不一致处已在第七节写明。
↑ 正文结束
✓ 本篇全文免费开放

会员可复制、下载全文 Markdown,还能让你的 AI 订阅和提问。

阅读原文 ↗
📮 新解读第一时间进邮箱

读完觉得有用?留个邮箱,每篇新解读发布就送达,随时退订。