Advanced Context Engineering · HumanLayer

让 AI 在复杂代码库中真正干活

Getting AI to Work in Complex Codebases —— 「频繁有意压缩」工作流全解
✍️ Dex Horthy(HumanLayer) 📄 原文:ace-fca.md(GitHub) 🎓 Stanford CS146S · Week 3 读物 🧭 主题:上下文工程 / 编码智能体

「AI 编码工具搞不定真实生产代码库」几乎是行业共识。作者用几个月的摸索给出反例:不必等更聪明的模型,只要把整个开发流程围绕上下文管理重新设计——保持上下文利用率在 40%–60%,在杠杆最高的位置插入人工审查——今天的模型就能在 30 万行的 Rust 代码库里修 bug、一天干完一周的活,且代码质量能通过专家评审。

🧱

行业共识:AI 搞不定真实代码库

01

文章开篇直面一个普遍接受的判断:AI 编码工具在真实生产代码库里表现挣扎。支撑这个判断的是斯坦福关于 AI 对开发者生产力影响的研究,它发现:

  1. AI 工具产出的很多「额外代码」,其实只是在返工上周刚交付的劣质代码(slop)——表面产出高了,净产出没那么好看。
  2. 编码智能体对全新项目和小改动很拿手;但在大型成熟代码库里,它们经常反而让开发者更低效

对此,行业的常见反应介于两个极端之间:悲观派说「这永远行不通」,温和派说「也许等模型更聪明的那天吧」。

而作者在几个月的折腾之后给出第三种回答:只要拥抱核心的上下文工程原则,今天的模型就能走得很远

🎯 作者的可信度声明(原文如此,非广告腔)
这不是又一篇「10 倍生产力」的推销文。作者自称对 AI 炒作机器一贯保持克制态度。但他们摸索出的工作流让他对可能性抱有相当大的乐观:他们让 Claude Code 处理过 30 万行代码(LOC)的 Rust 代码库一天交付一周的工作量、并且代码质量能通过专家评审

这套技术家族被作者命名为频繁有意压缩(frequent intentional compaction)——在整个开发过程中,刻意地设计「喂给 AI 什么上下文」这件事。他现在完全确信:AI 编码不只是玩具和原型的游戏,而是一门深度技术性的工程手艺(a deeply technical engineering craft)。

🎬 视频版:本文基于作者 8 月 20 日在 Y Combinator 的一场演讲,偏好视频可看 hlyr.dev/ace
🎤

思想源头:AI Engineer 2025 的两场演讲

02

作者说,AI Engineer 2025 大会上的两场演讲,从根本上塑造了他对这个问题的思考。

演讲一 · Sean Grove:「Specs 是新的代码」
是什么

Sean 认为我们所有人的 vibe coding 方式都错了:和 AI 聊两个小时、说清楚你要什么,然后扔掉全部提示词、只提交最终代码——这就像一个 Java 开发者编译出 JAR 包后,把编译产物签入版本库,却把源代码扔掉。

推论

在 AI 的未来,规格(specs)才是真正的代码。Sean 预言:两年后你打开 Python 文件的频率,大概相当于今天你打开十六进制编辑器去读汇编的频率——对多数人来说,就是「从不」。

演讲二 · Yegor(斯坦福研究):AI 对生产力的真实影响
是什么

这项研究分析了 10 万名开发者的提交记录,发现:① AI 工具常导致大量返工,让感知到的生产力增益大打折扣;② AI 工具在绿地(greenfield,全新)项目里表现好,但在棕地(brownfield,存量)代码库和复杂任务上常常适得其反。

斯坦福研究截图:AI 工具导致的返工吞噬产出
原文配图 · 斯坦福研究:返工吞噬感知产出(原图)
斯坦福研究截图:绿地 vs 棕地项目中 AI 工具效果对比
原文配图 · 斯坦福研究:绿地 vs 棕地对比(原图)

这和作者跟创业者们聊天听到的声音完全一致:

对「用 AI 干难活」这件事,大家的普遍情绪就是一句:「也许等模型更聪明的那天吧……」。作者还举了个例子:就连 Replit 的 Amjad,9 个月前在 Lenny 的播客上也在讲「PM 用 Replit agent 做原型,然后交给工程师去实现生产版本」。(作者自注:他最近没跟 Amjad 聊过——好吧,从来没聊过——这个立场可能已经变了。)

每当听到「也许等模型更聪明的那天」,我都会立刻跳出来喊:这正是上下文工程要干的事——把「今天的模型」的潜力压榨到极致。
—— 作者对「等模型论」的回应
🚀

今天就能做到什么(BAML 实证预告)

03

为了证明这不是纸上谈兵,作者先抛出一个具体例子(后文详述):几周前,他决定在 BAML——一个 30 万行 Rust 代码的 LLM 编程语言项目——上测试自家技术。要知道,作者顶多算 Rust 业余选手,而且此前从未碰过 BAML 代码库。

≈1 小时
产出一个修 bug 的 PR
次日早上被维护者批准合并
35k LOC
几周后与 @hellovai 结对
为 BAML 交付 3.5 万行代码
7 小时
两个「各需资深工程师 3–5 天」的特性
全部做到 draft PR 就绪

那 3.5 万行代码是与 @hellovai 结对完成的,添加的是取消支持(cancellation)WASM 编译两个特性——BAML 团队估计每个都要一位资深工程师干 3–5 天。

这一切围绕的就是频繁有意压缩工作流:把整个开发过程设计成围绕上下文管理来转,把上下文利用率保持在 40%–60% 区间,并在恰当的位置内建高杠杆的人工审查。他们用的是「研究、计划、实现」三步工作流,但作者强调:这里的核心能力和经验教训,远比任何具体工作流或提示词模板更通用

🛤️

一段不舒服的转型之旅

04

这套方法的起点,是一个真实的团队困境。作者当时正与他见过的最高产的 AI 编码者之一共事:此人每隔几天就甩出一个 2000 行的 Go PR。而且这不是什么 Next.js 应用或 CRUD API,而是复杂、易发竞态的系统级代码:在 Unix socket 上跑 JSON RPC、管理 fork 出来的 Unix 进程的流式 stdio(大部分是 Claude Code SDK 进程)。

每隔几天仔细读完 2000 行复杂 Go 代码?根本不可持续。作者说自己当时的心情,有点像 Mitchell Hashimoto 给 ghostty 加上「AI 贡献必须披露」规则时的状态。

他们的解法,是采纳类似 Sean 说的规格驱动开发(spec-driven development):

  • 一开始非常不舒服——作者必须学会放弃「逐行读完每个 PR」的执念。
  • 测试代码他仍然读得很仔细;但规格(specs)成了团队关于「在做什么、为什么做」的唯一真理源
  • 整个转型花了约 8 周,对所有人都极其难受,作者本人首当其冲。

然后就起飞了:几周前作者一天交付了 6 个 PR;过去三个月里,他手动编辑非 Markdown 文件的次数一只手数得过来

🎯 团队要的四样东西
① 能在棕地(存量)代码库里好好干活的 AI;② 能解决复杂问题的 AI;③ 没有 slop;④ 维持全团队的心智对齐(mental alignment)。(作者补了句玩笑:好吧,顺便尽量多烧点 token。)接下来他将展开:1)把上下文工程用在编码智能体上学到了什么;2)这门手艺「深度技术性」体现在哪些维度;3)为什么他不认为这些方法可以泛化;4)以及他在第 3 点上被反复打脸的次数。
🪜

从朴素用法到「有意压缩」

05

大多数人一开始把编码智能体当聊天机器人用:跟它来回说话(或者像 Geoff Huntley 说的,「醉醺醺地朝它嚷嚷」),凭感觉推进,直到:上下文用光、你放弃,或者智能体开始道歉。

聪明一点的做法:发现跑偏就丢弃会话、重开一个,在新提示里多给点方向修正,比如:

[原来的提示], 但务必使用 XYZ 方案,因为 ABC 方案行不通
原文示意图:把智能体当聊天机器人用
原文配图 · 聊天式用法(原图)
原文示意图:重开会话并加方向修正
原文配图 · 重开会话加方向(原图)

🧳 再聪明一点:有意压缩(Intentional Compaction)

你可能已经做过作者称为有意压缩的事:不管当前跑没跑偏,当上下文开始填满时,主动暂停工作,把状态写进文件,然后带着一个新鲜的上下文窗口重来。常用的提示长这样:

"把我们目前做的一切写进 progress.md,务必写明:
 最终目标、我们采取的方案、已完成的步骤、
 以及当前正在处理的失败问题"
原文示意图:有意压缩
原文配图 · 有意压缩(原图)

你也可以用 commit message 来做有意压缩

🍽️ 我们到底在压缩什么?

什么东西在吃掉上下文?

这些都会淹没上下文窗口。压缩(compaction),就是把它们蒸馏成结构化的工件(structured artifacts)

原文截图:一次好的有意压缩产出示例
原文配图 · 好的压缩产出长这样(原图)
上下文吞噬者 📂 搜索文件 🧭 理解代码流 ✏️ 应用编辑 🧪 测试/构建日志 🧾 巨型 JSON 数据块 …不断淹没上下文窗口 压缩 结构化工件 progress.md / 研究文档 目标 · 方案 · 已完成步骤 当前卡点 新鲜上下文窗口 轻装上阵 直奔正事
图 1 · 「有意压缩」:把吃上下文的原始过程蒸馏成结构化工件,再用它开启新鲜窗口
🔬

为什么要痴迷上下文?

06

正如作者在 12-factor agents 里深入讲过的:LLM 是无状态函数。在不训练/微调模型本身的前提下,唯一影响输出质量的,就是输入的质量

这条规律对「驾驭」编码智能体和设计通用智能体同样成立——只是问题空间更小:我们讨论的不是「构建」智能体,而是「使用」智能体。在任意时刻,Claude Code 这类智能体的一轮(turn)就是一次无状态函数调用:上下文窗口进,下一步动作出

上下文窗口 你唯一能控制的杠杆 LLM 无状态函数 下一步动作 质量 = f(输入质量)
图 2 · 每一轮都是无状态函数调用:上下文窗口的内容,是影响输出质量的唯一杠杆
原文示意图:LLM 是无状态函数,上下文进、下一步出
原文配图 · 无状态函数调用(原图)

也就是说,上下文窗口里装了什么,是你影响输出质量的唯一抓手。所以,是的,值得为它痴迷。

✅ 上下文窗口要优化的四件事
  • 正确性(Correctness)
  • 完整性(Completeness)
  • 大小(Size)
  • 轨迹(Trajectory,推进方向)
⚠️ 最糟的三件事(按严重程度排序)
  • 错误信息进入上下文
  • 缺失信息
  • 噪音太多
原文截图:作者自嘲的傻瓜公式
原文配图 · 作者自嘲的「傻瓜公式」(原图)
游戏规则是:你只有大约 17 万 token 的上下文窗口可用。所以关键是尽可能少用。上下文窗口用得越多,结果越差。
—— Geoff Huntley(@GeoffreyHuntley)

🤪 Ralph Wiggum:一个「蠢得好笑」的解法

Geoff 对这个工程约束的解法,是他称为 「Ralph Wiggum 当软件工程师」的技术:用一个简单提示词,把智能体丢进 while 死循环里跑:

while :; do
  cat PROMPT.md | npx --yes @sourcegraph/amp
done

想深入了解 ralph 或 PROMPT.md 里写什么,可以读 Geoff 的文章,或看作者与 @simonfarshid@lantos1618@AVGVSTVS96 在上周末 YC Agents 黑客松上做的项目——它(基本上)一夜之间把 BrowserUse 移植成了 TypeScript

Geoff 自己形容 ralph 是个「蠢得好笑」(hilariously dumb)的方案;作者却不太确定它真的蠢

🕵️

子代理(Subagents)= 上下文控制

07

子代理是另一种管理上下文的方式。通用子代理(即非自定义的那种)从早期起就是 Claude Code 和许多编码 CLI 的标配功能。

🧭 关键澄清:子代理不是「过家家」
子代理的意义不是给 AI 分配拟人化的「角色」来玩过家家,而是上下文控制(context control)。

最常见、最直接的用法:让子代理用一个全新的上下文窗口去做查找、搜索、总结类工作,这样父代理拿到干净的结论就能直接开干,自己的上下文窗口不会被一堆 Glob / Grep / Read 调用弄脏。

理想的子代理回复,长得和上一节「理想的临时压缩产出」差不多。但作者提醒:让子代理稳定返回这种高质量结论,并不简单

原文演示视频 · 子代理如何隔离搜索类调用(原始链接)
原文示意图:子代理隔离搜索(静态版)
原文配图 · 视频的静态版(原图)
原文示意图:让子代理返回高质量结论并不容易
原文配图 · 「不容易做对」(原图)
💬 没看懂子代理的价值?点这里换种说法

把父代理想成主刀医生:他不该亲自跑遍全院翻病历柜(那会耗尽他的精力=上下文)。他派助手(子代理)去查,助手翻完 200 份病历后只带回一页纸的摘要。医生的「工作记忆」始终干净,手术台上只放最相关的信息。(这是帮助理解的类比,非原文原话。)

🔁

效果更好的:频繁有意压缩(FIC)

08

作者过去几个月采用并想重点介绍的技术,统称频繁有意压缩(Frequent Intentional Compaction)。本质就一句话:把你的整个工作流围绕上下文管理来设计,并把上下文利用率保持在 40%–60% 区间(具体取决于问题复杂度)。

他们的做法是拆成「三步(左右)」——说「左右」,是因为有时会跳过研究直接进计划,有时又会在动手实现前做多轮压缩过的研究:

🔍 研究(Research)

理解代码库、与问题相关的文件、信息如何流动,可能还有问题的潜在成因。他们的研究提示词目前使用自定义子代理;作者在其他仓库用的是更通用的版本——用 Claude Code 的 Task() 工具配 general-agent,效果几乎一样好。

📋 计划(Plan)

列出解决问题的确切步骤:要改哪些文件、怎么改,并对每个阶段的测试/验证步骤写得极其精确。这是他们的计划提示词

🛠️ 实现(Implement)

按计划逐阶段推进。对复杂工作,作者常在每个实现阶段验证通过后,把当前状态压缩回原计划文件里。这是他们的实现提示词。顺带一提:如果你常听人说 git worktree——只有实现这一步需要在 worktree 里做,其余步骤他们都直接在 main 上进行。

🔍 研究 理解代码库 / 相关文件 信息流动 / 潜在成因 📋 计划 改哪些文件、怎么改 每阶段的测试/验证步骤 🛠️ 实现 逐阶段推进(worktree) 阶段完成→压缩回计划 🧑‍⚖️ 高杠杆人工审查 重点审「研究」和「计划」——比审代码杠杆高得多 ⚙️ 全程约束:上下文利用率保持 40%–60%;每步产出结构化工件,供下一步以新鲜窗口接力
图 3 · FIC 三步工作流:每一步都是「压缩过的工件」交接;人工审查压在研究与计划这两个高杠杆点上

这些 Markdown 文件怎么在团队内管理/共享?作者为篇幅计跳过了这部分,但留了个彩蛋:在 humanlayer/humanlayer 仓库里开个 Claude 会话,问问「thoughts tool」是怎么工作的。

⚔️

实战一:一战 BAML 修 bug

09

作者每周和 @vaibhav 做一期直播编码节目,在白板上推演并写码解决一个高级 AI 工程问题——作者称之为每周的高光时刻。几周前,他决定公开更多幕后过程:看看自家技术能否「一发入魂」地修掉 BAML(30 万行 Rust)里的一个 bug。他从 BoundaryML 仓库挑了一个(诚然偏小的)bug 开工。再强调一次:作者顶多是 Rust 业余选手,且从未接触过 BAML 代码库。(完整过程可看节目回放。)

🔍 研究阶段:第一版直接扔掉

📋 计划阶段:一场对照实验

📄 无研究版计划

也「能用」——修法可行,但修的位置和测试方式与代码库惯例脱节。

📄 带研究版计划

最佳位置修掉了问题,并且开出的测试方案符合该代码库的既有惯例。

两份计划都不长,但差异显著:它们用不同方式修复问题、测试思路也不同。作者的结论:两个「都能工作」,但研究版明显更优。

🛠️ 实现阶段:一夜双 PR

这一切发生在播客录制的前一夜。作者并行跑了两份计划,睡前把两个 PR 都提交了。第二天早上 10 点(太平洋时间)开播时,基于研究的那个 PR 已经被维护者 @aaron 批准——而 @aaron 根本不知道这是为播客做的一次「表演」🙂。另一个 PR 被关掉了

🏁 四大目标·战报(第一战后)
✅ 在棕地代码库工作(30 万行 Rust 项目) | ⬜ 解决复杂问题 | ✅ 没有 slop(PR 被合并) | ⬜ 维持心智对齐
🏔️

实战二:7 小时,3.5 万行

10

Vaibhav 仍然心存怀疑,作者也想验证能否解决更复杂的问题。于是几周后,两人花了 7 个小时(3 小时做研究/计划,4 小时做实现),给 BAML 交付了 3.5 万行代码,添加了「取消支持」和「WASM 支持」两个特性。

3 + 4
小时分配:研究/计划 3 小时
实现 4 小时
2 个特性
cancellation + WASM
每个估值 3–5 个资深工程师日
35,000
行代码,一天之内
取得「难以置信的进展」

✅ 于是第二个目标也打勾了:复杂问题,也能解

🎩

这不是魔法(以及一次结结实实的翻车)

11

还记得例子里「作者读完研究文档发现是错的、直接扔掉重来」那段吗?还有他和 Vaibhav 连续 7 小时深度投入?作者把话挑明:

⚠️ 硬性前提
做这件事时你必须真正投入到任务里,否则它不会奏效。有一类人永远在寻找「一个能解决所有问题的魔法提示词」——那东西不存在

通过研究/计划/实现来做频繁有意压缩,会让智能体表现更好;但让它好到能扛硬仗的,是你在流水线里内建的高杠杆人工审查

🍳 脸上有蛋:parquet-java 翻车记

几周前,作者和 @blakesmith 坐下来花了 7 小时,尝试把 Hadoop 依赖从 parquet-java 里移除——过程中一切出错细节和成因猜想,作者留待另写一篇,总之一句话:这次没搞成

🎯

人类杠杆,与 Code Review 的真正目的

12

如果整篇文章只记住一件事,作者希望是这个:

一行糟糕的代码……就是一行糟糕的代码。
但计划里的一行错误,可能导向数百行糟糕的代码。
而研究里的一行错误——对代码库运作方式或功能位置的误解——可能让你收获数千行糟糕的代码。
—— 所以,把人类的精力和注意力,聚焦到流水线中杠杆最高的环节
研究里的 1 行错误 (对代码库的误解) 计划里的错误 → 数百行坏代码 数千行坏代码 错误被逐级放大 🧑‍⚖️ 人工审查放在「研究 + 计划」上 在错误被放大之前拦住它 = 最高杠杆
图 4 · 错误放大链:越靠上游的错误,放大倍数越大——所以审研究和计划,比审代码杠杆更高

审研究、审计划,比审代码能拿到更高的杠杆。(顺带一提:作者所在的 HumanLayer 的主要方向之一,就是帮团队构建高质量工作流提示词,并为 AI 生成的代码与规格设计出色的协作流程。)

原文示意图:高杠杆人工审查嵌入流水线
原文配图 · 人工审查嵌入流水线(原图)
原文示意图:研究/计划中的错误被放大为大量坏代码
原文配图 · 错误放大(原图)
原文示意图:把人类精力聚焦在最高杠杆环节
原文配图 · 人类精力分配(原图)

🤝 Code Review 到底是为了什么?

人们对 code review 的目的看法不一。作者偏爱 Blake Smith 在《Code Review Essentials for Software Teams》里的定位:code review 最重要的作用是心智对齐(mental alignment)——让团队成员对「代码正在如何变化、为什么变化」保持同步。

原文示意图:code review 的核心是心智对齐
原文配图 · Code review 与心智对齐(原图)

回到那些 2000 行的 Go PR:作者当然关心它们是否正确、设计是否好,但团队内部不安和挫败感的最大来源,是心智对齐的缺失——「我开始搞不清我们的产品是什么、它是怎么工作的了。」作者相信,任何和高产 AI 编码者共事过的人,都体会过这种感觉。

这其实是研究/计划/实现三件套里对他们最重要的部分:所有人产出的代码都暴涨的必然副作用,是任意时刻,代码库中「任何一位工程师不熟悉的部分」的占比都会大幅上升。

📌 作者的诚实告诫
他不会试图说服你「研究/计划/实现」适合大多数团队——它多半不适合。但你绝对需要一套工程流程,能做到:① 让团队成员保持同频;② 让成员能快速了解代码库中自己不熟悉的部分。对多数团队,这套东西是 PR + 内部文档;对他们,现在是规格、计划和研究文档
🏆

总结、展望与邀约

13
🏁 四大目标·终局战报
✅ 在棕地代码库工作 | ✅ 解决复杂问题 | ✅ 没有 slop | ✅ 维持心智对齐 —— 「基本上,我们要的全拿到了。」(哦对,他们三人团队每月在 Opus 上的花费平均约 1.2 万美元。)

为了不让你觉得他只是「又一个打了鸡血的小胡子销售」,作者主动列出不完美之处:

🔮 接下来会发生什么

作者相当确信:编码智能体将被商品化(commoditized)。真正难的,是团队与工作流的转型——在一个 AI 写掉 99% 代码的世界里,关于协作的一切都会改变。他的立场很强硬:这件事你不想清楚,就会被想清楚了的人套圈

🛒 「好吧,你显然有东西要卖我」

(作者原话如此。)他们非常看好规格优先(spec-first)的智能体工作流,正在为此造工具。作者本人痴迷的问题是:如何让「频繁有意压缩」工作流在大型团队中协作化、规模化。当天他们发布了 CodeLayer 私测版——一个「后 IDE 时代的 IDE」,可以理解为「Claude Code 版的 Superhuman」。如果你是 Superhuman 和/或 vim 模式的粉丝,准备超越 vibe coding、认真用智能体做工程,可以去 humanlayer.dev 排队。

🤝 两个公开邀约

🙏 致谢(原文):感谢听过本文早期絮叨版本的朋友与创业者们——Adam、Josh、Andrew 以及许许多多人;感谢 Sundeep 陪伴度过这场疯狂风暴;感谢 Allison、Geoff 和 Gerred 把我们连拖带拽地拉进未来。

📚

关键术语速查

14
上下文工程
Context Engineering。围绕「喂给模型什么信息」做系统性设计,以最大化今天模型的输出质量。
压缩 Compaction
把搜索、日志、代码流理解等吃上下文的原始过程,蒸馏成结构化工件(如 progress.md)。
FIC
频繁有意压缩(Frequent Intentional Compaction):把整个工作流围绕上下文管理设计,利用率保持 40%–60%,配合高杠杆人工审查。
研究/计划/实现
Research / Plan / Implement,FIC 的三步落地工作流,每步产出压缩后的文档工件。
子代理 Subagent
用全新上下文窗口替父代理执行搜索/总结类工作的代理;本质是上下文控制,不是角色扮演。
棕地 / 绿地
Brownfield = 存量成熟代码库;Greenfield = 全新项目。AI 编码工具通常绿地强、棕地弱。
Slop
AI 产出的劣质、需要返工的代码,行业口头禅。
规格驱动开发
Spec-driven development:规格(而非代码)成为团队的真理源;源自 Sean Grove「Specs 是新的代码」。
心智对齐
Mental alignment:团队成员对「代码在如何变化、为何变化」保持同步;Blake Smith 认为这是 code review 的最重要目的。
Ralph Wiggum 技术
Geoff Huntley 的极简方案:用简单提示词让智能体在 while 死循环里持续跑。
BAML
BoundaryML 的开源项目,一门面向 LLM 的编程语言,约 30 万行 Rust,本文两场实战的战场。
CodeLayer
HumanLayer 发布的「后 IDE 时代 IDE」(私测),定位「Claude Code 版 Superhuman」。

🧭 一句话带走

上下文窗口是你影响 AI 输出质量的唯一杠杆;把整个开发流程设计成「频繁有意压缩」——研究、计划、实现,层层交接结构化工件——并把人类的审查压在研究与计划这两个错误放大倍数最高的关口上。AI 编码不是魔法,是一门需要深度投入的工程手艺。