为什么一个巨型指令文件会拖垮你的 Agent
600 行的 CLAUDE.md 是自我强化的失败循环,拆成入口加分册才是解药。
立靶:文件越大,Agent 越笨,这是一个会自我强化的循环
你给 Agent 写了一份 CLAUDE.md。第一周它 80 行,跑得挺好。于是你不断往里加:又踩了个坑,加一条;又定了个规范,加一条;某次方案讨论的结论,也顺手记进去。三个月后它 600 行了——然后你发现 Agent 开始忽略你白纸黑字写下的硬约束。
这不是错觉,而是一个自我强化的失败循环:
- 文件越大 → 吃掉的 context 预算越多 → 留给实际任务的注意力越少 → Agent 表现越差
- Agent 表现越差 → 你越想「再写一条说明它就懂了」→ 文件继续变大 → 表现继续变差
walkinglabs 的 Harness Engineering 把这条循环点破:把所有指令塞进一个大文件,是新手做 Agent 工程最常见、也最隐蔽的反模式。 隐蔽在于,它在小规模时完全无害,等你发现不对劲时,文件已经大到「不敢动」了。
框架:巨型指令文件的四个失败机理
把它们并排放,你会发现这四个问题互相喂养——不是四个独立 bug,而是同一个病灶的四张脸。
| 机理 | 现象 | 为什么致命 |
|---|---|---|
| ① context 预算耗尽 | 一个臃肿文件吃掉 10–20K token,每一轮对话都重复加载 | 这部分 token 每轮都是固定开销,挤占任务、检索结果、对话历史的空间 |
| ② lost in the middle | 长文本中段的利用率显著低于开头和结尾 | 关键硬约束如果埋在第 300 行,模型读得到但「看不见」——优先处理首尾,中段被系统性稀释 |
| ③ 优先级糊成一锅 | 硬约束、设计建议、历史注记用同一种格式平铺 | 模型无法区分「绝对不能违反」和「可以参考」——一条铁律和一句随手记的 TODO 长得一模一样 |
| ④ 维护腐化 | 增加一条无成本,删除一条有风险(怕删错),于是文件只增不减 | 熵单调增加。没人敢删的文件,最终变成所有人都不读、Agent 也读不进的「考古地层」 |
四者的合力:①让有效注意力变少,②③让仅剩的注意力还用错地方,④保证情况只会越来越糟。这就是为什么「再加一条」永远治不好病——你是在给一个已经溺水的人灌水。
框架:文件柜——入口文件 + 专题分册
walkinglabs 给的解药是一个生活比喻:文件柜。你不会把内衣、洗漱用品、文件、药品全堆进一个箱子,然后每次找东西都翻到底。你会分抽屉。Agent 的指令也该如此——入口文件只放「永远要看」的,专题分册按需拉取。
| 层级 | 文件 | 行数 | 装什么 | 不装什么 |
|---|---|---|---|---|
| 入口(抽屉柜的标签) | AGENTS.md / CLAUDE.md | 50–200 | 项目概览 + 启动命令 + ≤15 条硬约束 + 指向分册的链接 | 详细方案、历史决策、长清单 |
| 专题分册(各个抽屉) | docs/ 下每个文件 | 50–150 | 单一主题的细节(如部署、数据模型、某子系统约定) | 与本主题无关的任何内容 |
两条数字纪律是关键:入口 ≤ 200 行、硬约束 ≤ 15 条。超出就说明你把不该进入口的东西塞进来了。入口文件的职责不是「说清一切」,而是「告诉 Agent 去哪儿找清楚一切」。
这正好接上上下文工程的视角:入口文件是每一轮都固定加载、应当 100% 命中 prompt cache 的部分;专题分册更像按需拉取的检索/记忆,不占每轮固定预算。把分册塞回入口,等于把本该 lazy 的东西改成 eager,白白烧掉每一轮的 token。
case:一份「不堆一起」的入口文件实例
这门公开课项目,入口文件就是按文件柜架构写的。它没有把需求、方案、架构、进度全堆进 CLAUDE.md,而是做了两件事:
第一,用「入会顺序」代替「全文背诵」。 入口文件开头不是一长串规则,而是一份读取顺序清单:
1. 先读
STATUS.md(一句话状态 + 下次入口 + 踩坑清单) 2. 再读PRD.md/SPEC.md/architecture.md/features.json3. 开工前跑bash M1/init.sh确认环境全绿
这等于把抽屉的「打开顺序」写在柜门上。Agent 不需要在入口文件里读到需求细节,它只需要知道「需求在 PRD.md,要看去那儿拉」。需求、方案、架构各自是一个分册(三件套),进度是另一个分册(STATUS.md),互不污染。
第二,入口只留「每轮都要的硬约束」,细节全部外链。 视觉规范在入口只有一句「橙皮书风 + 禁 emoji + 图标用 line-SVG」,完整视觉系统在 assets/ 的 CSS 里;讲义体的硬规矩在入口一行带过,schema 细节在 SPEC.md。
对照四个失败机理,这套结构逐条拆弹:对①入口短,每轮固定开销小;对②硬约束集中在短文件里,没有「中段」可埋;对③入口里出现的就是硬约束,格式上天然区分于分册里的建议/细节;对④删除分册的某条细节,影响面被锁在那个分册内,你敢删了。
一个反向教训:某 SDK 默认 setting_sources=['user','project'],会偷偷把 ~/.claude/CLAUDE.md(约 17K token 的暗物质)注入每一轮。这是「巨型文件失败」的隐身版——你的入口文件明明很干净,但框架在背后帮你堆了个 600 行进去。设 setting_sources=[] 后,纯文本轮从 4.5s 降到 2.4s。机理①不只来自你写的文件,也来自 SDK 替你加载的文件。
可操作做法:从巨型文件到文件柜的迁移清单
- 先量,再拆。 拆之前跑一次「上下文体检」:打印入口文件实际占多少 token,顺手审 SDK 有没有偷塞(
setting_sources这类暗默认)。没有数字就别凭感觉拆。 - 画一张上下文构成表。 把入口文件里每一段标三列:
来源 | 每轮是否必看 | 该进入口还是分册。「每轮必看的硬约束」留入口,其余全部标记外迁。 - 按主题切分册,每册 50–150 行。 判据是「找这类信息时会不会一起找」——会一起找的放一册,不会的拆开。
- 入口瘦身到 ≤200 行、硬约束 ≤15 条。 超出的问自己:这是「每轮都要遵守的铁律」还是「需要时才查的细节」?后者一律外链。
- 用「读取顺序」替代「全文罗列」。 入口开头写一份入会清单,告诉 Agent 先读什么、去哪儿拉细节。
- 给硬约束一个视觉锚点。 把 ≤15 条硬约束集中成一个带标记的列表,让它们在格式上明显区别于建议。
- 立一条维护纪律对抗机理④:增加分册细节无需谨慎,但任何内容进入口必须过一道「这是否每轮都要看」的闸门。把「删除有风险」转成「进入有门槛」。
收口
巨型指令文件的失败,不是因为你写得不够多,恰恰是因为写得太多——Agent 的注意力是一笔固定预算,你往入口里多塞一行,就是从任务身上扣一行。
好的指令架构,是一个标签清楚的文件柜,不是一个塞满的箱子。入口只回答「去哪儿找」,专题分册回答「具体怎么做」。