Codex 调度策略一个月复盘:派发、结果与算力波动

用 463 个 rollout 和 8.5 万次模型响应复盘子代理派发的规则遵守、任务结果、积分成本和模型能力波动,并据此改写派发与容错规则

第 11 篇发布于

返回博客

《Codex 的封装》从 2026-09-02 起记录我在 Codex 上的子代理调度规则:根代理协调和验收,代码交给 Sol 实现者,高风险改动加 Astra 审查,需要运行时证据时加 QA,窄问题交给 Luna。规则写好以后,我一直没有回头看它在真实会话里的执行情况。

这篇用本机 9 月以来的 rollout 回答六个问题:规则有没有被遵守,哪些规则起了作用,哪些规则在制造多余的工作,钱花在了哪里,任务到底完成得怎么样,模型能力的波动造成了什么。结论直接改写了那篇文章的派发与容错规则。

数据与口径

Codex 把每个线程写成 ~/.codex/sessions 或 archived_sessions 下的一个 JSONL rollout。统计用到的字段:

记录字段用途
session_metathread_source、agent_role、parent_thread_id、cli_version、multi_agent_version区分根线程与子线程,还原父子关系和角色
turn_contextmodel、effort、sandbox_policy、approval_policy每一轮实际使用的模型、档位和权限
function_callspawn_agent 的 agent_type、model、reasoning_effort、fork_turns派发参数是否完整、是否与角色一致
工具输出agent thread limit reached容量失败
token_counttotal_token_usage输入、缓存输入、输出 token
task_completelast_agent_message审查与 QA 的结论

范围是 2026-09-01 到 10-13 上午的 463 个 rollout 文件:70 个用户发起的根任务(不含 1 个自动审查线程,43 个派了子代理)、377 个子代理线程、398 次 spawn_agent,CLI 从 0.152.1 到 0.162.1。日期按 UTC。按两次规则变化分成三段:

  • E1(09-01 至 09-13):GPT-5.6 子代理,线程上限 09-08 前为 2。
  • E2(09-14 至 09-26):GPT-5.6 子代理,经过 0.154.0 全篇复核。
  • E3(09-27 至 10-13 上午):GPT-6 角色,根代理先是 Astra,09-29 起改为 GPT-6.1 Sol。

口径说明:

  • 一个根线程可能分成多个分页文件,token 计数在文件之间累加,所以取每个线程的最大值,不能相加。
  • 派发参数里的 message 是加密的,统计只看参数结构,不看任务正文。
  • 积分按定价页的 Standard 单价(每百万 token:Astra 250 / 25 / 1,250,GPT-6.1 Sol 50 / 2.5 / 250,GPT-6 Sol 50 / 5 / 250,Luna 2.5 / 0.25 / 12.5,依次是输入、缓存输入、输出)乘以 token 数估算。它不含 Fast 倍率,也不等于订阅额度的实际扣减。
  • 审查结论按 APPROVE、BLOCK 等关键词匹配,可能漏判自由格式的结论。
  • 根代理直接改了哪些文件,只统计了 apply_patch 记录;通过 shell 或脚本写文件的操作没有扫描。
  • codex doctor 另报告了 150 个 subagent:other 来源的线程,多半来自自动审查,本文没有分析。

规则遵守情况

指标E1E2E3
spawn_agent 次数21410579
显式给出 model 与 effort21410579
使用自定义角色1917478
角色、模型、effort 与角色文件一致191/19174/7474/78
fork_turns 为 none21410579
线程上限失败2100
子代理继续派发000

文本规则的执行几乎没有缺口。E3 的 4 次不一致都发生在 09-27 切换当天,仍是 GPT-5.6 的派发;切换之后没有 GPT-5.x 子代理。E2 有 31 次派发没带自定义角色(20 次不填、11 次用内置 default),这些线程拿不到角色文件里的 developer_instructions,也就没有"不提交、不委派、返回证据包"这些约束。E3 只剩 1 次。

E2 里有 8 个根任务的根代理用了 ultra,31 次没带角色的派发中有 16 次出在这些任务里;另外 15 次和 E1 的 23 次都出在没用 ultra 的任务里。数据只能说明二者相关,E3 的下降更可能来自 09-14 和 09-27 两次规则修改。模型目录对 ultra 的说明是 "Maximum reasoning with automatic task delegation",现行规则据此要求 ultra 会话仍按派发理由和预算执行。

起作用的规则

线程上限与复用。 21 次派发失败(连同 followup_task 与 send_message 共 27 次 agent thread limit reached)都发生在 09-04 到 09-08,这段时间上限大部分时候是 2。09-08 改为 6 并要求优先用 followup_task 复用匹配的线程,09-09 之后五周内没有再出现;09-09 之后单个根任务最多派出 36 个线程,没有调用过关闭工具。旧文"完成的线程不释放槽位"来自上限为 2 的 0.153.4 桌面会话,不能推广到现在。

根代理不写生产代码。 按 apply_patch 记录,E3 根代理直接改的文件约九成是 Markdown 计划和文档,其余是 Codex 配置文件、一个 .gitignore、脚本生成的 logo 设计稿和一份 HTML 报告,没有通过 apply_patch 改生产或测试代码。唯一一次违规在 09-08:根代理直接改了仓库里 7 个 tsx、1 个 ts 测试文件和 package.json。

审查确实拦下了问题。 E3 的 17 个审查线程里 13 个至少给过一次 BLOCK,最后 11 个以 APPROVE 收尾。实现、审查、修复、再审查这条回路在工作。

审查线程E1E2E3
至少 BLOCK 一次7/4111/2513/17

制造多余工作的规则

所有代码都必须委派。 旧规则要求任何生产或测试代码改动都交给 Sol 实现者,根代理不得自己改。E3 的 21 个根任务里有 17 个派了子代理。按触发派发的那条用户消息逐条核对,下面这些请求本可以由根代理直接完成:

用户消息派出的子代理
commit & push(8 条这样的消息中只有这一条触发派发)Astra 审查一个
修一条 pnpm dev 启动报错实现一个
手机调试中回复"已进入场景,开始游玩"Astra 审查一个
分析项目并生成一份 HTML 报告侦察、实现各一个
回复"允许"(批准一个操作)两次分别派出实现一个、QA 一个
回复"retry"未带角色的 Sol 一个

Codex 文档写明,项目或技能指令要求委派时 Codex 会委派,而子代理流程比单代理运行消耗更多 token,因为每个子代理各自做模型与工具调用。Subagents "所有代码必须委派"正是这样一条项目指令。旧版文章没有写这条规则的理由,我推断是根代理当时用 Astra、比 Sol 贵得多;09-29 根代理换成 GPT-6.1 Sol 以后,根代理的单价不高于实现者,这个理由不再成立。

协调开销。 在派了子代理的根任务里,根代理的输出 token 占根加子代理输出总量的 33%(E3)。前两段按口径不同在 15% 到 31% 之间,不足以说明趋势,但 E3 的三分之一已经说明委派把相当一部分工作变成了协调。E3 平均每个派了子代理的根任务调用 send_message 69 次、wait_agent 50 次、followup_task 32 次。委派把一部分工作从实现变成了沟通和等待。

名义上的只读。 E3 根代理的 212 个轮次里有 207 个运行在 danger-full-access / never,其余 5 个是 workspace-write。子代理继承父会话的实时权限,审查和侦察线程没有一个轮次以 read-only 运行,角色文件里的 read-only 从未生效。config.toml 里写的是 workspace-write,但会话在界面里选了完全权限,配置值只影响新会话和 codex exec 的默认值。

钱花在哪里

E3 的估算积分按角色和模型分布:

角色模型线程积分占比
根代理gpt-6-astra842%
实现gpt-6-sol3421%
审查gpt-6-astra1715%
QAgpt-6-sol158%
根代理gpt-6.1-sol136%
未带角色gpt-6-sol15%
实现gpt-5.6-sol32%
侦察gpt-6-luna80%

表中不含 1 个仍在 gpt-5.6-terra 上的 QA 线程;09-29 从 Astra 切到 GPT-6.1 Sol 的那个根任务整体按 GPT-6.1 Sol 计价。

Astra 根代理加 Astra 审查约占 57%。Astra 根代理与 GPT-6.1 Sol 根代理的单任务积分相差约十倍,其中五倍来自单价,其余来自任务大小不同,这一对比只说明方向。另一处可省的地方是缓存:子代理的输入约 98% 命中缓存,GPT-6.1 Sol 的缓存输入单价是 GPT-6 Sol 的一半,实现与 QA 换成 GPT-6.1 Sol 后,同样的 token 量约便宜 38%。

任务到底完成得怎么样

前五节看的是规则执行和成本,这一节看结果。我按用户消息、失败轮次和最终回复,逐个判读了 09-14 以来的 39 个根任务。判读只有一个人,没有第二人复核,比例只作参考:

结果任务数
按要求完成20
纠正后完成5
部分完成11
放弃2
偏离目标1

委派的 33 个任务里 14 个按要求完成,每个任务平均被纠正 1.0 次,汇总轮次时间中位 48 分钟;直接完成的 6 个全部按要求完成,平均纠正 0.17 次,中位 7 分钟。直接完成的都是小任务,两组不能直接比较;只看 30 分钟以内的 11 个委派任务,8 个按要求完成、2 个放弃,中位 14 分钟。能说的是:数据里看不到委派带来的质量提升。

84 小时根代理轮次时间的去向:

  • 界面类任务的验收错位。 一个浏览器扩展项目的 7 个界面任务占了 56%。它们的共同点是本地测试和门禁全部通过,我看了却觉得不能用或不好看,然后反复返工。有一次根代理在一个可丢弃的原型上打磨了很久,我指出它改错了地方、又多花了约 100 美元,并追问当初给的目标。
  • 等待子代理。 有计时的轮询等待约 11 小时(1,036 次,单次不超过约 60 秒);09-26 之前另有 294 次没有计时,按平均 37.5 秒估算,合计约 14 小时。这段时间子代理在干活,不全是浪费,但单个实现者加根代理空等的组合把一部分工作变成了等待。
  • 上下文压缩。 压缩耗时从 09-26 起才有记录:216 次计时的压缩中位 66 秒,合计 6.9 小时,其中 2.3 小时在子代理线程里,不计入上面的 84 小时;09-14 以来的压缩共 491 次。
  • 满载和断流。 失败轮次约 206 分钟,加上我重发前的约 60 分钟,合计约 4.4 小时;没有一个任务最终卡死在容量上。
  • 权限或环境阻塞。 至少 90 分钟,例如浏览器进程被沙箱拒绝启动以后,会话一直等到我回来。

按出现频率排序的失败方式:交付结果被纠正(15 个任务、34 次纠正)、中途停下需要我催"继续"或"还剩什么"(9 个任务)、环境与权限阻塞(约 8 个任务)、满载或断流(根代理 3 个任务、子代理 5 个任务)、目标漂移与交互摩擦(3 个任务)。最贵的问题出在验收方式和任务规格上,模型能力和算力是第二位的。

模型能力的波动

我原以为"算力潮汐"是按时段起伏的,数据给出的是另外四种形态:

形态本机证据规律
满载失败35 个失败轮次里 25 个是 Selected model is at capacity,其余是额度耗尽 5 个、断流 4 个、其他 1 个;除 GPT-6 Luna 外所有在用模型都出现过集中在少数日子;10 月的几次只打在 GPT-6.1 Sol 上,同一会话里的 GPT-6 Sol 和 Astra 子代理照常工作
速度骤降Astra 在 09-12、GPT-6 Sol 在 09-30 的日中位速度降到平时的一半按天发生;多数模型按小时的中位速度只差 1.1 到 1.5 倍,GPT-6 Sol 的 2.7 倍也来自 09-30 那一天
额度耗尽周额度在 09-10、09-16、09-29 三次打满来自 Astra 的大量使用;10 月最高 43%
模型间的稳定差距输入 10 万到 20 万 token 时,GPT-6.1 Sol(根代理,xhigh)中位 33 秒,GPT-6 Sol(子代理)13 秒;6.1 Sol 的延迟还随上下文增长,5 万以下约 17 秒,25 万以上约 41 秒模型特性,不是波动;外部实测的 6.1 Sol 速度同样在 15 到 26 tok/s

两组对比里,6.1 Sol 的样本都是根代理、6 Sol 的样本都是子代理,角色本身也影响速度(Astra 根代理比子代理慢约 1.3 倍),扣除这一点后约为 2 倍(原始比较 2.6 倍);同一时刻、都作为根会话的对照实验里是 1.8 倍(见第 8 节)。

外部记录能对上几天:GPT-6.1 Sol 发布后的头两天 OpenAI 确认过负载高峰,与本机 09-30 GPT-6 Sol 降速和当天的满载失败对得上;10-13 OpenAI 状态页有 GPT-6.1 Sol 在 Codex 的降级事件,与本机当天的失败只对得上日期,具体时刻要看状态页用的时区;09-12 OpenAI 修复过一次 Astra 的服务配置问题,与本机 Astra 降速只对得上日期。没有找到任何按时段的规律。

Codex 自己的行为:HTTP 和流中断会自动重试,0.161、0.162 起遵循服务端的重试建议;这些重试失败,或者遇到满载、额度耗尽,整轮就结束,本机观察到的失败里没有一次自动换模型。最长的一次,一个跑了 75 分钟、累计 1,260 万输入 token 的根代理轮次在满载时结束,等我重发。官方文档里有 model/rerouted 事件,本机一次都没出现过。

根代理对照实验

2026-10-13 的根代理对照实验:同一时刻用四种配置跑同一个只读分析任务(读 6 个源文件,写 600 到 900 字、每句带行号引用的说明,最后列三个风险),四个都是根会话,上下文 4 万到 5.5 万 token。引用准确性由一个独立审查者逐条核对:

配置总耗时(含约 10 秒启动)模型时间输出 token(推理占比)引用核对
gpt-6.1-sol xhigh210 s190 s5,348(36%)47 处,0 错,2 处偏差 1 到 3 行
gpt-6.1-sol medium108 s92 s2,505(4%)43 处,0 错,4 处偏差
gpt-6-sol xhigh134 s107 s6,385(56%)47 处,0 错,2 到 3 处偏差;唯一发现一个未被使用的字段
gpt-6.1-sol xhigh + Fast209 s188 s6,332(40%)45 处,0 错,2 处偏差

四份答案都没有错误引用,差距在样本能分辨的范围以内。这次只有一个任务、各跑一次,能说明的有限:在这种读代码、写说明的任务上,gpt-6.1-sol 把 effort 从 xhigh 降到 medium,耗时减半,引用准确性没有可见损失;Fast 那一组的生成速度高约 20%,但 rollout 里看不出 Fast 是否确实生效,单次对比也分不清这是 Fast 的效果还是随机波动,总耗时没有缩短;gpt-6-sol xhigh 的总耗时比 gpt-6.1-sol xhigh 短约三分之一。据此本机根代理的默认 effort 从 xhigh 改为 medium,难题在会话里用 /model 切回 xhigh;规则要求根代理在 L3 及以上的任务里提醒一次,因推理深度不够而失败时停下请用户切换,不在 medium 上重试(见第 9 节)。换一天重跑,才能把模型特性和当天的波动分开。

据此做出的改动

改动已经部署到本机,并写进《Codex 的封装》:

  • 直接完成为默认。 只有可并行的独立工作、不该装进根上下文的大块内容、触发条件要求的独立验证、用户明确要求这四种理由才派发;git 操作、单条命令、文档报告、配置、设备操作和约三个文件以内的明显修复不派发。
  • 级别与积分权重。 按本机约 98% 缓存命中的 token 构成折算,以 GPT-6.1 Sol 为 1,Luna 约 0.08、GPT-6 Sol 约 1.6、Astra 约 8;L0 到 L4 的预算是 0、2、4、14、20,L2 及以上派发前报告账本;给已有线程分配新工作的 followup_task 也计入预算。结构移植自 Claude Code 侧的 dispatch-policy。
  • Astra 闸门。 常规审查改用 GPT-6.1 Sol;Astra 每个任务最多一次,只在 L3 及以上、针对一个具体的高风险问题串行使用,不复用线程。
  • 按职责命名角色。 implementer、qa、reviewer、astra_reviewer、recon。实现和 QA 用 GPT-6 Sol,常规审查用 GPT-6.1 Sol,两者由我预授权互为后备;implementer、qa、reviewer 不固定模型,model 和 effort 由每次派发给出;按原因升档:没尽力就提 effort,能力不够就换更强的角色。luna_recon_max 并入 recon。
  • 失败处理。 子代理满载或断流时,根代理告知我并在后备模型上从最后完成的步骤重派一次,这次重派不受级别预算限制;再失败就依次改为直接做、缩小或串行任务、停下报告续跑点。不自建重试循环,额度耗尽时停止派发。
  • 验收与进度。 界面类任务做到第一个可见里程碑就停下给截图;同一验收项连续两轮没有可量化的进展就停下给选项;超过约 30 分钟的工作先复述目标和验收标准,长步骤前写进度行;没有审批提示的阻塞立即停下说明;无关任务开新线程。
  • 派发契约。 agent_type 与 fork_turns = "none" 必填(0.162.0 起不填 fork_turns 就复制完整父历史);审查改为对抗式,第二轮审查开新线程。
  • 根代理默认 medium。 按第 8 节的对照实验,根代理默认 effort 从 xhigh 改为 medium;L3 及以上的任务里,根代理提醒我可以用 /model 切到 xhigh;它因推理深度不够而失败时,停下请我切换,不在 medium 上重试。
  • 如实写明权限。 继续以完全权限运行会话;只读角色只由指令约束。
  • Windows 沙箱改为 MXC。 探针输出 MXC_OK 后把 [windows] sandbox 从 unelevated 改为 mxc。

部署后用只读 codex exec 烟测验证:子线程 rollout 显示 recon 以 gpt-6-luna、effort low 运行;qa 和 reviewer 分别按派发值在 GPT-6.1 Sol 和 GPT-6 Sol 上运行,都是 read-only。

下次复盘看什么

指标本次基线(E3)期望方向
派了子代理的根任务占比17/21明显下降,小任务回到 L0
每个派发任务的子代理数4.6下降
根代理输出占比33%下降
Astra 积分占比57%大幅下降
审查线程至少 BLOCK 一次13/17保持;常规审查改用 GPT-6.1 Sol 后若明显下降,要检查漏判
线程上限失败0保持 0
按要求完成的根任务(单人判读)20/39上升,界面任务先过可见检查点
每个委派任务被纠正的次数1.0下降
失败轮次(其中满载)35(25),六周后备重派后,因满载停下等人的次数下降
GPT-6.1 Sol 根代理匹配延迟33 s改为 medium 后复测,同时看返工是否增加
上下文压缩(09-26 起有计时)216 次、6.9 h下降

统计脚本保存在本机 ~/.codex/scripts/:responses.py 抽取每次模型响应的延迟与 token,speed_report.py 出速度与波动报表,failures.py 统计失败与中断轮次,dispatch.py 统计派发合规和每条消息触发的派发。不做每周例行,换模型或改规则之后跑一次。

还没有验证的:后备重派在真实满载时的表现;根代理对照实验只跑了一个任务,要换一天重跑;GPT-6.1 Sol 与 GPT-6 Sol 作为实现者的质量差异,需要拿同样的任务在两个 worktree 里各跑一次;PreToolUse hook 能否在 v2 派发路径上拦截 spawn_agent;L2 及以上的派发是否真的在第一次派发前报告账本。