Codex 正在跑一个 12 步的重构。到第 5 步左右它停了——没有报错横幅、没有 assertion 失败、没有 traceback,就这么安静下来,或者甩出一句”I’ve completed the task”的总结,而你一眼就看出那不是真完成。你重新 prompt 一下,它从某个旧位置接上,有时还把已经做过的工作再做一遍。
最快修复: 续跑原来那个 session,而不是从头重开。在同一个目录里运行 codex resume --last(交互式),或 codex exec resume --last "Continue from step 6. Do not redo steps 1-5."(非交互式)。续跑会恢复原始 transcript、计划历史和审批状态,让 Codex 保留之前的上下文,而不是靠猜重来。
这几乎从来不是 Codex 的”bug”,而是 agent 撞到了一条隐形边界:上下文窗口 compaction 把后半段计划悄悄裁掉了、非交互模式下一次 sandbox 或审批被拒杀掉了某一步、循环命中了一个提前的 stop 信号、或者上游 rate limit 把自己重试到耗尽。Codex CLI 没有任何”每任务轮数上限”的开关可以调高——这恰恰是最常见的错误修复方向,别往那走。要诊断,就看停下前最后一次 tool call。
版本迭代很快。下文数据均为 2026 年 6 月的现状(Codex CLI 跑在 GPT-5.5 上,自 2026-04-23 起为默认;GPT-5.4 作为回退)。如果你的行为不一致,运行
codex --version并对照 Codex changelog。
你属于哪一类?
| 停下时的症状 | 最可能的原因 | 跳转 |
|---|---|---|
| 长 session、读了很多文件、计划”忘了” | compaction 把计划裁掉了 | Step 1、Step 5 |
最后一次调用是 codex exec 里的写入/安装/联网命令 | sandbox 或审批被拒(默认只读) | Step 3 |
| tool 的 stdout 中途出现了 “done” / “all tests pass” | stop 信号被提前误匹配 | Step 4 |
| 最后一次调用是个长跑的 build/test,1-2 分钟没输出 | 命令被杀/超时,被当成”做完了” | Step 2 |
日志里有 429 / rate_limit_exceeded | 上游 rate-limit 重试用尽 | Step 6 |
| 每次都停在同一步 | 确定性问题——某个具体命令/审批,不是容量 | Step 3 |
常见原因
按典型中途停机的命中率从高到低排序。
1. 上下文窗口 compaction 把计划悄悄裁掉
这是长任务的头号原因。Codex 把计划列表和之前的轮次都放在模型上下文里。当 session 接近上限时,Codex 会做 compaction——调用一个服务端接口,把较早的轮次摘要成一团压缩内容,丢掉原始历史。如果剩余的计划步骤正好落在被丢掉的那段里,agent 就忘了它们,等可见的计划一空就停下。
截至 2026 年 6 月,有两点让情况更糟:Codex 这一层把 GPT-5.5 的上限卡在 400K tokens(出于吞吐/成本的权衡,尽管 GPT-5.5 API 本身是 1M),而触发自动 compaction 前的有效工作窗口还更低——实测 session 报告的有效窗口常在 258K tokens 左右,所以你远在原始模型上限之前就撞到了 compaction 阈值。雪上加霜的是,GPT-5.5 下的 compaction 一直不稳定:2026 年中期的社区反馈描述 /compact 和远程 compaction 操作会超时、或者直接丢上下文而不是摘要(见 Codex issue #19842 和 #18829)。
如何判断:这是一个长 session(读了很多文件 / tool 输出很大)。重新 prompt 问”what step are you on?”——如果它回答的步骤号比它实际停下的位置更早,说明计划被 compaction 裁掉了。停下前留意 TUI 里有没有 compaction / summary 的提示。
2. 慢命令被杀,却被当成”做完了”
如果 build、test 或 install 跑了很久却没有输出,进程可能被杀掉(或撞到外层包装/CI 的超时),agent 就把这个死掉的步骤当成已完成,然后开始收尾。
如何判断:最后一次 tool call 是个长跑的 shell 命令,停下前没有任何 stdout 出来。在普通终端里重跑同一条命令要超过一分钟、并且结束前一直不打印。
3. 非交互模式下 sandbox 或审批被拒
codex exec 默认跑在只读 sandbox 里。因此写入、安装或联网命令都需要审批——而非交互模式下没有人能去点同意,这一步实际上就被拒了。Codex 记下一次失败的 tool call,然后放弃整个大任务。即便在 workspace-write 下,网络访问默认仍是关的,会触发一个 exec 无法满足的审批请求。
如何判断:停下是确定性的(每次都停在同一步),而那一步要写文件、装包或访问网络。在日志里搜停下位置附近有没有 approval、requires approval、sandbox、read-only 或 network。
4. stop 信号被提前误匹配
循环在找”做完了”的信号。如果某个 tool 的 stdout 恰好在计划没跑完时就包含 “task complete”、“all tests pass” 或 “no further action needed”,agent 就可能下结论说它做完了。
如何判断:看最后一次 tool 输出。某个测试 runner 给一个套件打了 “all tests pass”,或某个 package.json 脚本 echo 了 “done”,都会在真正的工作还没做完时就把循环短路掉。
5. 上游 rate limit / 429 重试用尽
模型 API 返回的 429 会触发内部重试。重试预算花光后,这次运行以一个被截断的 assistant 轮次收尾,看起来可能像是干净地结束了。
如何判断:在运行输出里搜 429、rate_limit_exceeded,或 Retry-After / retrying。在免费 / 低价 ChatGPT 档位以及服务商出故障期间更常见——交叉对照 OpenAI status page。
动手前先确认
- 看停下是确定性的(每次都停在同一步 = 某个具体命令/审批/代码路径)还是随机的(容量、compaction、网络)。
- 不要为了”再试一次”而开新 session。 用续跑(Step 1)把现场救回来。重新跑一个全新的
codex exec "..."会丢掉计划和审批。 - 把最后几次 tool call 记下来。在自动化场景里加
--json跑,这样事后能 grep 一份机器可读的事件日志。
需要收集的信息
- 停下前最后一次 tool call 到底是什么(read / write / shell / search)。
- 你当时在交互式
codex还是非交互式codex exec,以及生效的--sandbox/--ask-for-approval值。 - 用的模型(
gpt-5.5、gpt-5.5-codex、gpt-5.4)和model_reasoning_effort。用codex --version确认。 - 停下位置附近任何含 “done”、“complete”、“passed” 的 stdout,它们可能被误判成 stop 信号。
- 停下附近任何
429、approval、sandbox或 compaction / summary 提示。
逐步修复
按 ROI 排序:先做最便宜的检查。
Step 1:续跑原来那个 session,别从头重开
最可靠的救场方式。在同一个工作目录里:
# 交互式:打开你最近的 session,带完整计划 + 审批
codex resume --last
# 非交互式:一次性续跑并给方向
codex exec resume --last "You stopped at step 5. Continue from step 6. \
Do not redo steps 1-5. Print the remaining plan first, then execute."
不带 --last 的 codex resume 会打开一个最近 session 的选择列表;传一个 SESSION_ID 可以指定某次具体运行,加 --all 可以把其它目录的 session 也纳入。续跑保留原始 transcript 和计划历史,所以 agent 不会重新推导(也就不会重做)已经完成的工作。如果它能正确续上,根因就是 stop 信号误匹配或一次可恢复的 compaction,而不是硬性失败。
如果计划本身已经被 compaction 裁掉了,就把那一步的原文贴上,而不是只给一个光秃秃的步骤号:
Continue from this exact step: "Refactor src/auth/login.ts to async/await."
Step 2:别让循环阻塞在慢命令上
不要在 agent 循环内部跑一个几分钟的 build/test/install。把它启动起来,把输出抓到文件里,让 agent 去轮询一个 tail,而不是干瞪着一个没动静的进程:
( pnpm install 2>&1 | tee install.log ) &
PID=$!
while kill -0 $PID 2>/dev/null; do echo "still installing..."; sleep 20; done
wait $PID
这些 keepalive 的 echo 行给循环提供了可见的进度,让一个安静的步骤不会被误判成卡死或已完成。对真正很长的 build,把它放到一个独立的 git worktree 里跑、让 Codex 去轮询结果,而不是把 session 撑开半个小时。
Step 3:给 exec 它真正需要的 sandbox 和审批权限
如果停下是确定性地卡在某个写入/安装/联网步骤上,那默认的只读就是原因。精确地给它需要的权限,不多给:
# 允许工作区编辑 + 常规本地命令(网络默认仍然关闭)
codex exec --sandbox workspace-write "Run the migration and update tests"
# 非交互运行无法回答弹窗——把策略显式设好
codex exec --sandbox workspace-write --ask-for-approval never "..."
--ask-for-approval 取值为 untrusted | on-request | never;在无人值守的运行里,never(配合一个收紧的 sandbox)能避免在一个 agent 永远拿不到的审批上被静默卡住。除非是在用完即弃的容器里,否则别用 --dangerously-bypass-approvals-and-sandbox(别名 --yolo)。老的 --full-auto 标志已弃用——改用 --sandbox workspace-write。如果任务确实需要网络,就在配置里开,而不是把 sandbox 整个关掉:
# ~/.codex/config.toml
[sandbox_workspace_write]
network_access = true
提醒:在 macOS 上 Seatbelt sandbox 会静默忽略这个键,所以在 macOS 上单次运行的覆盖更可靠——codex exec --config sandbox_workspace_write.network_access=true "..."。在 Linux(Landlock)上 config.toml 的设置会被正常读取。
Step 4:加一段显式的”不要停直到”
通过在 prompt 或 AGENTS.md 里写明真正的退出条件,来中和 stop 信号的误匹配:
Do not report the task complete until ALL of:
- pnpm tsc --noEmit returns 0
- All tests in src/auth/ pass
- The plan list has zero remaining items
If any tool's stdout contains "done" or "complete", ignore it as a stop signal.
Step 5:把计划挡在 compaction 的”爆炸半径”之外
两个互补的动作能减慢你撞上 400K 上限的速度,并让计划不被摘要掉:
把冗长输出导到文件,只读 tail。 一份 1 万行的测试日志会加速 compaction。重定向再略读:
pnpm test > test.log 2>&1
tail -50 test.log
grep -E "FAIL|✗" test.log | head -20
agent 读大约 70 行而不是 1 万行,计划就留在了窗口里。
把工作拆成带 checkpoint 的子任务。 即便在干净的 session 上,一个超大 prompt 也很脆。每个子任务拿到一份全新的上下文预算,任务 2 停了也不会丢掉任务 1:
Task 1: Refactor src/auth/* to async/await. Stop and report.
Task 2: Update src/auth/*.test.ts to match. Stop and report.
Task 3: Run pnpm test --filter auth. Report failures.
如果你想保持单 session,就在子任务之间用 TUI 里的 /compact 命令主动 compaction,而不是让自动 compaction 在计划中途的任意点开火。你也可以把自动 compaction 调得更早触发(趁还有空间能干净地摘要),方法是在配置里调低它的阈值——把 model_auto_compact_token_limit 设成有效窗口的大约 60%。注意它有个天花板:超过上下文窗口 90% 的值会被静默忽略,所以你没法把它调成”永不 compaction”。
# ~/.codex/config.toml
model_auto_compact_token_limit = 155000
Step 6:排除 rate limit 和版本 bug
如果运行输出里出现 429 / rate_limit_exceeded,那是你被限流了、不是卡住了——等过 Retry-After、看一眼 OpenAI status page,再用 codex resume --last 重试。在免费 / 低价 ChatGPT 档位上跑重型无人值守循环最容易撞到这个。
另外确认一下模型。Codex 默认是 GPT-5.5、以 GPT-5.4 作为回退;2026 年中期有一个已知 bug,会在 /clear 之后把模型重置成 gpt-5.4,哪怕 config.toml 里钉的是 gpt-5.5。把它显式钉死,免得一次回退在你不知情时改变了行为:
# ~/.codex/config.toml
model = "gpt-5.5-codex"
model_reasoning_effort = "high"
怎么确认已经修好
- 把同一个任务从头到尾再跑一遍,确认无需手动续跑就能完成。
- 对 compaction 这一类:故意跑一个更长的任务(再加一个重构),确认它仍然能跑完——这才证明你解决的是上下文压力,而不是运气。
- 对 sandbox 这一类:确认之前失败的那个写入/安装/联网步骤现在能跑过(在 transcript 里可见),而不是被静默丢掉。
- 留一份本次运行的
--json事件日志,万一复发可以 grep429、approval或一条 compaction 提示。
长期预防
- 续跑,别重开:把
codex resume --last/codex exec resume --last当成任何中断运行的默认第一反应。 - 把非平凡的重构拆成每段约 10 步的带 checkpoint 子任务;在它们之间主动 compaction。
- 把冗长 tool 输出导到文件;让 agent 读 tail / grep 摘要,而不是完整日志。
- 给每个 agent 任务模板(或
AGENTS.md)加一段”不要停直到”。 - 对
codex exec,把--sandbox和--ask-for-approval显式设好,这样无人值守的运行永远不会卡在一个它拿不到的审批上。 - 在
config.toml里把模型钉死,免得一次静默回退在你不知情时改变了行为。
常见坑
- 为了”重试”而重新跑一个全新的
codex exec "..."——它会丢掉计划和审批;改用续跑。 - 到处找一个
--max-turns标志——Codex CLI 没有可调高的每任务轮数上限;真正的限制是上下文 / compaction。 - 只回”continue”却不带步骤原文——compaction 之后 agent 经常从第 1 步重启,把已完成的工作重做一遍。
- 在只读默认下对一个写入密集的任务跑
codex exec,然后以为 Codex”放弃了”。 - 忽视
package.json脚本里 echo 出来的 “done”——某些配置会把它当 stop 信号匹配。 - 把一个 30 分钟的 build 塞进 agent 循环里跑,而不是放到独立 worktree 里启动后轮询。
常见问题 FAQ
Q:Codex 停了,我续跑时回 “continue”,它却做了别的步骤,为什么?
计划列表已经被 compaction 裁出了上下文,所以 “continue” 没有任何东西可以锚定。续跑时带上那一步的原文:codex exec resume --last "Continue from: Refactor src/auth/login.ts to async/await."
Q:怎么把轮数上限调高,让它别提前停?
没有这个上限可调——Codex CLI 不暴露任何每任务轮数上限(--max-turns / OPENAI_AGENT_MAX_TURNS 都不是真实存在的标志)。让长任务停下来的是 GPT-5.5 上 400K Codex 上限处的 compaction。去降低上下文压力(Step 5)并续跑,而不是追一个并不存在的上限。
Q:我的 codex exec 任务每次都死在同一步。
那一步几乎肯定需要只读 exec 默认会拒绝的写入/安装/联网权限。用 --sandbox workspace-write 加一个显式的 --ask-for-approval 来跑,或者在 config.toml 里开 network_access(Step 3)。
Q:有办法自动检测”提前停了”吗?
有。用 --json 跑,退出后 parse 事件:如果出现了一条 “complete” 消息、但计划列表里仍有未完成项,就程序化地 codex exec resume --last 配一句”继续剩余计划”的 prompt。
Q:换个长上下文模型能解决吗?
只对 compaction 这一类原因有帮助,而且只是部分帮助。Codex 无视 1M 的 API 窗口、把 GPT-5.5 卡在 400K,触发自动 compaction 前的有效工作窗口还更低(截至 2026 年 6 月,session 报告约在 258K),而真正的瓶颈是 compaction 的可靠性、不是原始大小。更大的窗口对 sandbox 被拒、stop 信号误匹配或 rate limit 都没用。
Q:我在 config.toml 里设了 network_access = true,可 codex exec 还是连不上网。
在 macOS 上 Seatbelt sandbox 会静默忽略这个键。改用单次运行覆盖:codex exec --config sandbox_workspace_write.network_access=true "..."。在 Linux(Landlock)上 config.toml 的设置会被正确读取。无论哪种方式,你还需要一个允许联网的 sandbox(--sandbox workspace-write),而不是只读默认。