你让 Codex Agent 加一个函数。Transcript 显示它写第一行代码之前调了 47 次工具:Read package.json 四次、同一个 pattern 的 Glob "**/*.ts" 三次、Read src/types.ts 八次,其中两次还是连着。等它终于开始写代码时,turn 预算已经用了一半、相关上下文也被挤出了窗口。最后产出形状错了,它从没真正落到问题上。
最快修法(90 秒): 先用 Codex CLI 的 /plan 模式跑一遍,让 agent 只读、只分析、提出 plan,不动文件;然后在项目根目录放一份精简的 AGENTS.md 结构图,让它不必反复发现结构;再把 model_reasoning_effort = "medium"(GPT-5.5 默认值)保持住,别拉到 xhigh,后者反而会增加探索性读取。光这三招通常就能把冗余 tool 调用砍掉 40-70%。
冗余 tool 调用不是模型缺陷,是 agent 在搜不在建的信号。它没地图、没计划、没”最近读过什么”的缓存,每一次 tool 调用都是猜。修法是提前给地图、写代码前先写 plan、prompt 结构上不让 agent 重新发现你已经知道的事。
先判断你属于哪一类
| Transcript 里的症状 | 最可能的原因 | 跳到 |
|---|---|---|
| 前 5+ 次都是 read 且后面没 edit | 没结构图 | Step 1 |
Read → Write → Read → Write 穿插 | 动手前没写 plan | Step 2 + /plan |
| N 个 grep match 后跟着 N+ 次 read | search 结果没摘要 | Step 3 |
同一个 Read <path> 出现 3+ 次 | 没有”读过什么”的缓存 | Step 4 |
大量 ls / wc / head 灌水、无 edit | 工具被当思考辅助 | Step 5 |
| 5000 行 stdout 之后立刻重读 | 冗长输出引发重读 | Step 6 |
常见原因
按命中率排序。
1. 没结构图:agent 重新发现结构
你说”加个新 endpoint”。Agent 不知道 endpoint 在哪。它读 package.json、tsconfig.json,扫 src/,读 index.ts、app.ts、server.ts。一句话本来能告诉它的事,它读了 5 次。
如何判断:前 5+ 次 tool 调用是探索不是行动,read 之后没跟着 edit。
2. 动手前没写 plan
Agent 直接开编辑、撞到未知、再读、再编辑、再撞到未知。每个未知触发新 read。没写 plan,每个决定就变成临时查阅。
如何判断:Tool 调用穿插 Read → Write → Read → Write,而不是集中 Read 阶段 → 集中 Write 阶段。
3. Search 结果没做摘要
Agent 跑 grep -rn "useAuth" src/ 得到 80 个 match。不是摘要 / 过滤,而是一个个把 match 的文件读完。5 分钟后忘了摘要又跑一次同一个 query。
如何判断:grep N 个 match 之后跟着 N+ 次 file read——agent 没在读之前收敛。
4. 上下文里没有”我读过什么”的缓存
Agent 忘了它读过某个文件。10 turn 之后再提到同一路径 → 重读。没有结构性指针”文件 X 我们已经覆盖过”。
如何判断:同一个 Read <path> 在 transcript 里出现 3+ 次。
5. Tool 调用被当作思考辅助
某些 prompt 下 agent 更愿意跑 ls、cat、wc 来代替推理。像在”检查”而不是 commit 到决策。turn 数翻倍但没进展。
如何判断:大量便宜的、单文件 head / ls / wc 调用,中间没 edit。
6. 冗长 stdout 引发重读
某次 tool 调用返回 5000 行。Agent 在工作记忆里端不住,部分信息被 summarize 掉,它又重读同一文件的某些部分来”验证”。
如何判断:吵的工具输出之后紧跟着重读刚刚同一路径。
动手前先确认
- 拿一份典型任务的 tool 调用计数基线——
grep -c "tool_use" agent.log之类。 - 识别 agent 模板的探索阶段长度——长探索 = 症状。
- 判断这次是”我不熟这个仓库”还是”我熟但让 Codex 自己重推”——两个修法不同。
需要收集的信息
- 出问题那次跑的完整 transcript + 各类 tool 调用计数。
- 前 10 次 tool 调用——通常能看出 agent 是有图还是在搜。
- 任务 prompt 的原文——含糊的 prompt 引发更多搜索。
- 任何本来可以喂给 agent 但没喂的 AGENTS.md / repo-map.md / 约定文档。
最短修复路径
按收益从高到低。
Step 1:用 AGENTS.md 预喂地图(不只是 prompt)
Codex CLI 会在每个 session 的第一个 turn 自动把项目根目录(以及更近目录)的 AGENTS.md 加载进来,所以地图会跨任务持久化,不用每次重打。把结构图放进去:
# AGENTS.md
## 仓库结构
- API 路由:src/api/routes/*.ts(一个 resource 一个文件)
- Services:src/services/*.ts(业务逻辑)
- 类型:src/types/index.ts(共享)+ src/types/<feature>.ts(feature 专属)
- 测试:和源代码并列 *.test.ts
## 约定
- 新 endpoint = 路由文件 + service 方法 + 类型条目 + 测试
- 永远别读 node_modules 或 dist,都是构建产物
截至 2026 年 6 月有两个坑:Codex 每个 AGENTS.md 只读到 project_doc_max_bytes(默认 32 KB),所以地图要简短;如果你的文件叫别的名字,得在 ~/.codex/config.toml 里用 project_doc_fallback_filenames 注册,否则会被忽略。两个 key 都见 OpenAI 的 Codex 配置参考。
具体任务仍然在 prompt 顶端圈定范围:
本次任务需要编辑:
- src/api/routes/orders.ts(新建)
- src/services/orderService.ts(扩展)
- src/types/order.ts(扩展)
- src/api/routes/orders.test.ts(新建)
Agent 一次 read 都不用就拿到结构图,省 5-15 次冗余探索调用。
Step 2:用 /plan 模式强制先探索再动手
Codex CLI 自带 /plan 模式:模型只读文件、分析代码库,然后提出实现 plan,在你批准前什么都不写。这正是你想要的结构化探索阶段,能掐掉那种引发重读的 Read → Write → Read → Write 穿插。输入 /plan(或在 composer 里用 Tab 切换 plan 模式),看完 plan,再退出执行。
如果你在写脚本、或想在普通 turn 里要一个 plan,就显式要求:
先写 plan。输出:
PLAN:
1. <step>
2. <step>
...
每步列出涉及的文件。确认 plan 在 working scope 内,然后才能开始编辑。
执行中需要改 plan 就输出 REVISED PLAN 再继续。
Plan 模式有自己的 reasoning 预算:plan_mode_reasoning_effort(取值 none | minimal | low | medium | high | xhigh)让你在规划时多想,而不必把这个成本摊到每个执行 turn 上。任务动到三个以上模块就用 /plan;一行小改就别用,规划开销不划算。
Step 3:多 match search 之后强制摘要
任何 grep / glob / search 返回 > 5 个结果,输出 SUMMARY:
SUMMARY of "<query>":
- M 个文件 N 个 match
- 相关文件:<列 1-5>
- 跳过:<列>
然后只读相关文件,不要每个 match 都读。
一份 grep 摘要 + 3 次 read 胜过 80 次原始 match 读。
Step 4:在 prompt 里维护显式 read tracker
每次 Read 完追加到 scratchpad:
READ_TRACKER:
- src/types/order.ts(step 2 时读过)
- src/services/orderService.ts(step 3 时读过)
Read 之前先查 tracker。文件已列出就凭记忆回忆,内容没变就不重读。
把”读过什么”的缓存外置化,agent 必须显式承认重读。session 特别长时,在 read 历史滚出窗口之前先跑 /compact 把早期 turn 压成一份小摘要;这通常比让 agent 重读掉到队尾的内容更省。
Step 5:把任务用不到的工具直接关掉
在 ~/.codex/config.toml(或项目级 .codex/config.toml)里,关掉那些诱发乱调用的能力:
# 封闭仓库任务别让 agent 去联网
web_search = "disabled" # 取值:disabled | cached | live
# 任务没真需要就别 spawn 子 agent,
# spawn_agent / wait_agent 各自都加 tool-call 开销
[features]
multi_agent = false
然后用 /plan(只读)后接执行来驱动阶段,而不是指望模型在 turn 中途自我约束。拿掉一个工具,就彻底拿掉了”我再查最后一件事”的念想。也可以按单次任务用 inline override,比如 codex -c web_search='"disabled"'。
Step 6:吵的工具输出加帽
爱灌水的命令包一层:
pnpm test 2>&1 | tee /tmp/test.log | grep -E "FAIL|PASS|Tests:" | head -50
输出少 → 为验证而重读也少。很多冗余 read 是在追被一墙 stdout 淹没的信号。
Step 7:先调 reasoning effort,再调模型
Reasoning effort 的影响比多数人以为的大。model_reasoning_effort 取值 minimal | low | medium | high | xhigh,GPT-5.5 默认 medium,对 agentic 编码就是合适的平衡点。反直觉的是,拉到 xhigh 往往增加探索性 tool 调用,因为模型会反复自我怀疑;对范围明确的紧凑任务,medium(甚至 low)反而读得更少、收尾更快。
# ~/.codex/config.toml
model = "gpt-5.5"
model_reasoning_effort = "medium"
模型本身:GPT-5.5 是 OpenAI 给 Codex 推荐的起点,达到同样结果所用 reasoning token 比老的 GPT-5.4 更少,这在 tool 密集、多步的跑里会复利累积。想再进一步,可以用 Codex 专调的变体(gpt-5.2-codex 系列),专为 agentic 编码而生。截至 2026 年 6 月有个已知 bug 要注意:在交互式 CLI 里打 /clear 可能把你掉回 gpt-5.4,而不是 config.toml 里的模型(openai/codex #19451)。clear 之后记得复查底部的模型标识。
怎么确认已经修好
- 下一次跑数一下 tool 调用——光 Step 1-3 通常掉 40-70%。
- 看 transcript:清晰的 Read 阶段 → Plan 输出 → Write 阶段,而不是混在一起。
- 整跑里没有重复
Read <同一 path>。 - 完成所需 turn 数下降、有余量地在 turn 预算内结束。
长期预防
- 仓库根目录常驻一份
AGENTS.md,写清”X 住在哪”的标准约定;Codex 每个 session 自动加载它,而不是重新发现结构(保持在project_doc_max_bytes以内)。 - 任何多文件改动默认走
/plan;一行小改可跳过。 - 在
config.toml里钉死model = "gpt-5.5"和model_reasoning_effort = "medium",免得某个乱入的xhighprofile 抬高读取量。 - 默认关掉仓库永远用不到的工具(
web_search = "disabled"、features.multi_agent = false)。 - 默认给吵的工具加输出帽,agent 永远见不到 5000 行 stdout。
- 留一份 agent-runs.log,每周复盘:tool call 超过 60 次的跑都要找根因。
常见坑
- 把”tool 调用更多 = 更彻底”当好事。每次调用都耗上下文和 turn,冗余是纯成本。
- prompt 里写”不要重读文件”但没给 agent tracker 机制——指令落不了地。
- 让 agent 在大仓库跑
find . -type f——光是输出就把预算炸光。 - 把 turn 预算调到 200 来”吸收”冗余——冗余在能装下时仍然拉低输出质量。
- 忘了 prompt cache 让冗余 dollar 上更便宜但 window 上依然贵。
常见 FAQ
Q:Agent 在相邻两次 turn 重读同一文件,为什么?
大概率你的 runner 没把”前序 tool 调用”surface 出来,agent 的 plan 也没引用那次 read。加显式 READ_TRACKER scratchpad 就好了。
Q:怎么自动数 tool 调用次数?
大多数 agent runner 会发 JSON event stream。数 tool_use 类型的记录。文本日志的话:grep -c "function_calls" transcript.txt。
Q:“read / edit 比例”有健康值吗?
粗略:熟悉代码 2-4 读 1 编辑,不熟悉 5-8。如果看到 15+ 读 1 编辑,prompt 缺结构图。
Q:直接把 max-turns 调低能强制提高效率吗?
调低 max-turns 也会惩罚正经工作。不如修原因(没图、没 plan):效率上来的同时余量也变大。
Q:/plan 模式是真的减少 tool 调用,还是只是推迟?
是真的减少。在 /plan 模式里 Codex 把读取和分析一次性、提前做完,动文件之前就 commit 到一个 plan。这把”读-改-读-改”的反复(每撞到一个意外就触发一次新 read)换成一遍集中的探索,所以同一批文件不会在编辑中途被反复重读。
Q:/clear 之后我的 agent 突然又把所有文件读一遍,正常吗?
正常。/clear 会清掉整段对话,包括 read 历史和上下文里的地图,所以下一个任务从零开始。把仓库地图放进 AGENTS.md(Step 1)让它自动重载;同时复查底部模型标识:有个已知 bug 会在 clear 后把模型重置回 gpt-5.4。