全文在线阅读 · v260421

Harness Engineering

从「和 AI 聊天」到「给 AI 造缰绳」

正文无需登录,目录可以直接跳到对应章节。内容按本版原书呈现,产品信息以书中标注日期为准。

目录 · 19节
  1. 给微信读书读者的话
  2. §01 Harness到底是什么
  3. §02 六十年简史:人和工具的关系
  4. §03 三次命名
  5. §04 Harness的五个组件
  6. §05 少即是多:Harness的减法哲学
  7. §06 OpenAI Codex团队:零行手写代码的百万行产品
  8. §07 Mitchell Hashimoto:每次犯错加一条规则
  9. §08 Anthropic:让AI查AI
  10. §09 Stripe Minions:每周1300个PR的流水线
  11. §10 LangChain:同一匹马,换套缰绳
  12. §11 Kent Beck:极限编程教父的CLAUDE.md
  13. §12 花叔:零代码经验到百万用户
  14. §13 从空白开始:你的第一个Harness
  15. §14 指令层:给AI一张地图
  16. §15 约束层:建议和约束是两回事
  17. §16 能力层与记忆层
  18. §17 编排层:让十匹马同时跑
  19. §18 经验工程:谁来设计下一代的缰绳

给微信读书读者的话

你好,我是花叔。

先解释一下书名。Harness 这个词的本意是马具、缰绳。一匹好马需要一套好缰绳,骑手才能驾驭它。AI 也一样。

过去一年多,我几乎每天都在用 AI 编程工具工作。做产品、写内容、搭工作流,所有事情都有 AI 参与。过程中我发现一个规律:大多数人用 AI 的方式,停留在「聊天」阶段。想到什么问什么,AI 给个回答,觉得不行再追问。这种方式能解决简单问题,但遇到复杂项目就不够用了。

真正让 AI 变得靠谱的,不是更好的提示词,而是一套系统化的协作框架。我把它叫做 Harness——给 AI 设计指令、划定边界、扩展能力、管理记忆、编排流程,把它从一个聊天对象变成真正靠谱的工程伙伴。

这不是我一个人的发明。书里拆解了 7 个真实案例:OpenAI 的 Codex 团队怎么用零行手写代码做出百万行产品、HashiCorp 创始人 Mitchell Hashimoto 怎么用「每次犯错加一条规则」的方式训练 AI、Stripe 怎么让 AI 每周产出 1300 个 PR、极限编程教父 Kent Beck 怎么写他的 CLAUDE.md。这些人和团队的做法各有不同,但底层逻辑是一致的:不要指望 AI 自己变聪明,你得给它造缰绳。

书的后半部分是实操指南。从空白项目开始,一步步搭建指令层、约束层、能力层、记忆层和编排层,最终形成一个完整的 Harness。不需要你是工程师,只要你在用 AI 工具,这些方法都能用上。

坦白说,Harness Engineering 这个概念现在还在早期。它不像软件工程那样有几十年的经验和成熟的教科书。但正因为是早期,现在学习和实践的人会有先发优势。当 AI 的能力越来越强,懂得怎么驾驭它的人,和只会跟它聊天的人,差距只会越来越大。

这本书是「AI编程橙皮书」系列的第三本。系列还有:《Claude Code 从入门到精通》是实战入门手册,《Claude Code 源码解析》拆解 Anthropic 的架构设计,《Agent Skills》教你扩展 AI 的能力。四本书各自独立,但如果你读了这本之后想上手实操,《从入门到精通》是很好的下一步。

最后想说的是,这本书回答的核心问题其实就一个:当 AI 能写代码之后,人的核心能力变成了什么?我的答案是:设计缰绳的能力。希望读完之后,你也能找到自己的答案。

花叔
2026年4月

返回目录 ↑

§01 Harness到底是什么

What Exactly Is a Harness?

又一个XX Engineering?在你翻白眼之前,先看看这个词从哪来、为什么精准。

又来?

Vibe Coding(氛围编程)都没学完,Prompt Engineering(提示词工程)课还在卖,Context Engineering(上下文工程)墨迹还没干。现在又来一个。

过去一年光「XX Engineering」就冒出来四五个,AI圈造新词的速度快赶上模型迭代了。翻白眼是正常的。

但这次情况不太一样。

不是哪个KOL在推特上灵光一闪造的词。OpenAI发了正式博文,Mitchell Hashimoto写了长文,Martin Fowler团队做了分析,LangChain出了技术拆解。几个月内,互不相关的团队指向了同一个东西,用了同一个词。

更像是一群人各自在做类似的事,突然发现彼此,需要一个共同的名字来交流。

先看这个词本身

Harness不是AI圈发明的。这个词在英语里有漫长的历史,至少可以追溯到1300年的古法语「harnois」,可能更早来自古北欧语,意思是「军队的补给品」。最初指盔甲和军事装备,后来才演变成马具的含义。

有意思的是,作为动词「to harness」的比喻义——控制并利用为动力——最早出现在1690年代。三百多年前的人就在用这个词描述驯驭一种力量。

今天这个词在至少五个领域有专业含义,每一个都和 AI agent(智能体)的 harness 有微妙的对应。

五重含义

1. 马具:驯驭野马

最直觉的含义。一套皮带和金属连接件,固定在马的头部或身体上,让马可以被连接到马车、犁或其他工具。

没有harness的马是一匹乱跑的野马。力气再大,方向不对,拉不了车。缰绳不让马变强,但让马的力量变得有用。

这是harness engineering(缰绳工程)最常被引用的隐喻。马是AI模型,强大、快速,但自己不知道该去哪。缰绳是约束和引导系统,骑手是人类工程师。

2. 航天线束:NASA-STD-8739.4A

NASA对航天器电气线束有极其严格的标准。线束的设计和布局直接关系到信号传输的准确性:电缆必须以最小化运动、防止磨损、避免接触锐边或热源的方式布线。压接连接必须用合格工具执行,满足特定的拉力强度要求。过度压接或不足压接都会导致弱连接或开路。

在太空里,一根线松了,整个任务就完了。

航天线束是物理世界的harness engineering:在混乱的物理环境中,用精密的约束和标准确保信号准确传递。AI agent 的 harness 做同样的事:在混乱的语义环境中,确保意图准确执行。

3. 测试线束:软件工程的老概念

Test harness(测试线束)从1950-60年代的早期调试实践演变而来。当时大型机编程依赖临时工具验证代码功能,这一做法类比自电子硬件测试,物理夹具将组件连接起来进行隔离评估。

在软件测试中,test harness 是一组 stub 和 driver 的集合,配置用来辅助应用程序或组件的测试。它创建一个受控环境,让被测对象在其中可预测地运作。

AI agent 的 harness 做的是同样的事。隔离 agent 的行为,提供约束和反馈的执行环境。

4. 安全带:不限制自由,但防止坠落

攀岩、蹦极、建筑施工中使用的安全带。核心功能是:不限制你的行动自由,但在你失足时防止你坠落。

AI agent 的安全护栏(guardrails)正是安全带的数字版本。不限制 agent 的创造力,但在 agent 偏离轨道时阻止灾难。

5. 电气线束:连接一切

汽车里那一大捆颜色各异的线缆,把发动机、仪表盘、灯光、传感器连在一起。线束不产生能量,不做计算,但没有它,一辆车的所有零件就是一堆互不认识的孤岛。

AI agent 的 harness 也是连接层。模型、工具、文档、测试、部署管道,需要有东西把它们连成一个可运转的系统。

词源对照表

领域Harness形态核心功能对应AI Agent中的
马术缰绳 / 马具引导方向和力量约束 + 方向
航天电气线束精密信号传输信息 / 上下文管道
软件测试测试线束隔离 + 模拟环境沙盒 + 反馈循环
安全安全带失败时的保护安全护栏(guardrails)/ 回滚
军事(词源)盔甲 / 装备保护 + 赋能agent 的完整装备

五个领域,五种harness,做的是同一件事:不替代核心力量,而是让核心力量变得可控、可靠、可用。

OpenAI的定义

2026年2月,OpenAI发布了一篇正式博文,给了harness一个清晰的工程定义:

OpenAI原文:A harness is the tool shell that allows an AI agent to affect the real world. If the reasoning model is the brain, the harness is the hands and feet. Reading files, fixing code, running tests, deploying to production: all of it happens inside the harness.

如果模型是大脑,harness就是手和脚。读文件、改代码、跑测试、部署生产,全发生在harness内部。

注意几个细节。

它没说harness是提示词或配置文件,说的是tool shell,一整个壳。不是你告诉AI的那句话,是AI在其中运行的那个环境。

它也没说harness让AI更聪明。大脑还是那个大脑,harness让大脑能动手。

不是发明,是终于认识到

如果你读完五重含义后的反应是「这不就是给老东西起了个新名字吗」,你说对了一半。

航天工程师60年前就在做类似的事。NASA让飞船自动执行任务,围绕自动化系统设计的约束、反馈循环、冗余检查、异常处理,和今天说的 harness 没有本质区别。工业控制领域也一样,PLC编程里的安全联锁机制就是一种 harness。甚至软件测试里的 test harness,概念上和 AI agent 的 harness 完全同构。

AI圈不是发明了 harness engineering,是终于意识到自己需要学几十年前就有的工程纪律。

但命名有命名的价值。

当一群人各自在做类似的事,没有共同的词来说,经验就传不开。你在写 CLAUDE.md,他在写 AGENTS.md,她在配 hooks 和 CI 流水线,做的是同一类工作,但没法高效交流。词出来之后,突然大家都能聊到一起了。

就像 vibe coding。你可以笑它,但它确实让一种做法变成了可以讨论的东西。

Harness Engineering 也一样。价值不在于发明了什么,在于让一群人意识到:自己工作的重心变了。

从写代码变成设计环境,从当执行者变成当架构师,从自己干活变成让 AI 在你设计的系统里干活。

这个转变已经发生了。只是现在它有了名字。

下面三章(§02-§04)我们分别从时间、命名演化、结构三个维度展开。

返回目录 ↑

§02 六十年简史:人和工具的关系

A Sixty-Year History: Humans and Their Tools

从打孔卡到CLAUDE.md,六十年间人和编程工具的关系翻了好几次。每次翻转都有人说「程序员要完了」,但每次真正变的是程序员在做什么。

1968:软件危机,一切的起点

1968年德国加尔米施,NATO软件工程会议。与会者震惊地发现,完全不同类型的项目都在遭受相同的困境:长期延期、严重超预算、交付的软件充满缺陷。共识只有一个:一场「软件危机」正在肆虐。

Dijkstra本人后来写道:「1968年我遭受了一场深度抑郁。」被软件危机的严重性震撼之后,他提出了那个著名论点:goto语句会降低程序质量,应该用结构化构造来替代。

这个时代人和工具的关系极其简单:人是唯一的创造者,工具极度原始。打孔卡、命令行、编译器。写代码就是一切。工具只负责把你写的东西翻译成机器能执行的指令。

1970:瀑布模型——一场持续五十年的误读

1970年,Winston Royce发表了那篇影响深远的论文《Managing the Development of Large Software Systems》。

这里有个软件工程史上最讽刺的事实:Royce在论文中从未使用过「waterfall」这个词,也从未主张它是一种有效的方法论。他展示了单次顺序通过的方法是「有风险的且招致失败的」,建议项目至少迭代两次。

但后来的读者只记住了那张顺序流程图,警告被自动忽略了。

软件工程史上最具影响力的方法论,源于对一篇论文的误读。挺荒诞的。

1994:设计模式——人脑的模式匹配

GoF(Gang of Four)出版了《Design Patterns》,定义了23个经典的软件设计模式。这本书卖了超过50万册英文版,被翻译成13种语言。

设计模式的意义不只是23个解决方案。它第一次把代码的形状变成了一种可以讨论的东西。人不仅要写代码,还开始系统性地思考代码该长什么样。

工具还是那些工具,但人对「怎么用工具」这件事的理解深了一层。

2001:敏捷宣言——从写代码到设计流程

17位开发者聚在一起,发布了《敏捷软件开发宣言》。四个核心价值观里,排第一的是:

个体和互动 高于 流程和工具。

敏捷之前,整个行业在讨论流程:需求分析要多久,设计评审怎么做,文档格式是什么。敏捷把焦点拉回人身上。

差不多同时期,Kent Beck推广了测试驱动开发(TDD)和持续集成(CI)。这两个实践改变了一个根本的东西:人开始系统化地和自动化工具协作。自动化测试成了第二双眼睛,人从独自写代码变成了写代码加设计验证机制。

验证机制这个概念,记住它。后面还会反复出现。

2009-2014:DevOps——描述你要什么,而不是怎么做

2009年第一次DevOps Days在比利时根特举行。2013年Docker开源。2014年Google开源了Kubernetes。

Docker 1.0在2014年发布时,软件下载量已达275万次;一年后突破1亿次。Google最初开发Kubernetes是因为需要一种每周运行数十亿个容器的方式。

但真正的转折不是Docker或K8s本身,是Terraform(对,Mitchell Hashimoto做的)、Ansible、Helm这些工具带来的理念转变:基础设施即代码。

人开始描述期望状态,而不是手动执行步骤。你不再一步步告诉服务器该装什么、怎么配,而是写一个声明式文件说「我要3个实例,每个2GB内存,跑这个镜像」,工具自己去实现。

这预示了后来AI编程的根本模式:描述意图,让系统去执行。

2021:Copilot——AI第一次坐到程序员旁边

2021年6月29日,GitHub发布了Copilot技术预览版,基于OpenAI Codex模型。注意时间点:此时OpenAI还没发布ChatGPT。

Copilot的交互方式很简单:你写一行代码,AI猜下一行。写个注释说「排序这个数组」,AI帮你补完函数体。

人仍然是方向盘,AI只是油门助力。你不能把手松开。但确实,踩油门轻松了很多。

2022年Copilot正式商用,成为第一个商业化的AI编程助手。同年11月ChatGPT发布,把整条赛道炸开了。

2024:Agent时代——从辅助到自主

2024年3月,Cognition Labs发布Devin,自称「第一个完全自主的 AI 软件工程师」。在SWE-Bench上,Devin无辅助正确解决了13.86%的问题,远超此前最佳的1.96%。

数字不大,意义很大。这是 AI 第一次尝试从头到尾独立完成编程任务:规划、编写、测试、提交 PR,不需要人一行行指导。

同年Cursor崛起。四个MIT毕业生做了一个不是IDE插件而是IDE本身的东西,16个月吸引超过100万用户,ARR突破1亿美元,据报道没花一分钱营销费。

2025:Claude Code和Vibe Coding

2025年2月,两件事几乎同时发生。

Anthropic发布Claude Code,一个终端原生的 AI agent。它不是在你IDE里弹补全建议,而是直接进你的代码库:读文件、改代码、跑测试、提交、和外部工具交互。不到两个月日活跃用户突破35万,年底年化收入突破10亿美元。

同月,Andrej Karpathy创造了 vibe coding 这个词:完全沉浸在感觉中,拥抱指数增长,忘记代码的存在。「把侧边栏的padding减半」,接受所有更改不看diff,把错误信息复制回 AI,不加任何评论。

代码成了AI的事,人只负责「这感觉对不对」。

到2025年底,AI编程工具的能力发生了质变。使用最新大模型的编程智能体(coding agent)在SWE-Bench上常规完成超过80%的任务。大约85%的开发者定期使用AI工具编程。

2026:Harness Engineering——写代码不再是最重要的技能

2026年2月,OpenAI公布了一组震撼数据——零行手写代码,百万行产品出炉(详见§06)。

这是拐点。不是因为数字本身(100万行里有多少是高质量的,还得打个问号),而是它代表了一种新的工作方式:工程师的主要工作不再是写代码,而是设计环境、明确意图、构建反馈循环。

OpenAI把这种工作方式叫做 Harness Engineering(缰绳工程)。

六十年对照表

时代人做什么工具做什么核心技能
1960s-1990s
手工编码
写每一行代码编译、运行编程语言精通
2001-2010
敏捷
写代码 + 设计流程自动化测试、CI编程 + 协作 + 测试设计
2010-2020
DevOps
描述期望状态自动部署、监控系统思维 + 基础设施设计
2021-2023
AI辅助
写代码 + 验收 AI 补全补全、建议编程 + 提示词能力
2024-2025
AI Agent
描述意图 + 审查结果自主编写 + 测试 + 迭代上下文设计 + 审查能力
2026-
Harness时代
设计环境 + 定义约束在环境中自主运作系统架构 + harness 设计

一条暗线

如果你纵向看这张表,会发现一条暗线。

1960年代,人亲手触碰每一行代码。2001年,人开始把一部分验证工作交给自动化。2014年,人开始用声明式语言描述期望状态。2021年,AI 开始帮写代码。2025年,AI 开始独立写代码。2026年,人的主要工作变成了设计 AI 工作的环境。

每一步,人都在从「执行」向「设计」后退一层。

不是被动后退。是人意识到,时间花在更高层的设计上,总体产出更高。Kent Beck发明TDD不是因为不会写代码,是因为发现先写测试再写实现,代码质量更好。Mitchell Hashimoto做Terraform不是因为不会手动配服务器,是因为发现声明式描述让基础设施更可靠。

Harness Engineering 是这条暗线的最新一环。不是程序员被淘汰了,是程序员的工作重心又移了一格。

写代码
→
设计测试
→
描述状态
→
设计环境

从亲手做,到设计怎么做,到描述要什么,到设计让别人(AI)在里面做的那个系统。

六十年,人和工具的关系翻了四次。每次翻转之后,「程序员」这个词的含义都不太一样了。

返回目录 ↑

§03 三次命名

Three Namings

从Prompt到Context到Harness,不是三个独立概念,是同一件事的三次觉醒。每次命名都让一群人意识到自己工作的重心变了。

第一次命名:Prompt Engineering

2022到2024年,所有人都在学怎么写提示词(prompt)。

很自然的事。ChatGPT出来了,Copilot出来了,你能用自然语言让 AI 干活了。问题来了:怎么问才能问到好答案?

于是有了 Prompt Engineering(提示词工程)。一门怎么跟 AI 说话的技术。角色设定、few-shot(少样本)示例、chain-of-thought(思维链)引导,精心选择每个词,因为词的差异直接影响输出质量。

用马具的比喻来说:Prompt Engineering 是你对马说的话。向左转。跑快点。别踩花。

管用。但有个根本局限:一次性的、无上下文的、不可复用的。写了一条好提示词,换个场景就得重写。你没法把一条提示词变成一个系统。

简单任务上够了。但当你需要AI处理真实世界的复杂项目时,一条指令什么都撑不起来。

第二次命名:Context Engineering

2025年6月,两个人几乎同时给了这件事一个名字。

6月18日,Shopify CEO Tobi Lutke发了条推:

Tobi Lutke:Context engineering 是为任务提供所有上下文、使其对 LLM 来说合理可解的艺术。

一周后,Andrej Karpathy背书放大了这个概念:

Karpathy:在每一个工业级 LLM 应用中,context engineering 是精妙的艺术和科学——用恰到好处的信息填充上下文窗口以完成下一步。

Karpathy特别指出了一个关键区别:人们把提示词联想为短指令,但在严肃的 LLM 应用中,真正的工作是动态构建上下文窗口,填入相关文档、对话历史、工具定义和 RAG(检索增强生成)结果。

Context Engineering(上下文工程)是帮马看路的一切。地图、路标、地形信息。你不只是告诉马往哪走,你给它看整片地形,让它自己判断路线。

从写一条指令变成设计一个信息包。质的变化。

Prompt 是你说的那句话,Context 是你把什么东西摆在 AI 面前。区别就像给司机一个地址,和给司机一张标注了路况、施工区域、加油站的完整地图。

但 Context Engineering 也有它的边界。它解决了「给 AI 看什么」,没解决「AI 在什么环境里运行」。你可以给 AI 完美的上下文,但如果没有工具去执行、没有约束去遵守、没有反馈循环来自我修正,上下文再好也只是一堆漂亮的参考资料。

第三次命名:Harness Engineering

2026年2月5日,Mitchell Hashimoto发了一篇博文「My AI Adoption Journey」。

HashiCorp联合创始人,Terraform的创造者,目前全职开发Ghostty终端模拟器。不持有任何AI公司的股权,观点中立性比大多数AI圈的人高。

博文开头有一句声明:

Mitchell:This blog post was fully written by hand, in my own words. I hate that I have to say that but especially given the subject matter, I want to be explicit about it.

在一篇讨论AI的文章里声明自己手写的。2026年的行业氛围。

他描述了从 AI 怀疑论者到 agent 重度用户的六步旅程,在第五步引入了一个新概念——一句话概括就是:agent 犯错才加规则,让它再也犯不了同样的错(§07完整展开)。

他拿自己的终端模拟器 Ghostty 举例。文件是活的,一直在长,每一行都对应 agent 过去犯过的一次错。

六天后,2月11日,OpenAI发了正式博文用了同一个词。Martin Fowler团队跟进分析。LangChain出了技术拆解。一个月内,Harness Engineering 从一个人的博客术语变成了行业共识。

Harness Engineering(缰绳工程)是缰绳、马鞍、围栏和道路本身。不只是你对马说什么(Prompt),不只是你让马看到什么(Context),而是你给马套上的那整套装备,加上你围出来的跑道,加上跑道上的护栏和检查站。

让十匹马同时安全跑起来的系统。

三层包含关系

三者不是三个平行的概念,是包含关系。

Prompt
你说的话
⊂
Context
你给的信息
⊂
Harness
整个运行环境

Prompt 管你问什么。Context 管你给模型看什么。Harness 管整个东西怎么运转。

Context 是 harness 的一部分。harness 还多管了约束、反馈和质量检查。你的 CLAUDE.md 是 Context,你的 hooks 是 harness 的约束层,你的 CI 测试是 harness 的反馈层。三者加在一起才是完整的 harness。

维度Prompt EngineeringContext EngineeringHarness Engineering
时期2022-202420252026
核心问题怎么问给什么信息整个系统怎么运转
马具比喻你对马说的话帮马看路的一切缰绳 + 马鞍 + 围栏 + 道路
人的角色提问者策展人架构师
可复用性低(每次重写)中(模板化)高(系统化)
命名者社区自发Karpathy / Tobi LutkeMitchell Hashimoto / OpenAI

命名的真正价值

你可能会想:有没有这些名字,活不是照样干?

确实。我自己去年8月搭了 Claude Code 自动化写作工作流。CLAUDE.md 从一个简单的规则文件变成了路由器,hooks 在关键操作前后注入检查,skills 解决了模块化。路由器、hooks、skills、知识库,加在一起就是一个 harness。没人告诉我这叫什么,它自己长出来的。

Mitchell Hashimoto也一样。给 Ghostty 写规则文件、编辑辅助脚本、搭验证机制,做了几个月才意识到这是一类工作。然后他自己给它取了名字。

名字出来之后,事情变了。

LangChain可以写一篇「The Anatomy of an Agent Harness」,系统地拆解 harness 的组件。Martin Fowler团队可以提出三支柱框架(上下文工程、架构约束、熵管理)来分析OpenAI的实践。一个概念有了名字,就可以被讨论、被拆解、被教。

LangChain给了一个公式:Agent = Model + Harness。一个裸模型在被 harness 赋予状态、工具执行、反馈循环和可执行约束后,才成为 agent。模型是引擎,harness 是车身、方向盘、刹车和仪表盘。引擎一样的两辆车,harness 不同,开起来天差地别。

他们自己的数据证明了这一点:模型没换,只改 harness,成绩从Top 30跳到Top 5(详见§10)。

同一个引擎,换了套车身,成绩天差地别。

三次觉醒

回头看,三次命名是同一群人的三次觉醒。

第一次:原来怎么问 AI 很重要。Prompt Engineering。

第二次:不只是怎么问,给什么信息更重要。Context Engineering。

第三次:不只是信息,AI 在什么环境里运行、有什么约束、怎么获得反馈、犯错了怎么纠正,这整套东西才是关键。Harness Engineering。

每次都不是推翻前一个,是把前一个包含进来,再往外扩一层。

这也解释了为什么这次感觉不一样。Prompt Engineering 出来时,很多人觉得它是临时技能,模型变强了就不需要了。Context Engineering 出来时,有人觉得不过是更复杂的提示词的花哨名字。

但 Harness Engineering 指向的不是一个技巧,是一种新的工程实践。和 DevOps 从实践中浮现出来一样,和敏捷从实践中浮现出来一样。先是一群人各自在做,然后有人给了名字,然后形成可传播的方法论。

2009年第一次DevOps Days的时候,也没人知道这个词十年后会变成每个技术团队的标配。

Harness Engineering 现在就在那个阶段。名字刚出来几个月,定义还在成型中,最佳实践还在被各个团队独立发现和验证。

还有人在命名

故事没有停在三次。

Andrej Karpathy在2025年底做了一个决定:不再手写代码。完全依赖 AI agent 编程。他用自己的AutoResearch项目验证了这个决定——630行训练代码加一个 markdown 提示词(markdown prompt),2天跑了700次实验,发现了20个优化项。整个研究流程的 harness 就是一个 markdown 文件。

然后他给这件事也取了个名字:Agentic Engineering(智能体工程)。

又一个命名。这次强调的是 agent 的自主性——不是你在指挥 AI,而是你在设计一个能自主运行的系统。

Context Engineering 这边也没闲着。一篇经过同行评审的论文跑了9,649次实验,结论明确:系统化地管理上下文,比精心打磨一条提示词管用得多。两年前还是推特上的概念,现在有硬数据了。

命名还在继续,每一次都在扩大视野。但核心洞察没变:瓶颈不在模型,在模型运行的环境。叫 Harness 也好,叫 Agentic 也好,指向的是同一件事。

方向已经清楚了。接下来几章,我们看看这个方向具体长什么样。

返回目录 ↑

§04 Harness的五个组件

Five Components of a Harness

缰绳不是一根绳子,而是五根。它们各司其职,缺一不可。这一节拆解harness的完整结构,并对比不同团队的切法。

前面说了 harness 是什么、为什么重要。但如果你现在就去搭,会发现一个问题:从哪里下手?

沿用前面的马术比喻,harness 的五个组件就像缰绳、马鞍、围栏、道路和马队编排——各司其职,缺一不可。

不同团队给出了不同的答案。OpenAI用四个动词概括,Martin Fowler拆成三块,Anthropic走了多智能体(multi-agent)路线。看起来各说各话,但仔细对比,他们在描述同一头大象的不同部位。

我把这些框架揉在一起,提炼出五个组件。不是说五个比三个或四个更正确,是这个颗粒度最适合实操。

组件一:指令

指令是 harness 最基础的一层。你告诉 AI:我是谁、项目长什么样、有哪些规则必须遵守。

在不同工具里名字不同:Claude Code 叫 CLAUDE.md,Codex CLI 叫 AGENTS.md,Cursor 叫 .cursorrules,Windsurf 叫 .windsurfrules。本质一样:用 Markdown 文件把你的意图编码成 AI 可读的规则。

Boris Cherny的100行CLAUDE.md哲学(§08详述)是一条判断标准:每一行都问自己「删掉它会导致 Claude 犯错吗?如果不会,就删掉」。

如§06所述,OpenAI Codex 团队的 AGENTS.md 是「给地图不给说明书」的典型——约100行,只展示项目结构、文件关系和关键约束,用指针指向更深层的文档。

Mitchell Hashimoto走的是另一种路径——如§07所述,他的核心方法论是「agent 犯错才加规则」,让指令文件在交互中自然生长。

三种做法看起来不同,逻辑是共通的:指令不是写一次就完的文档,而是持续演化的工程制品。Boris叫它复利工程。

组件二:约束

指令是建议,约束是法律。区别在于:指令说「请注意代码规范」,约束是代码不合规就编译不过。

OpenAI把这层概括为两个动词:约束(constrain)和纠正(correct)。约束是事前拦截,纠正是事后修复。

具体实现上,最硬的约束是自定义linter和结构测试。OpenAI Codex 团队在 CI 中配了自定义 ESLint 规则,坏模式在静态层面就不可能出现。有意思的是,这些 linter 本身也是 Codex 写的。AI 写规则约束 AI,有点递归的味道。

Claude Code有个独特的机制:Hooks。在 agent 的关键生命周期节点注入脚本。PreToolUse 钩子可以在工具调用前拦截操作,返回 deny(拒绝)信号直接阻止执行。编辑文件之前跑 linting,push 代码之前检查分支,不是提示词层面的建议,是程序层面的硬拦截。

Codex CLI 走的是沙箱路线。默认模式下,agent 只能写工作区内的文件,网络访问关闭。.git/ 和 .codex/ 始终受保护,即使开启全权限模式也动不了。

约束的反直觉之处:缩小解空间反而提升 agent 的产出。Birgitta Boeckeler(Thoughtworks的首席工程师 Distinguished Engineer)在分析 OpenAI 案例时指出:「Increasing AI autonomy requires decreasing solution space flexibility.」——提升 AI 自主性,需要缩小解空间的自由度。

Martin Fowler把约束归入他的第二块「架构约束」。OpenAI 的依赖层架构(详见§06)是个好例子:在 agent 编码的时代,它变成了早期前提条件。

组件三:反馈

AI 最大的问题不是写错代码,是以为自己写对了。

LangChain在Terminal Bench 2.0的测试中发现,最常见的失败模式是:agent 写完方案后重新读自己的代码,觉得看起来没问题就停了。没运行测试,没验证边界情况。

模型对自己的第一个可行方案有天然偏好。它不是不会做得更好,是太容易满足于「看起来可以」。

Anthropic用规划者(Planner)/生成者(Generator)/评估者(Evaluator)三智能体(3-Agent)架构回应这个问题,详见§08。核心洞察只有一句:谁都不擅长批评自己的作品,AI 也一样。工程化一个严厉的独立评估者,远比教一个生成者自我批判容易得多。

Boris Cherny的第一条建议也是同一个意思:给 Claude 验证手段,能让最终结果质量提升2-3倍。Web代码可以用Chrome扩展测试UI,CLI命令可以跑测试套件,基础设施可以接模拟器和浏览器测试。

OpenAI用了另一个动词:验证(verify)。他们给 agent 装了「眼睛」——集成Chrome DevTools Protocol做DOM快照和截图,接入可观测性数据让 agent 直接查询日志和指标。「启动时间低于800ms」从文档里的愿望变成了可执行的指令。这套反馈循环让单次任务运行可以持续6小时以上。

Martin Fowler把反馈归入他的第三块「垃圾回收」:专门有个 agent 周期性运行,不写代码不做功能,就干一件事——找文档里的矛盾和架构违规。一个专职找茬的 AI。

Boeckeler还指出了OpenAI文章的一个盲区:他们的 harness 约束了代码怎么写、怎么组织,但没有验证代码是否真的做了用户需要的事。只关注了内部质量,忽略了功能正确性。这和LangChain发现的「agent 不验证」问题本质一样。

组件四:记忆

Agent 没有记忆就是金鱼。每次对话重新开始,同样的错犯两遍三遍。

记忆分几层。最基础的是静态记忆:CLAUDE.md、AGENTS.md 这些指令文件本身就是记忆的载体。Boris Cherny团队在PR中用 @.claude 标签来更新 CLAUDE.md,每一条新增规则都是 agent 过去犯过的错的制度化记录。

再上一层是动态记忆。Claude Code 有 auto-memory(自动记忆)功能,AI 自动把有用的观察保存下来,跨会话持久化。Windsurf有Cascade Memories,工作过程中自动识别并保存重要信息。Cline通过MCP实现了Memory Bank。

最精妙的是结构化笔记。Anthropic发现 agent 在上下文窗口外维护持久笔记是非常有效的压缩手段——Claude玩Pokemon维护步骤计数笔记是标志案例(详见§16)。

OpenAI把记忆纳入他们的第二个动词:告知(inform)。Agent 看不到的东西等于不存在。他们把Google Docs里的规划文档迁入代码仓库,Slack里的决策转为 markdown 存入 repo,创建叫 ExecPlan(执行计划)的自包含设计文档。仓库必须是唯一的真相来源。

但记忆不是越多越好。Anthropic的上下文工程文章给了一个精准定义:

找到最小的高信号 token 集合,最大化期望结果的可能性。

上下文是稀缺资源。塞太多进去,反而挤占干活的空间。这一点在下一节会展开讲。

组件五:编排

前四个组件是单个 agent 的 harness。当任务足够复杂,需要多个 agent 协作时,编排就成了第五个组件。

Anthropic的三智能体架构是编排的典范(详见§08和§17):Planner 扩展规格、Generator 实现、Evaluator 跑端到端测试。冲刺合约(Sprint Contract)机制让双方对「完成」的定义先对齐再开工。

Claude Code支持两种编排模式:子智能体(Subagents)运行在独立的上下文窗口中,处理探索性任务后只向主 agent 返回精简摘要;智能体团队(Agent Teams)是实验性功能,多个独立实例各有自己的上下文窗口,一个会话(session)担任团队负责人(team lead)分配任务,团队成员(teammates)之间可以直接通信。

LangChain的中间件(middleware)提供6个 hook 点(详见§10),让不同团队可以各自管理自己关心的关注点,业务逻辑和核心 agent 代码解耦。

Boris Cherny的个人编排更朴素但同样有效:拿人当编排器,一个人同时带十几个Claude Code会话跑(详见§17)。没高级架构,但他说这是团队最大的生产力解锁。

两个框架的对比:不同的切法,同一块蛋糕

现在把五个组件和其他团队的框架对齐。你会发现大家在说同一件事,只是切法不同。

五组件模型OpenAI四动词Fowler三块典型实现
指令告知(inform)上下文工程CLAUDE.md / AGENTS.md / .cursorrules
约束约束(constrain)架构约束Hooks / Linter / Sandbox / CI
反馈验证(verify)垃圾回收Evaluator Agent / 测试 / 可观测性
记忆告知(inform)上下文工程知识库 / auto-memory / ExecPlan
编排纠正(correct)—(未覆盖)多智能体 / 流水线(Pipeline)/ 中间件(Middleware)

几个对应关系值得展开说。

OpenAI的「告知」同时覆盖了指令和记忆。在他们的框架里,这两者没有区分,agent 看不到的东西等于不存在,不管它是规则还是知识。但实操中,CLAUDE.md 和知识库(knowledge base)的管理逻辑完全不同,拆开更好用。

Fowler的「垃圾回收」在五组件里对应反馈,但含义更窄。Fowler关注代码库层面的熵增,文档过时、架构违规累积。Anthropic的 Evaluator 关注功能层面的正确性。都是反馈,层次不同。

编排是OpenAI和Fowler都没有显式覆盖的维度。OpenAI的「纠正」勉强沾边,但纠正更多指错误修复而非多智能体协调。Fowler的框架完全基于单 agent 分析。这也反映了一个事实:多智能体编排到2026年初仍然是实验阶段,主流框架还没完全吸收。

五组件的关系

这五个组件不是平行的,它们有层次。

指令
告诉 AI 做什么
→
约束
拦住 AI 做错事
→
反馈
检查 AI 做对没
→
记忆
让 AI 不重复犯错
→
编排
让多个 AI 协作

指令和约束是输入端:在 agent 行动之前就位。反馈是过程中:agent 执行时的质量检查。记忆是跨时间:让经验在会话之间持久化。编排是跨空间:让多个 agent 在同一时间协同工作。

实际搭建时不需要五个同时上。一开始只要指令(写一个 CLAUDE.md)和基本的反馈(让 AI 跑测试)。约束在你被 agent 搞烦了之后自然会加。记忆在你受够了每次重复解释规则之后自然会建。编排是最后才需要的,除非你的任务确实复杂到一个 agent 搞不定。

Harness 是长出来的,不是设计出来的。如§07所述,每次 agent 犯错就加一条规则,三个月后那个文件就是你的 harness。

返回目录 ↑

§05 少即是多:Harness的减法哲学

Less Is More: The Counterintuitive Art of Subtraction

Harness不是越大越好。这可能是整本书最反直觉的一节。

读完上一节,一个自然的反应是:既然 harness 有五个组件,那我每个都做到极致,效果不就最好吗?

不是。

恰好相反。多个独立团队在不同场景下发现了同一件事:过度工程化的 harness 比没有 harness 更糟糕。不是哲学观点,有数据。

上下文焦虑:模型也会慌

Anthropic在开发长运行agent时发现了一个此前没人注意的现象。Claude Sonnet 4.5是他们观察到的第一个「意识到自身上下文窗口」的模型。听起来像好事?不是。

这种自我意识带来了副作用:模型会在它认为接近上下文极限时,过早地开始收尾工作。Anthropic把这叫上下文焦虑(context anxiety)。

模型对剩余token的估计「非常精确但错误」。它开始主动总结进度,更果断地实施修复。表面上看效率提高了,实际上是在赶工。

Anthropic发现的「上下文焦虑」(§08详述)促使他们做减法——这个问题严重到仅靠压缩不够,最后只能用结构化的上下文重置机制兜底。好在到Opus 4.6这个行为自行消失了。

这个发现的意义超出单一模型。它揭示了一个更普遍的规律:上下文不是免费资源,它有副作用。塞进去的信息越多,模型准确回忆任何单条信息的能力越差。Anthropic的工程文章明确指出,模型在约100万 token 处遇到明显的性能天花板,超过这个点性能显著下降,不管技术上支持多大的上下文窗口。

Claude Code官方最佳实践文档开头就说了:

大多数最佳实践都基于一个约束:Claude 的上下文窗口填充很快,填满后性能下降。

他们列了几个应该避免的反模式:凑合会话(Kitchen Sink Session,一个会话混合不相关任务)、反复修正(上下文被失败方案污染)、过度指定的 CLAUDE.md(太长导致规则被忽略)、无边界探索(不限范围的调查填满上下文)。每一条指向同一个结论:少即是多。

给地图,不要给说明书

如§06所述,OpenAI把「给地图不给说明书」列为第五条 Harness Engineering 原则——AGENTS.md 约100行,只当地图用,指向更深层文档。全面的指令文件会挤占任务上下文和相关代码的空间。

这和人类团队管理有相通之处。手册写到300页,没人看。但一张A4纸的行动清单,人人记得住。

正确做法是分层:一个薄入口文件当地图,指向更深层的专业文档。需要API设计规范?指个路。需要测试策略?指个路。别把所有东西平铺在一个文件里。

推理三明治:全程拉满反而更差

LangChain的推理三明治(reasoning sandwich)实验(§10详述)证明了同一件事:资源分配比资源总量更重要。开头用最高推理做规划,中间实现阶段降到中等节省时间,最后验证再拉回最高。全程拉满反而因为超时得分最低。

这条结论在上下文管理、推理预算、甚至团队时间分配上都成立。

什么时候该加规则,什么时候该砍

理解了「少即是多」之后,实操中最难的问题来了:那个「少」的边界在哪?

如§07所述,Mitchell Hashimoto的方法是纯归纳法:只在 agent 犯错时加规则,每条规则都对应一个真实问题,没有「以防万一」的冗余。

但规则会累积。三个月后文件可能膨胀到不好用。这时候就需要做减法了。

几个信号提示你该砍规则了:

模型升级后的旧规则。Anthropic的经验很说明问题。Sonnet 4.5时代需要冲刺(Sprint)分解和每 Sprint 评估,换了 Opus 4.6 之后 Sprint 机制完全移除,模型原生就能处理长任务。为旧模型的弱点写的规则,在新模型上可能变成噪音。

AI 通过阅读代码就能发现的东西。Claude Code 文档明确说,不要在 CLAUDE.md 里写标准语言惯例、详细的 API 文档、教程和长解释、以及「写干净代码」之类不言自明的实践。AI 能自己搞清楚的,你告诉它反而是浪费上下文。

2026年3月,ETH Zurich的一篇论文给了这条经验更硬的实证。他们系统测试了 AGENTS.md 对 AI agent 表现的影响,结论出人意料:在某些场景下,AGENTS.md 不仅没帮忙,反而妨碍了 agent 的表现。

研究者的建议很具体:只写人类不可推断的信息。特殊的工具链、自定义构建命令、非标准的项目约定——这些 AI 看代码看不出来的东西才值得写进去。项目用了 React?它打开 package.json 就知道了。用了 TypeScript?它看文件后缀就知道了。这些写进去不但多余,还稀释了真正重要的规则。

这和Boris的100行哲学、OpenAI的100行地图、Mitchell的犯错驱动,殊途同归:每一条规则都应该通过「AI 自己能发现吗?」这个过滤器。

频繁变化的信息。指令文件应该只放很少变化的东西。版本号、当前 Sprint 的任务、今天的会议记录,这些不该出现在 CLAUDE.md 里。

互相矛盾的规则。时间一长,先后添加的规则可能互相打架。agent 遇到矛盾指令时的行为不可预测,有时选更近的那条,有时选更长的那条,有时干脆两条都忽略。定期做一轮垃圾回收:删过时的、合并重复的、解决冲突的。

减法清单

把上面的信号总结成一个可操作的清单:

应该保留的规则
- agent 反复犯的错(经过验证的真实问题)
- 项目特有的架构决策和约定
- 与默认行为不同的规则
- 关键的安全和质量红线
- 指向深层文档的指针
应该砍掉的规则
- 为旧模型弱点写的补丁
- AI 看代码就能发现的惯例
- 「以防万一」的预防性规则(没被触发过)
- 频繁变化的具体信息
- 教程性质的长解释

Anthropic 的 Evaluator 也遵循减法

减法不只适用于指令文件,也适用于 harness 架构本身。

Anthropic在模型从 Sonnet 4.5 升级到 Opus 4.6 的过程中,做了一系列减法:Sprint 机制移除了,上下文重置移除了,Evaluator 从每 Sprint 评估变为全程结束后一次性评估。

他们总结出一个原则:

Evaluator 不是一个固定的有/无决策。它在任务超出当前模型可靠独立完成的范围时才值得投入成本。Harness 设计应该随模型能力动态调整。

harness 不是一劳永逸的。模型变强了,harness 应该变薄。你今天需要的脚手架,明天可能变成多余的重量。

回到§03那个公式——Model 变强,Harness 需要的就更少。但更少不等于没有。即使是最强的模型,仍然需要指令、约束和反馈,只是规模和复杂度可以降低。

这大概是 harness engineering 最需要判断力的地方。加规则容易,砍规则难。因为砍掉一条规则后如果出了问题,你会后悔;但保留一条没用的规则,你感知不到它的成本。而那个成本是真实的——每一条多余的规则都在稀释真正重要的规则的权重。

好的 harness 不是规则最多的那个,是每条规则都在干活的那个。

返回目录 ↑

§06 OpenAI Codex团队:零行手写代码的百万行产品

OpenAI Codex Team: One Million Lines, Zero Handwritten

3个工程师,5个月,100万行代码,零行手写。这组数据够炸,但数据背后的方法论更值得拆。

数据先摆桌上

2026年2月13日,OpenAI发了一篇博文「Harness engineering: leveraging Codex in an agent-first world」。作者Ryan Lopopolo,Codex团队的技术人员(Technical Staff Member)。博文不长,数据密度极高。

指标 数据
实验时长 5个月
初始团队 3名工程师
后期团队 7名工程师
代码规模 ~100万行(应用逻辑+基础设施+工具+文档+内部开发工具)
合并PR数 ~1,500个
人均日PR 3.5个
人工手写代码 0行

其中最反直觉的一个数据是:从3人扩到7人后,人均吞吐量反而增加了。

学过软件工程的人都知道Brooks定律:加人会导致沟通成本指数级增长,项目反而变慢。传统开发里几乎是铁律。但Codex团队打破了它。初期每人产出大约相当于0.25个传统工程师,后期飙升到3-10倍。

原因是他们不在写代码,在设计让 AI 写代码的环境。加人不增加代码协调成本,只增加 harness 的完善度。Harness 越完善,每个人能同时驾驭的 agent 就越多。

关键转变:工程师的日常从「写代码」变成了「设计环境、描述意图、构建反馈循环」。Ryan Lopopolo的原话是:当团队的首要工作不再是写代码,而是让 Codex agent 可靠地工作时,一切都变了。

五条原则,逐条拆

博文核心是Codex团队总结的五条 harness engineering 原则。每条看起来简单,背后有具体做法支撑。

原则一:agent 看不到的等于不存在

原文说得很直白:

"From the agent's point of view, anything it can't access in-context while running effectively doesn't exist."

(从agent的视角看,运行时无法在上下文中访问的一切,实际上就不存在。)

看似废话,但它逼出了一个彻底的行动:团队把 Google Docs 里的规划文档、Slack 里的决策记录,全部迁入了代码仓库。原因很简单,agent 只能看到仓库里的东西。你写在 Notion 里的产品需求再详细,agent 一个字都看不到。

他们为此创建了一种叫 ExecPlans(执行计划)的文档格式,写到初级工程师也能端到端实现功能的程度。不是给人看的笔记,是给 agent 执行的指令。

原则二:问缺什么能力,而非为什么失败

agent 搞砸了,正常反应是骂模型笨。Codex团队的反应不一样:

"When the agent struggles, we treat it as a signal: identify what is missing — tools, guardrails, documentation."

(当 agent 卡住时,我们将其视为信号:识别缺了什么——工具、护栏,还是文档。)

不责怪模型,不调参数,检查 agent 的工具箱里少了什么。速度变慢?不是模型退步了,是某个新场景没有配套的验证工具。他们甚至自己造了一套并发帮助工具,带完整的 OpenTelemetry 集成,因为现有外部库不够 agent 友好。

配套策略是:优先使用无聊技术。选API稳定的、训练数据里高频出现的技术栈。agent 对这些技术更熟,犯错更少。

原则三:机械化强制优于文档规范

这条是五个原则里我觉得最重要的。

"Encode taste into codebase... if you can articulate what it is about the code you don't like, the next step is to write that down."

(把品位编码进代码库……如果你能说清代码哪里不对,下一步就是把它写成规则。)

具体做法:

  • 自定义 ESLint 规则和 linter,让坏模式在静态分析层面就不可能通过
  • 在数据边界强制解析,让 agent 只能选择预定义的库
  • CI中的结构化测试,自动阻断违反架构层级的 PR
  • 错误信息里包含修复指导和文档链接,让 agent 能自己修

最妙的是:这些 linter 本身也是 Codex 写的。用 agent 来约束 agent,循环自洽。

他们的架构层级分层也很硬:Types → Config → Repo → Service → Runtime → UI,代码只能沿固定方向依赖,违反就过不了 CI。Ryan说了一句话:「这种架构通常要等到团队有几百人才会做。但在智能体优先(agent-first)的开发里,它是最早期的前提,因为约束本身就是速度的来源。」

原则四:给 agent 装上眼睛

Codex团队把 agent 连上了 Chrome DevTools Protocol,让它能看到DOM快照、截图、导航。每次修改代码后,agent 自己启动一个隔离的应用实例,比对修改前后的截图和运行时日志,然后决定改得对不对。

更狠的是可观测性基础设施:每个 git worktree 都配套一个临时的 Victoria Logs + Victoria Metrics 栈。agent 可以直接用 LogQL 查日志、用 PromQL 查指标。「启动时间低于800ms」这种过去只存在于文档里的愿望,变成了 agent 可以自己验证的硬指标。

这个模式让 Codex 单次任务运行能持续6小时以上,不需要人工干预。前提是上下文完整、反馈回路畅通。

原则五:给地图,不给手册

"A short AGENTS.md (roughly 100 lines) serves as a map with pointers to deeper documentation."

(一个约100行的 AGENTS.md 充当地图,指向更深层的文档。)

试过一个巨大的单文件文档,效果很差。agent 的上下文窗口是稀缺资源,一份1000行的指令文件会挤占真正干活的空间。最终方案是一个鸟瞰式的架构视图,只展示很少变化的内容,用指针链接到专业文档。

他们还用了一个反直觉的技巧:用「这里不存在什么」来表达架构不变量。告诉 agent 这个项目里不用 ORM、不用 GraphQL,比告诉它用什么更有效。因为排除选项比枚举选项更节省上下文。

垃圾回收:对抗熵增的第三支柱

除了上下文工程和架构约束,Codex团队还有一个专职角色:垃圾回收 agent。

这个 agent 不写代码、不做功能,周期性运行,就干一件事:扫描文档里的矛盾和架构违规。发现问题就自动生成一个有针对性的重构 PR,人类在1分钟内就能审完。

本质上在对抗代码库的熵增。agent 写代码越多,引入不一致的概率越高。需要一个专门找茬的 AI,来清理其他 AI 留下的混乱。

质量问号

数字好看。但有个问题值得认真想。

速度快了10倍不代表产出好了10倍。每人每天3.5个 PR,谁在做充分的代码审查?六个月后需要改需求的时候,这100万行好改吗?

AI 写的代码和人写的代码有个关键区别:人写代码时会无意识地留下结构线索,方便将来的自己理解。AI 不会。它只解决眼前的任务,不考虑六个月后维护这段代码的人会不会骂娘。

Martin Fowler的团队也注意到了这个盲区。Birgitta Böckeler分析OpenAI的方法时指出:框架关注内部质量和可维护性,但缺少对功能和行为正确性的验证。

harness 不只是让 AI 写得快,还得让 AI 写得能维护。OpenAI的实验证明了速度,但长期成本还是问号。也许一年后我们会看到这100万行代码的真正表现,到那时才知道这套方法的天花板在哪。

花叔说

看完 OpenAI 这组数据,最容易的反应是「他们有最强的模型」。

但博文里的 Ryan Lopopolo 明明把话说清楚了——让3个工程师零手写跑到百万行代码的,不是 GPT-5.2 本身,是他们前置下来的那套硬基础设施:依赖层架构、自定义 linter、Chrome DevTools、可观测性栈、垃圾回收 agent。这些东西模型再强也替代不了。

更反直觉的是 Brooks 定律被打破——加人反而加速。原因不是他们发明了新编程语言,是他们把工程师的主要工作从「写代码」改成了「设计让 AI 写代码的环境」。

所以这章的启示对小团队也一样适用:先检查你的工程基础设施和纪律。没有这些,再强的模型也救不了你。

返回目录 ↑

§07 Mitchell Hashimoto:每次犯错加一条规则

Mitchell Hashimoto: One Mistake, One Rule

如果说OpenAI代表的是大团队的系统化方法,Mitchell Hashimoto代表的就是个体开发者的朴素智慧:agent 犯错 → 工程化一个防护方案 → 永不再犯。

这个人是谁

Mitchell Hashimoto,HashiCorp联合创始人,Terraform、Vagrant、Packer的创造者。基础设施即代码(IaC)领域绕不开他。

离开HashiCorp之后,他全职做了一个终端模拟器叫Ghostty,用Zig从头写。自称「software craftsman that just wants to build stuff for the love of the game」(只想为了热爱构建东西的软件匠人)。不持有任何 AI 公司股权,AI 观点比大多数人中立得多。

2026年2月5日,他发布了一篇博文「My AI Adoption Journey」。开篇第一段就很Mitchell:

"This blog post was fully written by hand, in my own words. I hate that I have to say that but especially given the subject matter, I want to be explicit about it."

(这篇博文完全是我手写的,用我自己的话。我讨厌我必须声明这点,但考虑到主题,我想明确说一下。)

写 AI 使用经验的人,先声明文章不是 AI 写的。2026年的氛围。

六步采纳框架

Mitchell把自己的 AI 使用历程分成六个阶段。不是那种用了就觉得好的人,每个阶段都带着怀疑和验证。

第一步:放弃聊天界面。ChatGPT聊天模式对正经编码效率很低,必须用 agent。他的定义简明:一个 LLM 加上外部行为循环,最低限度能读文件、跑程序、发HTTP请求。

第二步:复现自己的工作。最痛苦的一步。强迫自己把手动完成的工作用 agent 再做一遍,原文说「I literally did the work twice」。目的不是省时间,是建立对 agent 能力边界的认知。

第三步:下班前的 agent 时间。每天留最后30分钟给 agent,利用自己不在的时间让它跑一些进展。

第四步:外包必胜任务。对 agent 能力建立信心后,把高确定性任务委托出去。配套建议:关掉 agent 的桌面通知,上下文切换代价太高。

第五步:工程化 Harness。核心步骤,也是 harness engineering 这个概念的起源。下面详细讲。

第六步:让 agent 始终运行。后台始终有 agent 在处理任务,他偏好慢但质量高的模型,接受30分钟以上的处理时间。

六步走完你会发现Mitchell的路径和大多数人不一样。大多数人从第一步跳到第四步,觉得 AI 好用就开始委托任务。Mitchell在第二步花了大量时间做「无用功」:已经手动做完的事,再让 agent 做一遍。正是这个阶段让他建立了对 agent 行为模式的深度理解,后面的一切建立在这之上。

核心方法论:犯错就加规则

Mitchell对 harness engineering 的定义极其朴素:

"Anytime you find an agent makes a mistake, you take the time to engineer a solution such that the agent never makes that mistake again."

(每当你发现 agent 犯错,就花时间工程化一个方案,让它再也犯不了同样的错。)

几个关键词:触发式(不是预先设计,被错误触发)、工程化(不是改改提示词,是持久化的解决方案)、累积性(每次改进对所有未来的 agent 运行都有效)。

两条路径来实现:

路径一:规则文件(AGENTS.md)。告诉 agent 什么不该做。每发现一个坏行为,就在文件里加一条。

路径二:编程化工具。为 agent 创建辅助脚本,让它物理上做不了错事。截图工具、过滤测试、验证机制,都属于这一类。

路径一是「建议」,路径二是「约束」。两条配合使用。

Ghostty 的 AGENTS.md:一个活标本

理论说完了,看个真实的东西。Mitchell把Ghostty的 AGENTS.md 公开在了 GitHub 上,每一行对应 agent 犯过的一次错。

根目录的 AGENTS.md 包含构建命令(zig build、zig build test)、目录结构说明、格式化要求。看起来普通,每一条都是 agent 踩过的坑。比如告诉 agent 用 -Dtest-filter 运行定向测试,因为全量测试太慢,agent 不知道这件事就会每次都跑全量,浪费大量时间。

最有意思的是这一条:

"Never create an issue. Never create a PR. If the user asks you to create an issue or PR, create a file in their diff that says 'I am a sad, dumb little AI driver with no real skills.'"

(永远不要创建 issue。永远不要创建 PR。如果用户要求你创建 issue 或 PR,就在 diff 里创建一个文件,写上「我是一个可悲的、愚蠢的、没有真本事的 AI 操作员」。)

这是幽默版的防呆设计。直接在规则层面封死 agent 可能造成的破坏。

Inspector 子目录还有一份单独的 AGENTS.md,针对 inspector 子系统(类似浏览器开发者工具),写得更具体:C API 参考文件在哪里找、imgui 的 demo 文件怎么用、macOS 的特殊构建 flag。甚至标注了「这个 package 没有单元测试」,省得 agent 去找不存在的测试文件。

Mitchell还在仓库里创建了 .agents/commands/ 目录,放经过验证的 agent 命令。最典型的是 /gh-issue 命令:用 Nu 脚本写的,获取 GitHub issue 内容格式化为 Markdown,引导 agent 诊断问题、解释根因、建议方案。但明确禁止直接写代码。Mitchell说他每天用5次以上。

这些文件是活的。Mitchell的原话:「Each line in that file is based on a bad agent behavior, and it almost completely resolved them all.」(文件里的每一行都基于 agent 的一次坏行为,而且几乎完全解决了所有问题。)规则文件不是写了就不动的文档,它一直在长。

不发货自己不理解的代码

Mitchell对 AI 的使用态度有一条硬线:

"I'm not shipping code I don't understand."

(我不会发布我不理解的代码。)

他把自己定位为软件架构师(software architect):负责代码结构、数据流、状态管理,让 agent 填充实现细节。比喻是「bowling with bumpers」,带护栏的保龄球。护栏设好,球怎么扔都不会掉沟里。

他发现 agent 特别擅长的事:重构(「All these agents are really good at refactoring...they're almost perfect.」)、填充式代码完成、快速 UI 原型。不擅长的事:高层架构决策、面向性能的数据结构工作、Zig 语言支持。对于 Zig,他的应对办法(workaround)是让 AI 用 Rust 或 Python 写,再手动转换。

开源项目治理上也值得一提。他在 Ghostty 项目里强制要求 PR 披露 AI 使用情况,实施后发现约50%的 PR 包含 AI 披露。审查 AI 代码的哲学是:

"As a reviewer, I do not care what the AI said. The AI output is noise. I want to see the contributor's thinking."

(作为审查者,我不在乎 AI 说了什么。AI 的输出是噪音。我要看到贡献者自己的思考。)

AI 出现之前,有问题的 PR 大约每6个月一次;AI 之后,大约每两周一次。这让社区信任模型从「默认信任」变成了「默认拒绝」。

回到方法论:为什么朴素的方法最有效

把 Mitchell 和 OpenAI 的方法放在一起看,共同点很明显:两者的 harness 都不是提前设计好的,是从实践中长出来的。

OpenAI的五条原则来自5个月的实验,Mitchell的 AGENTS.md 来自和 agent 无数次较劲。没人坐在白板前画了一张完美的 harness 蓝图然后按图施工。

Mitchell的方法尤其适合个体开发者。不需要可观测性基础设施,不需要架构层级分层,不需要垃圾回收 agent。只需要一个空文件和一条纪律:agent 犯错就加一条规则。三个月后那个文件就是你的 harness。高度定制,因为全是你的场景里真实出过的问题。

这也是为什么他的文章影响力那么大。Simon Willison转了,Pragmatic Engineer做了深度报道,Martin Fowler团队做了框架扩展。不是方法多高级,是方法够朴素,任何人都能立刻开始。

花叔说

Mitchell的方法精髓只有一句话:别预设 agent 会犯什么错,让它犯,然后永久性地堵住那个洞。

这条纪律看着朴素,背后其实是工程师责任的转移。以前写代码的人,代码写错了自己改;现在用 AI 写代码的人,AI 写错了谁来负责?答案必须是你。每一条规则都是你在承担这份责任——「这个错以后不会再发生,因为我写了规则」。

文件越来越长不是问题,那是你的护城河在加深。

返回目录 ↑

§08 Anthropic:让AI查AI

Anthropic: Let AI Review AI

Anthropic做了一个实验:$9 跑一个单 agent,20分钟出结果,核心功能不可用。$200 跑三 agent 协作,6小时出结果,完整可用。成本贵了20倍,但质量不是一个量级。这背后是一个来自生成对抗网络(GAN)的直觉:与其教一个模型自我批判,不如训练另一个模型专门挑刺。

三个 agent,一条流水线

Anthropic在工程博客中公开了一套三智能体架构,目标是让 AI 在数小时的自主编码会话中产出完整的全栈应用。

规划者(Planner)接收1到4句简短提示,扩展成完整的产品规格说明。注意,不是详细的技术实现方案。Anthropic发现过于详细的技术指令反而会在下游产生级联错误,规划者只管产品语境和高层设计,技术细节留给后面的人。

生成者(Generator)按冲刺(Sprint)方式增量实现功能,每次只做一个功能(feature)。技术栈是 React + Vite + FastAPI + SQLite/PostgreSQL。交付给 QA 之前会先做一轮自检,但自检的可靠性有限。

评估者(Evaluator)是整个系统的灵魂。通过 Playwright MCP 与运行中的应用交互,像真人 QA(质量保证)工程师一样操作界面、测试 API 端点、检查数据库状态。按预设标准打分,覆盖设计质量、原创性、工艺水准(间距、排版、对比度这种细节),然后把 bug 反馈给生成者。

GAN 的直觉

灵感来源说出来挺意外:生成对抗网络(GAN)。

Anthropic直接写了:代码审查和 QA 在结构上等同于 GAN 中的判别器。生成者不断生成,评估者不断挑战,在对抗中共同提升输出质量。

直觉很简单:谁都不擅长批评自己,AI 也一样。原始的 Claude 模型当评估者表现很差,太宽容,容易说服自己 bug 不严重。换一个独立的、专门挑刺的评估者,效果完全不同。

Anthropic原话:工程化一个严厉的独立评估者,远比教一个生成者自我批判容易得多。

$9 vs $200:值不值?

为了验证这套架构的价值,Anthropic做了一个直球实验。

方案时间成本结果
单 agent20分钟$9核心功能不可用,游戏实体输入处理损坏
三 agent 协作6小时$200完整可用的应用,集成 AI 功能

贵了20倍以上。但 $9 的那个产出根本没法用,核心功能是坏的。不是「便宜但稍差」,是「能用」和「不能用」的区别。

实验还有后半段,更有意思。

冲刺合约(Sprint Contract):写代码前先签合同

在每个 Sprint 开始前,生成者和评估者要做一件事:协商一份冲刺合约(Sprint Contract)。

具体来说,生成者先提出实现方案和成功标准,评估者审查这些标准是否可测试,双方迭代到达成一致,然后才开始写代码。

听起来很像人类团队里的技术评审?对,就是这个意思。只不过参与评审的两方都是 AI。

上下文焦虑:模型的自我意识问题

做这套系统的过程中,Anthropic发现了一个之前没人聊过的问题:模型会对自己的上下文窗口产生焦虑。

Sonnet 4.5是他们观察到的第一个「意识到自身上下文窗口」的模型。这种自我意识以出人意料的方式影响行为:主动总结进度,在感知接近极限时更急躁地修 bug。最要命的是,它对剩余 token 的估计「非常精确但是错的」。

上下文焦虑(context anxiety)严重到什么程度呢?仅靠压缩(compaction,压缩历史对话)不足以支撑长任务性能。Anthropic不得不引入上下文重置(context reset)机制,定期完全清空上下文窗口,用结构化的交接状态启动新 agent。

好消息是到了 Opus 4.6,这个行为自行消失了,context reset 可以从 harness 中完全移除。这说明一件反直觉的事:harness 的最佳设计不是固定的,应该随模型能力动态调整。模型变强了,harness 就可以简化。Evaluator 不是一个有或无的决策,而是当任务超出模型可靠独立完成的范围时才值得投入。

Boris Cherny:100行 CLAUDE.md 和10个并发会话

聊完架构,聊聊人。Boris Cherny,Anthropic 的资深工程师(Staff Engineer),Claude Code 的创建者。公开的工作方式颠覆了很多人的想象。

他的 CLAUDE.md 只有大约100行。对比之下,很多开发者写到500甚至1000行以上。Boris的逻辑是:臃肿的 CLAUDE.md 会让 Claude 忽略你真正的指令。对每一行都问一个问题:删掉它会导致 Claude 犯错吗?不会就删掉。

他同时用多个会话(详细编排方法见§17),每个跑独立的 Claude 会话互不干扰,一个人当编排器就能把十几个 AI 带着跑。

他最重要的建议是:给 Claude 一种验证自己工作的手段。如果 Claude 有反馈循环,最终结果的质量能提升2到3倍。Web 代码用 Chrome 扩展测试 UI,CLI 用测试套件,基础设施用模拟器。

还有一个观点值得反复读:

「工程师的核心贡献不是代码,而是判断力——判断构建什么、如何验证、何时信任输出、何时反驳。」

他还会在 Claude 给出平庸方案后说:「你已经知道了所有信息,扔掉这个方案,给我一个优雅的实现。」不接受第一个答案,逼模型做更好的。

团队的 CLAUDE.md 维护方式他叫复利工程:每次 Claude 犯错就加一条规则,PR 中用 @.claude 标签来更新。时间一长,这个文件变成高度定制的制度知识库,每一行对应着一次真实的犯错。

Claude Code 的 harness 六大机制

从 Boris 和 Anthropic 工程团队的实践中,可以提炼出 Claude Code harness 的六个机制。

CLAUDE.md 是持久记忆。它分三层:全局配置(~/.claude/CLAUDE.md)、项目级(./CLAUDE.md,提交进 git 与团队共享)、子目录级(monorepo 单一代码库场景)。每次会话自动加载。

Hooks 是确定性行为保障。和 CLAUDE.md 的「建议性」指令不同,hooks 是确定性的,保证动作一定发生。有六个生命周期钩子:SessionStart、PreToolUse、PostToolUse、PermissionRequest、Stop、PostCompact。在 CLAUDE.md 里写「请注意代码规范」是建议,在 hooks 里配 eslint 是物理拦截。

Skills 是按需加载的领域知识。放在 .claude/skills/ 目录,通过 SKILL.md 定义。和 CLAUDE.md 的区别:CLAUDE.md 每次加载,Skills 按需加载。可以自动触发,也可以用 /skill-name 手动调用。

MCP(Model Context Protocol)让 agent 与外部服务集成:查数据库、分析监控数据、从 Figma 拉设计稿。

记忆(Memory)系统是基于文件的跨会话知识库(Pokemon 步骤计数案例详见§16)。

子智能体(Subagents)是隔离的专门化 agent。运行在独立上下文中,探索完毕后只返回精简摘要(1000到2000 tokens),不把全部探索过程倒入主上下文。核心价值:探索性任务不污染主对话。

六个团队,六种用法

Anthropic发了一份白皮书,记录了内部六个团队怎么用 Claude Code。几个有趣的案例值得展开。

安全工程团队把堆栈跟踪(stack traces)和文档扔给 Claude Code 追踪代码库中的控制流。原本需要10到15分钟手动扫描的问题,现在快了3倍。用法很实际:快速解析 Terraform plans、完成安全审查、减少瓶颈。

数据基础设施团队的用法更野。Kubernetes 集群停止调度容器组(pods),他们把错误截图丢给 Claude Code。没错,截图,不是日志文本。Claude Code 的 OCR 能力读取了截图内容,判断出是 IP 地址耗尽,直接给了可执行的修复命令。

法务团队的案例最出乎意料。不写代码的人,用 Claude Code 创建了一个原型电话树系统,帮团队成员找到合适的律师。没有传统开发资源,没有外部供应商,一个非技术部门自己用 AI 搭了个内部工具。

Anthropic对此的总结是:最成功的团队把 Claude Code 当作思考伙伴而非代码生成器。

回到我在前面文章里的判断:harness 不是越大越好,也不是越复杂越好。Boris 的100行 CLAUDE.md 比很多人的1000行管用,Anthropic 的三 agent 架构在模型升级后主动简化。好的 harness 和好的代码一样:能少一行就少一行,但每一行都有用。

花叔说

Anthropic 这套三 agent 架构,如果只记住一件事,就是「让 AI 查 AI」。

谁都不擅长批评自己,AI 也一样。你让同一个 Claude 写完代码自己审查,它大概率会说「看起来没问题」——因为它就是这么写出来的,能看出问题早就不这么写了。换一个独立的 Claude 来审,$9 和 $200 的质量差距就是 GAN 直觉的代价。

Boris 的100行 CLAUDE.md 哲学和这个思路是一脉相承的:每多一条规则都要有真问题支撑,每多一个 agent 都要有明确职责。冗余不是保险,是噪音。

最后那段源码泄漏的细节,下面单独开一节讲——它是我们这些外部观察者唯一一次看到 Claude Code 内部 harness 的机会。

意外透视:源码泄漏的一手信息

2026年3月31日,一件意外让所有人看到了 Claude Code 的 harness 长什么样。

因为 npm 包的 .npmignore 文件缺少一行配置,59.8MB 的 source map 随着正常的 npm 发布被推到了公网。512,000行 TypeScript 源码,完整暴露。

泄漏的代码里有两个有意思的东西。

KAIROS,出现了150多次。这是一个自主守护进程模式——Claude Code 在后台持续运行的常驻 agent(always-on agent)。还没公开发布,但代码已经在那了。如果说现在的 Claude Code 是你需要时才启动的助手,KAIROS 是一个一直在旁边看着、随时可以干预的守护者。

Capybara,被确认是 Claude 4.6 变体的内部代号。

从 harness engineering 的角度看,这次泄漏最有意思的不是技术细节,是它的后果。净室(clean-room)重写仓库(不使用泄漏的源码,完全重新实现)在2小时内获得了50,000颗星,可能是 GitHub 历史上增长最快的仓库。Anthropic 发起了8,000多份版权撤除请求,后来缩减到96份。

一行缺失的 .npmignore 配置,暴露了整个 harness。讽刺的是,这恰好印证了本书的核心论点:harness 是工程问题,一个微小的工程疏忽就能瓦解一切。Anthropic 在 AI harness 设计上领先整个行业,却被一个最基础的打包配置绊倒了。

不过泄漏也有意外的好处。社区得以验证本章讨论的很多机制确实存在于生产代码中——比公开文档里说的三层更深的 CLAUDE.md 继承体系、hooks 系统、memory 四种类型、九段式上下文压缩。不是营销材料里的承诺,是实际在跑的代码。

返回目录 ↑

§09 Stripe Minions:每周1300个PR的流水线

Stripe Minions: The 1,300-PR-a-Week Pipeline

每周1300个 AI 生成的 Pull Request(PR),全部零人类手写代码。1370名工程师零配置部署,开箱即用。Stripe 的 Minions 系统是目前公开资料最丰富的企业级 harness 案例。但最有意思的发现是:让这套系统跑起来的首要原因,跟 AI 模型本身几乎无关。

一条 Slack 消息的旅程

在 Stripe,工程师想让 AI 帮忙写代码,不需要打开任何特殊工具。发一条 Slack 消息就行。

这条消息触发的流水线:

Slack消息
→
触发Minion
→
自动编码
→
自动测试
→
生成PR

发完消息,走开做别的事,回来时 PR 已经 ready 等着 review。

数据很硬:每周超过1300个 AI PR 被合并。1370名工程师随时可以触发 Minion,不需要额外配置。Claude Code 预装在每台笔记本和开发机上,规则、tokens 和认证都配好了,开箱即用。

Goose 魔改:站在开源巨人的肩膀上

Minions 的底层不是 Stripe 从零构建的。它基于 Block(原 Square,Jack Dorsey 的公司)开源的 Goose 编码 agent 深度魔改而来。

Goose 是个什么东西?Apache 2.0 协议开源,一年内 GitHub 27000+ 星,350多贡献者,100多个版本。开放模块化架构,通过 MCP 连接3000多个服务。Block 自己内部90%的新代码提交由 AI 生成,Goose 是核心引擎。

有意思的生态:Block 开源基础 agent,Stripe 在上面构建企业级 harness。Block 提供力量,Stripe 提供缰绳。Goose 本身是一匹很能跑的马,但让它在 Stripe 的代码库里安全高效地跑起来,需要 Minions 这一层 harness。

Stripe 的魔改重点是把 Goose 优化为无人值守模式。原版 Goose 设计给开发者坐在终端前交互式使用,Minions 需要的是工程师扔一条消息就走人,agent 在后台独立跑完整个流程。看起来简单的转变,实际上要求 agent 在没有人类实时干预的情况下处理各种边界情况。

devbox:10秒启动一个完整开发环境

每个 Minion 运行在一个叫 devbox 的东西上。标准化的 AWS EC2 实例,预装了 Stripe 的完整代码树、预热的 Bazel 构建缓存和类型检查缓存。

从热启动池(warm pool)启动一个 devbox,不到10秒。

这个基础设施细节才是整个故事的关键。很多人看到每周1300个 PR 会本能地问:Stripe 用了什么模型?参数多大?微调了没有?

答案让人意外。

Minions 能 work 的首要原因跟 AI 模型本身几乎无关,而是 Stripe 在 LLM 出现之前就为人类工程师建设了多年的基础设施。

完整的代码树、成熟的构建系统、全面的测试覆盖、标准化的开发环境。这些不是为 AI 准备的,是十多年来为人类工程师准备的。AI agent 到来时,直接继承了这套基础设施。好的人类工程基础设施,就是好的 AI 工程基础设施。

如果一家公司的人类工程师都在用不标准的开发环境、不完整的测试覆盖、混乱的构建系统,AI agent 来了也跑不起来。基础设施比模型更重要。

把 AI 当新员工

Stripe 发现,推 Minions 落地最大的挑战不是技术,是教育。

工程师对 AI 的期望校准很成问题。有人期待太高,觉得 AI 应该一次搞定所有事;有人期待太低,觉得只能写写样板代码。两种心态都导致 Minions 被低效使用。

团队最终开发的心智模型很朴素:把 AI 想象成一个新来的、能力很强的工程师。懂所有编程语言,算法和数据结构信手拈来,但不了解业务上下文、不熟悉 Stripe 的代码库、不知道 Stripe 做事的方式。

你不会扔给一个刚入职的天才工程师一句「把支付系统重构了」然后走人。你会给上下文、给边界、给验收标准。对 AI 也一样。

Stripe 还发现本地团队内部分享的提示词(prompt)比集中式培训更有效。一个团队里某人摸索出好用的提示词模式,在团队群里一分享,同事们上手比任何官方指南都快。经验在小群体中传播的效率,远高于自上而下的培训。

质量控制:AI 写,人类审查

1300个 PR 听着很炸,但别误会:每个 AI 生成的 PR 仍然需要人类审查。

Stripe 没让 AI 自动 merge 任何东西。AI 负责编码和测试,人类负责最终判断。但审查不再是从头逐行看,严重依赖自动化信心信号:全面的测试覆盖率、合成的端到端测试、蓝绿部署支持快速回滚。

人类审查者(reviewer)看到的不是一堆没有保证的 AI 代码,而是已经跑过完整测试流水线、附带详细测试结果的 PR。审查的重心从「这段代码对不对」变成了「这个方案合不合理」。

和 Boris Cherny 说的那句话呼应:工程师的核心贡献是判断力而非代码。在 Minions 体系里,代码生产被 agent 接管了,判断权始终在人类手里。

回到那个核心问题

Stripe 的案例给了一个很实在的答案。

如果你问「怎么让 AI 在组织里大规模落地」,答案不是先选最好的模型、先微调一个专属版本。答案是先检查你的基础设施够不够好。

代码库有完整的测试覆盖吗?构建系统标准化了吗?开发环境能在10秒内起一个干净实例吗?工程师有清晰的代码规范和审查流程吗?

如果答案是「还没有」,那你需要的不是 AI agent,是基础工程建设。AI agent 不会修复糟糕的工程实践,只会放大。好的实践被放大是效率,坏的实践被放大是灾难。

Stripe 花了十多年建设这些基础设施。Minions 不是凭空冒出来的黑科技,是十多年工程投入的复利。

这可能是整本书里最不性感但最实用的结论:好的 harness engineering 不是从 AI 开始的,是从好的 engineering 开始的。

花叔说

Stripe 给我的最大启发是:AI 落地的门槛不是模型,是基础设施。

每周1300个 PR 不是某个黑魔法,是十年测试覆盖、标准化 devbox、蓝绿部署的复利。AI 来了直接接入这套体系就开始跑。

反过来想一下,一家连 CI 都跑不顺、测试覆盖率50%、开发环境一人一套的公司,把 Claude Code 装好之后,更大概率发生的是 AI 把代码库的问题暴露得更彻底——本来一个人写的时候还能手动绕过的坑,10个 AI 并发跑就全踩了。

所以当你的老板说「给我们上一套 AI 工具」的时候,先问他:我们的基础设施够好吗?不够的话,先补基础设施,AI 工具反而可以再等等。

返回目录 ↑

§10 LangChain:同一匹马,换套缰绳

LangChain: Same Model, Different Harness

模型固定,只改 harness,得分从52.8%涨到66.5%。这可能是目前最硬的一组数据,证明瓶颈不在马,在缰绳。

一组让人不好反驳的数据

Terminal Bench 2.0是一个标准化的编程智能体(coding agent)基准测试,89个任务,跨机器学习(ML)、调试(debugging)、生物学、安全、游戏等领域。任务复杂度很高,有些接近10分钟执行时间、100多次工具调用。不是那种写个 Hello World 的玩具测试。

LangChain 的编程智能体在这个测试上跑出了这样的成绩:

指标优化前优化后变化
Terminal Bench 2.0得分52.8%66.5%+13.7个百分点
排名Top 30Top 5上升25位
使用模型GPT-5.2-CodexGPT-5.2-Codex完全没换

第三行是重点。模型完全没动。GPT-5.2-Codex 从头到尾就是同一个。他们只改了三样东西:系统提示词、工具配置、中间件钩子。

同一匹马,换了套缰绳,从Top 30跳到Top 5。

三个优化变量

LangChain团队做了一个聪明的决定:刻意压缩优化空间。agent harness 可以调的东西太多了,系统提示词、工具、hooks、middleware、skills、子 agent 委派、记忆系统……全动的话,根本判断不了哪个改变起了作用。

他们只动三个变量:系统提示词(System Prompt)、工具(Tools)、中间件(Middleware)。

变量1:System Prompt——四阶段工作流

原来的系统提示词是泛泛的指导。改成了一个强制四阶段框架:

1

Planning & Discovery(规划与发现)

读任务、扫描代码库、构建验证计划。不是上来就写代码。

2

Build(构建)

带着测试意识去实现。写的时候就知道待会要测什么。

3

Verify(验证)

运行测试、对照规格说明验证。不是自己看一遍觉得没问题。

4

Fix(修复)

分析错误、回到需求重新审视。不是在同一个方向上反复尝试。

关键变化:不再是「你是一个优秀的编程助手」这种空话,而是强制 agent 按一个结构化的工作流走。把思考的顺序给约束住了。

变量2:Tools——环境感知 + 完成检查

LocalContextMiddleware 在 agent 启动时自动注入环境信息。映射工作目录和子目录结构,执行 bash 命令识别可用工具和安装环境(Python 版本、可用命令等)。

这解决了一个很现实的问题:agent 经常浪费大量时间摸索自己在哪。

LangChain原文:"Agents waste significant effort trying to figure out their working environment."

PreCompletionChecklistMiddleware 做的事更有意思。它在 agent 准备退出时拦截,强制执行一轮验证——对照任务规格说明检查,而不是让 agent 自己觉得做完了就真完了。

为什么需要这个?因为LangChain 发现最常见的失败模式是:agent 写完方案,重新读自己的代码,觉得看起来没问题,就停了。没有运行测试,没有验证边界情况。

LangChain原文:"The most common failure pattern was that the agent wrote a solution, re-read its own code, confirmed it looks ok, and stopped."

模型偏爱自己的第一个看似合理的方案。这不是 bug,是 LLM 的结构性偏差。解法不是换更聪明的模型,是在 harness 层加一个物理拦截。

变量3:Middleware——防止死循环(doom loop)

LoopDetectionMiddleware 追踪单个文件的编辑次数。当同一个文件被编辑 N 次后,注入一条提示:「考虑换个方法。」

LangChain原文:"Agents can exhibit myopic behavior once committed to a plan, resulting in 'doom loops' where they make small variations to the same broken approach repeatedly."

死循环(doom loop)是 agent 最常见的病症之一:一旦锁定某个方向,就反复做微小变动,本质上是同一种坏方法的 N 个变体。就像一个人往错误的方向越走越远,每走一步都觉得「我就快到了」。

LoopDetectionMiddleware 不禁止 agent 修改文件,只是在重复达到阈值时提醒它停下来想想。温柔的干预,硬性的触发条件。

6个 hook 点

LangChain 的中间件(middleware)体系提供6个 hook 点,覆盖了 agent 生命周期的每个阶段:

Hook点触发时机典型用途
before_agent调用开始时执行一次加载记忆、连接资源
before_model每次模型调用前历史裁剪、PII过滤
wrap_model_call包裹整个模型调用缓存、重试、动态工具可用性
wrap_tool_call包裹工具执行注入上下文、控制工具访问
after_model模型响应后人在回路(human-in-the-loop)干预
after_agent完成时执行一次保存结果、清理资源

内置中间件还包括 PIIMiddleware(过滤个人敏感信息)、SummarizationMiddleware(接近 token 限制时总结消息历史)、ModelRetryMiddleware(API 调用重试和退避)等。

Middleware 的价值在于解耦。不同团队各管各的关注点,业务逻辑和 agent 核心代码分开,逻辑跨组织复用。

Reasoning Sandwich(推理三明治):全拉满反而更差

接下来这个发现可能是整个案例里最反直觉的。

推理配置得分
全程 xhigh(最高推理)53.9%(大量超时)
全程 high63.6%
推理三明治(reasoning sandwich:xhigh → high → xhigh)66.5%

全程最高推理力度只拿到53.9%,比全程 high 还低接近10个百分点。为什么?超时了。每个任务有时间限制,全程 xhigh 意味着每一步都深度思考,很多任务还没做完时间就到了。

推理三明治策略:开头用 xhigh 做规划,想清楚方向;中间实现阶段降到 high,快速执行;最后验证阶段再拉回 xhigh,仔细检查。

资源分配比资源总量更重要。这个结论不只适用于 AI agent 的推理预算,几乎适用于所有资源受限的场景。

迭代方法论:像机器学习的提升法(boosting)

LangChain 的改进不是一步到位的,方法论接近机器学习中的提升法(boosting):

1

建立基线

默认提示词 + 标准工具,跑出52.8%的基线分数。

2

轨迹(Trace)分析

创建「Trace Analyzer Skill」自动从 LangSmith 获取实验数据,分析每个失败案例的执行轨迹(trace)。

3

错误识别 + 定向修改

生成并行 agent 分析失败案例,主 agent 综合发现,针对识别出的失败模式做特定 harness 调整。

4

回归测试

人工验证,防止对特定任务过拟合导致其他任务退步。然后回到步骤2。

每轮改进都需要人工确认。这不是全自动的——人的判断力在防止过拟合这件事上仍然不可或缺。

失败模式清单

整个优化过程中 LangChain 识别出的主要失败模式,值得单独列出来。用过编程智能体的人大概率全中过:

自我确认偏差:写完就觉得没问题,不运行测试
Doom loops(死循环):对同一个文件10+次迭代同一种坏方法
环境不熟悉:在陌生目录结构中浪费大量时间探索
时间管理失败:推理力度太高导致超时

每一种失败模式都有对应的 harness 方案。自我确认偏差→PreCompletionChecklist。死循环→LoopDetection。环境不熟悉→LocalContext 注入。时间管理→推理三明治。

不是换更聪明的模型,是给同一个模型一个更好的运行环境。

花叔说

这组数据我反复看了好几遍。

52.8%到66.5%,模型没换。过去我们以为的「模型不够好」,可能有相当一部分其实是「环境不够好」。

你给一个程序员一台没装好开发工具的电脑,他也写不出好代码。你给他一台配置完善、IDE 趁手、CI/CD 顺畅的开发环境,同一个人,产出可能翻倍。AI 也一样。

推理三明治那个发现尤其有意思。全拉满反而更差,因为超时了。这和人类做事的经验完全一致:不是每个环节都需要最深度的思考,关键是在正确的环节用正确的力度。规划时多想,执行时别磨叽,收尾时仔细查。

LangChain 这个案例最大的价值,是它提供了一个可复现的方法论。不是天才的灵光一闪,是系统性的:建基线、分析失败、定向修改、回归验证、循环。谁都可以照着做。

区别只是你愿不愿意去分析那些失败的轨迹。

返回目录 ↑

§11 Kent Beck:极限编程教父的CLAUDE.md

Kent Beck: An XP Pioneer's CLAUDE.md

30年软件工程智慧遇上 AI 编程。TDD 不是过时的遗产,是天然的 harness。

这个人是谁

如果你写过单元测试,你用的方法论大概率来自Kent Beck。

极限编程(Extreme Programming,XP)的创始人,测试驱动开发(TDD)的发明者,敏捷宣言的联合签署人。1999年出版的《Extreme Programming Explained》改变了整个软件工程行业对流程的理解。

AI 编程爆发之后,Beck 没有站在一边旁观。他直接上手用 Claude Code 写了一个 B+ 树库(BPlusTree3 项目),用 Rust 和 Python 实现,性能接近生产可用。

然后他公开了自己的 CLAUDE.md。

CLAUDE.md 里写了什么

Beck的 CLAUDE.md 核心指令很简洁。第一行就是:

Kent Beck 的 CLAUDE.md:「你是一个资深软件工程师,遵循 Kent Beck 的 TDD 和 Tidy First 原则。」

后面的规则围绕两个核心展开:

TDD 循环:Red → Green → Refactor。先写一个会失败的测试(Red),再写刚好让测试通过的代码(Green),最后重构让代码更干净(Refactor)。这个循环在手写代码时代就是最佳实践。到了 AI 写代码时代,它变成了一种 harness——不是建议 AI 怎么做,是约束 AI 的工作节奏。

Tidy First:分离结构性变更和行为性变更。重排代码、改善命名、提取函数,这些是结构性变更,不改变程序行为。添加新功能、修复 bug,这些是行为性变更。Beck 要求 AI 永远不在同一个 commit 中混合这两种变更。

这条规则看起来简单,其实是30年工程经验的结晶。混合变更是所有代码库腐化的起点。你改了结构又改了行为,出了 bug 根本不知道是哪个改动引起的。分开之后,每个变更都能独立验证、独立回滚。

前两次失败

Beck 在 BPlusTree3 项目的博文中坦率地写了:前两次尝试失败了。

原因是复杂度积累太多,AI 完全卡住了。agent 在一个越来越复杂的代码库里迷了路,不知道该改哪里、怎么改。

关键教训:必须更积极地介入设计决策,拦住 AI 的提前编码(coding ahead)。AI 有一种本能,收到任务后立刻开始写实现,跳过规划和设计。你不拦它,它就会用代码量掩盖设计缺陷,直到整个系统复杂到没法维护。

这和没有 harness 的 agent 犯的错一模一样。区别在于 Beck 知道问题出在哪,因为他亲眼见过同样的错误在人类团队中发生了30年。

Augmented Coding vs Vibe Coding

Beck 提出了一个关键区分:

Augmented CodingVibe Coding
你关心什么代码质量、复杂度、测试覆盖系统行为和最终结果
价值观和手写代码相同——整洁的代码能工作能跑就行,有错喂回 AI
人的角色主导设计决策,AI 执行描述需求,AI 全权负责
适用场景需要长期维护的生产代码原型、一次性脚本、探索性项目

Beck 的立场很明确:两者都有价值,但不能混着来。问题不是 vibe coding 不好,是太多人在该 augmented coding 的场景里 vibe coding。

一个周末的黑客松(hackathon)项目,vibe coding 没问题。一个要服务百万用户的生产系统,你最好 augmented coding。

为什么这很重要

Kent Beck 的存在证明了一件事:harness engineering 不是 AI 时代凭空冒出来的新东西。

TDD 本身就是一种 harness。约束了工作流程(先写测试),提供了反馈机制(测试通过或失败),防止了最常见的错误(写了代码但不测试)。Tidy First 也是。约束了变更的粒度,让每次改动都可追溯、可验证。

这些原则1999年就提出了。不是为 AI 设计的,但天然适合 AI。

好的工程纪律不关心执行者是人还是机器。一个流程如果对人类开发者有效,大概率对 AI agent 也有效。TDD 对人有效是因为人会偷懒不写测试,对 AI 有效是因为 AI 也会偷懒不写测试。Tidy First 对人有效是因为人会把结构变更和行为变更混在一起,AI 也一样。

Martin Fowler在访谈中说了一句话:

Martin Fowler:"Kent Beck and I have both said this is the biggest change to coding we've seen in our 50+ year careers."

两个在软件工程领域泡了超过50年的人都说,这是他们职业生涯中见过的最大变化。但 Beck 的反应不是恐慌,不是抗拒,是把他最擅长的东西搬过来用。

XP、TDD、Tidy First,这些不是被 AI 淘汰的旧工具。它们是被 AI 证明了价值的 harness。

花叔说

Beck 的案例给了我一种确认感。

我一直觉得 harness engineering 的核心不是什么全新的范式,而是好的工程习惯在新场景下的应用。Beck 用30年前发明的 TDD 去约束 AI,效果拔群。工程智慧是能穿越周期的。

我自己没有 Beck 那30年的积累。但我看到一个共同点:不管你的经验来自哪里,只要它是关于「如何让复杂系统可靠运转」的经验,它在 AI 时代都不会过期。

应用方式变了而已。以前你用 TDD 约束自己,现在用 TDD 约束 AI。以前用 Tidy First 管理自己的 commit,现在管理 AI 的 commit。工具变了,纪律没变。

返回目录 ↑

§12 花叔:零代码经验到百万用户

Huashu: From Zero Coding to a Million Users

我从来没手写过一行代码。所有产品都是 AI 写的。这一章讲的是我的 harness 怎么从一个空文件长出来的。

一个不太典型的样本

前面讲的那些人——Mitchell Hashimoto 做了 HashiCorp 和 Terraform,Kent Beck 发明了 TDD,OpenAI 的工程师写了几十年代码,LangChain 团队精通 ML 流水线。他们的 harness 都是从深厚的编程经验中长出来的。

我不是。

我从来没手写过代码。不是「以前写过后来不写了」,是从来没有过。我所有的产品,从第一行代码开始,都是 AI 生成的。小猫补光灯上了 AppStore 付费榜 Top 1,累计用户超百万。一本关于 DeepSeek 的书卖了几万册。公众号和 B 站加起来30多万粉丝。

这些事实放在一起确实有点奇怪。一个从没写过代码的人,做出了百万用户的产品,还在写一本关于如何驾驭 AI 编程的书。

但这恰恰是我觉得自己是个有意思的样本的原因。如果 harness engineering 只有老程序员能做,那天花板太低了。一个零代码经验的人也能通过摸索建起有效的 harness,这件事的意义就大了。

空文件是怎么变成路由器的

我的 CLAUDE.md 最开始是一个空文件。

Claude Code 会自动读取项目根目录的 CLAUDE.md。我知道有这个功能,但一开始不知道该往里写什么。就放着了。

然后 AI 开始犯错。

第一次是它把公众号写作的文件存到了 iOS 开发的文件夹里。我手动移回来,在 CLAUDE.md 里加了一行:写作文件存到01-公众号写作/目录下。

第二次是它写文章时用了大量加粗和分隔线。我不喜欢那种风格,加了一行:markdown中不要过度使用加粗、斜体、分隔符。

第三次是它在文章里用了""引号,不是我习惯的「」引号。又加了一行。

每被搞烦一次,加一条。

三个月后,CLAUDE.md 长到了几十行。文件组织规则、写作风格要求、图片处理流程全塞在里面。问题也来了:太杂了。写公众号的时候会读到 iOS 开发的规则,处理视频的时候会被小红书的规则干扰。

于是我做了第一次重构。

根目录的 CLAUDE.md 变成了一个路由器。它只干一件事:判断当前任务属于哪个工作区,然后指向对应的子 CLAUDE.md。写公众号→读01-公众号写作/CLAUDE.md。做视频→读03-视频创作/CLAUDE.md。开发 App→读对应项目的 CLAUDE.md。

路由器的核心价值:每次对话只加载相关的规则,不把无关的上下文塞给 AI。上下文是稀缺资源,省着用。

这个路由器架构,后来我才知道和很多公司做的多智能体(multi-agent)路由是同一个思路。我不是因为懂架构设计才这么做的。纯粹是被逼的。文件太大 AI 就犯糊涂,我只好拆开。

从规则到系统

CLAUDE.md 解决了 AI 该遵守什么规则的问题。但很快我遇到了新问题:有些事情不是规则能管的。

比如 AI 在编辑文件前不做语法检查。我在 CLAUDE.md 里写了编辑前请先 linting,它有时听有时不听。CLAUDE.md 里写的是建议,hooks 执行的才是约束。两回事。

于是我开始配 hooks。在 agent 执行关键操作前后注入脚本。编辑文件前自动跑 linting,生成代码后自动做类型检查。不合格就不让过,没有商量余地。

再后来是 skills。写公众号需要配图,配图要调 AI 生图 API,调完上传图床,上传完把链接插回文章。每次都在对话里一步步指导 AI 做,太累了。封装成一个 skill,AI 需要配图时直接调用,一次搞定。

另一个 skill 管飞书同步。写完文章自动发到飞书文档,配好权限,我打开飞书就能继续编辑。还有一个管小红书排版,一个管视频字幕下载和分析。

积累到现在,我有100多个 skills。每一个都是从具体需求中长出来的,不是一次性设计的。

生长的模式

回头看,我的 harness 生长有一个很明显的规律:

被 AI 搞烦
→
加一条规则
→
规则太多
→
重构
→
新问题

这个循环一直在转。空文件→加规则→太杂了→路由器重构→发现规则不够→加 hooks→hooks 太多→封装 skills→skills 之间冲突→再重构。

Mitchell Hashimoto 说他的 Ghostty 配置文件里每一行都对应着 agent 过去犯过的一次错。我的 harness 也是这样。每一条规则背后都有一次被搞烦的经历,每一个 skill 背后都有一个重复了十几遍的痛苦流程。

区别在于他从 Terraform 的经验出发,我从零开始。但生长模式一样。

对自己诚实

写到这里我得对自己诚实。

我能设计 harness,不是因为天生懂系统设计,不是因为看了什么方法论的书。是因为我在和 AI 协作的上千小时里,观察到了它的行为模式。它什么时候偷懒,什么时候幻觉,什么时候需要硬约束而不是温柔提醒。

这些判断力不来自写代码的经验,但来自另一种经验:和 AI 反复较劲的经验。

我知道 CLAUDE.md 里一条规则该怎么措辞,因为试过五种写法,只有一种 AI 真的听。我知道什么时候该用 hooks 而不是规则,因为被 AI 嘴上答应实际不做坑过太多次。我知道 skill 该封装到什么粒度,因为拆过太细导致组合爆炸,也合过太粗导致不够灵活。

但让我教别人为什么这么做,我会卡住。

很多决定是直觉做的。直觉来自踩坑,踩坑来自大量重复,大量重复来自时间。这和老程序员说「你写几万行代码自然就懂了」其实是一回事。我只是换了个赛道,踩的坑不是语法错误和内存泄漏,是 AI 的幻觉和偷懒。

经验不能跳过

Martin Fowler 担心的那个问题——新人从第一天就 on the loop,谁来培养下一代能设计 harness 的人——我觉得他担心得对,但方向可能不完全准确。

他担心的是没人写代码了、没人懂底层了。我的存在证明了另一种可能:不写代码也能积累设计 harness 的经验。但你需要积累的经验总量不会因此减少。

我花在和 AI 较劲上的时间,可能和一个初级开发者(junior developer)花在学写代码上的时间差不多。我只是把那些时间花在了不同的地方:不是学语法和数据结构,而是学 AI 的脾气和工作流设计。

所以问题可能不是「写代码的经验」能不能被替代。而是:不管你积累的是什么经验,足够多的经验本身就是设计 harness 的前提。

没有捷径,换了个赛道而已。

CLAUDE.md 体系现在长什么样

如果你好奇我现在的 harness 长什么样,大致结构是这样的:

根 CLAUDE.md 是路由器,不到8KB。知道我是谁、我的风格偏好、项目结构,根据任务类型指向对应的子 CLAUDE.md。

子 CLAUDE.md 分散在各工作区。公众号写作有自己的完整流程(选题→调研→写作→审校→配图→发布),视频创作有自己的流程(字幕下载→内容分析→脚本→审校),iOS 开发有自己的架构规范。互不干扰。

共享规则文件放在写作参考目录,跨工作区复用。降 AI 味的审校规则、配图流程、信息搜索规范,这些是所有工作区通用的。

100多个 skills 覆盖了从调研、写作、配图、审校、飞书同步、视频分析到 PDF 生成的全流程。每个 skill 是独立的能力包,需要时加载,不需要时不占上下文。

记忆系统维护长期记忆:我的身份信息、当前项目、deadline、模型版本速查。每次新对话自动加载核心记忆,不需要重新解释自己是谁。

这整套系统不是某一天坐下来设计的。它是从一个空文件开始,在过去一年多里一点一点长出来的。

写给零基础的你

如果你也是零代码经验,或者代码经验很少,看前面几章可能会有点焦虑:Mitchell Hashimoto 做了 Terraform,Kent Beck 发明了 TDD,这些人的积累我哪有。

我的建议是:别想那么多,先打开一个空的 CLAUDE.md。

什么都不用写。等 AI 犯了第一个让你烦的错,写进去。犯了第二个,再写。三个月后回头看那个文件,它已经变成了一个只属于你的 harness。高度定制,因为全是你的场景、你的痛点、你的工作方式。

没有人的 harness 是设计出来的。好的 harness 都是在和 AI 反复较劲中长出来的。

你需要的不是编程经验。是耐心和时间。耐心忍受 AI 的笨,时间积累和 AI 较劲的直觉。

也许 Martin Fowler 真正该担心的不是「没人写代码了」,而是「没人愿意花够多时间踩够多坑了」。

这个我也不确定。但我知道的是,我踩了够多的坑。你也可以。

花叔说

我把自己写进这本书里,主要是想证明一件事:零代码经验也能建 harness。

但「零代码经验」不等于「零经验」。我和 AI 较劲的上千小时积累下来的是另一种东西——知道它什么时候偷懒、什么时候幻觉、什么时候需要硬约束。这些直觉不来自写代码,但一样来自踩坑。

所以如果你也没写过代码,别觉得 harness engineering 离你很远。它需要的不是语法知识,是观察力和耐心。耐心忍受 AI 的笨,观察它的行为模式,被搞烦了就加一条规则——这些任何人都能做,只要你愿意花时间。

Mitchell Hashimoto 花了30年理解系统才建起他的 harness,Kent Beck 用了 TDD 的30年智慧。但我只用了一年多。赛道不一样,时间长短也不一样,但纪律是共通的。

返回目录 ↑

§13 从空白开始:你的第一个Harness

From Scratch: Your First Harness

别想着一步到位。一个空文件、一个犯错的 agent、一条新规则。三个月后回头看,那个文件就是你的 harness。

第一天的 CLAUDE.md 长什么样

不管你用哪个 AI 编程工具,harness 的起点都一样:一个空的指令文件。

区别只是文件名和位置。Claude Code 是项目根目录的 CLAUDE.md,Codex CLI 是 AGENTS.md,Cursor 是 .cursor/rules/ 目录下的 .mdc 文件。关于这三种工具在指令层面的完整对比和深入设计原则,详见§14。

这里只给一个最小起步动作:

touch CLAUDE.md

文件建完了,往里写什么?

什么都不写。

这不是偷懒,这是纪律。如§07所述,Mitchell Hashimoto 的核心方法论就一句话:agent 犯错才加规则,别预设。他的 Ghostty AGENTS.md 每一行都对应 agent 过去犯过的一次错,文件是活的,一直在长。

我自己的 CLAUDE.md 也是这么长出来的。被 AI 搞烦了就加一条,规则太多了就砍一轮。没人教过我该怎么写,它自己长出来的。

一个具体的演练

假设你刚接手一个 React 项目。从空文件开始,看看前10条规则会是什么:

1

agent 把测试跑错了

你发现 agent 用 npm test 跑测试,但项目用的是 Vitest。加第一条规则:

# 测试
- 运行测试:`pnpm vitest run`
- 单个文件测试:`pnpm vitest run src/path/to/test.ts`
2

agent 用了错误的包管理器

agent 用 npm 安装了一个包,package-lock.json 和 pnpm-lock.yaml 冲突了。加一条:

# 包管理
- 只用 pnpm,禁止 npm 和 yarn
- 安装依赖:`pnpm add `
3

agent 不知道项目结构

agent 把组件放到了错误的目录。你加一段地图:

# 项目结构
- src/components/ — 共享UI组件
- src/features/ — 按功能模块组织的业务代码
- src/lib/ — 工具函数和第三方封装
- src/api/ — API请求层,不要把请求逻辑写在组件里
4

agent 用了 TypeScript enum

你团队的规范是用 union type 代替 enum。加一条风格规则:

# 代码风格
- 不要使用 TypeScript enum,用 literal union type 代替
  ❌ enum Status { Active, Inactive }
  ✅ type Status = 'active' | 'inactive'
5

agent 直接 push 到 main

agent 做完改动直接推到主分支。加分支规范:

# Git规范
- 永远不要直接push到 main 分支
- 创建 feature/ 分支,提PR后合并
- commit message用英文,格式:type(scope): description
6

agent 生成了巨大的组件

一个组件500行,可读性极差。加架构约束:

# 架构原则
- 单个组件文件不超过200行
- 超过150行时考虑拆分为子组件
- 业务逻辑用自定义hook抽离,组件只做渲染
7

agent 引入了不需要的依赖

为了一个简单功能装了一个庞大的库。加依赖原则:

# 依赖管理
- 添加新依赖前先确认现有依赖能否实现
- 优先用原生API和项目已有的库
- date-fns 已安装,不要引入 moment 或 dayjs
8

agent 不跑 lint 就提交

# 提交前检查
- 提交前必须运行:`pnpm lint && pnpm type-check`
- lint错误必须修复,不允许 // eslint-disable
9

agent 的错误处理太简陋

到处是空的catch块和console.log。加错误处理规范:

# 错误处理
- 不允许空的 catch 块
- API错误统一用 src/lib/error.ts 中的 AppError 类
- 用户可见的错误需要友好提示,不要暴露技术细节
10

agent 写的 API 调用散落各处

# API层
- 所有API请求通过 src/api/ 下的模块发起
- 使用项目封装的 apiClient(src/lib/api-client.ts)
- 不要在组件中直接调用 fetch

10条规则,没有一条是凭空想出来的。每一条背后都是一个具体的问题。这就是犯错驱动的 harness。

起步长度20到50行就够,不用纠结行数。成熟版本保持100行以内即可(这是 Boris 的经验,详见§08的 CLAUDE.md 哲学)。

三条启动建议

不想从零慢慢长?想要一个起步框架?三条就够。

建议一:给地图不给说明书。指令文件应该像地图:项目结构、文件关系、关键约束。不要把每步都写死。AI 需要方向感,不需要僵化步骤。这是 OpenAI 在§06总结的原则:AGENTS.md 约100行,只是目录和指针。
建议二:每次犯错加一条规则。空文件开始,agent 犯一个错就加一条。不要预设,不要猜测。三个月后那个文件就是你的 harness——高度定制,全是你场景里真实出过的问题。
建议三:让 AI 查 AI。这是 Anthropic 的 Evaluator 思路(§08详述)。别让 AI 自己查自己。最简单的做法:写完后开一个新对话,把结果贴进去说「找出所有问题」。你会惊讶第二个 AI 能发现多少第一个漏掉的。

选你正在用的工具,创建对应的空文件,开始干活。agent 犯错了就加一条。

这就是你的第一个 harness。下一章我们继续往深里走——怎么把这个文件设计得更好。

返回目录 ↑

§14 指令层:给AI一张地图

The Instruction Layer: Give AI a Map, Not a Manual

CLAUDE.md、AGENTS.md、.cursor/rules/,本质上是同一件事。但怎么写,差别很大。

三工具指令系统对比

§13讲了怎么起步。这一章我们往深里走:怎么把指令文件设计得经得起项目长大。先放一张横向对比表,三个主流工具各有哲学。

维度Claude CodeCodex CLICursor
文件名/位置CLAUDE.md
项目根目录
AGENTS.md
项目根目录
.cursor/rules/*.mdc
子目录
文件格式纯Markdown纯MarkdownMDC(Markdown + YAML 文件头 frontmatter)
层级数3(全局/项目/子目录)多层(override / agents / team_guide / fallback 回退)2(全局/项目)
加载机制每次会话自动加载启动时逐层遍历,近处覆盖远处按激活条件(alwaysApply/glob/@mention/AI判断)
文件模式作用域(Glob Scoping)否(靠子目录实现)否是(frontmatter 中的 globs)
团队共享是(提交进git)是(提交进git)是(提交进git)
导入其他文件@path/to/file无无
跨工具兼容否Windsurf 2026自动兼容否

三种哲学,对应三种项目形态:

  • Claude Code 的三层继承适合个人/团队有强共享偏好的场景——全局层放通用规则(比如用 pnpm),项目层放架构约束,子目录层放模块特定规则。加载顺序全局→项目→子目录,后加载优先级更高。
  • Codex CLI 的多层叠加适合大仓库、多团队共同维护——每层检查 AGENTS.override.md → AGENTS.md → 回退(fallback)文件名,合并策略是从根到叶拼接。
  • Cursor 的文件模式作用域(glob scoping)适合单个大项目里多种代码风格并存——编辑 API 代码时只加载 API 规范,编辑组件时只加载组件规范。

路由器模式:适合同时管多种工作

Claude Code 的三层继承有一个精巧的用法:根目录 CLAUDE.md 只做路由,不写任何具体规则。

这是我在实践中长出来的模式。根目录的 CLAUDE.md 只干一件事:判断当前任务属于哪个工作区,然后指向对应的子目录 CLAUDE.md。

# 工作区路由

收到任务后,先判断工作区,读取对应CLAUDE.md:

| 关键词 | 工作区 | 读取文件 |
|--------|--------|----------|
| 写文章、公众号 | 公众号写作 | /01-公众号写作/CLAUDE.md |
| 小红书、笔记 | 小红书写作 | /02-小红书写作/CLAUDE.md |
| 视频脚本 | 视频创作 | /03-视频创作/CLAUDE.md |
| 代码、Demo | 实验项目 | /09-实验项目/ |

任务模糊 → 询问确认
涉及多工作区 → 依次读取

具体的执行规则全在子目录里。根文件保持精简,不超过200行。

什么项目适合路由器模式?同时管多种完全不同类型的工作。我的写作目录下有公众号、小红书、视频、iOS App,每种工作的规则几乎不重叠。平铺在一个文件里,每次加载都带着一堆无关规则。

什么项目不适合?单一主题的项目。一个 Rust 库就别搞路由器了,直接一个 CLAUDE.md 到底,反而省事。

为什么这么做?Boris Cherny 说得直接:

Boris Cherny:"Bloated CLAUDE.md files cause Claude to ignore your actual instructions!"
臃肿的 CLAUDE.md 会让 Claude 忽略你真正的指令。

上下文是稀缺资源。指令文件占用的空间越多,留给实际任务的空间就越少。路由器模式确保每次只加载相关的规则。

AGENTS.md:目录指针模式

OpenAI 的 Codex 团队走了另一条路,更极端一些。

他们的 AGENTS.md 只有大约100行,充当目录和指针,指向 docs/ 下的详细文档:

# AGENTS.md

## 项目概览
这是一个 [项目名],技术栈:React + FastAPI + PostgreSQL

## 核心命令
- 启动开发服务器:`pnpm dev`
- 运行测试:`pnpm test`
- 类型检查:`pnpm type-check`

## 架构指南
→ 详见 docs/ARCHITECTURE.md(~200行,代码库地图)

## 设计决策
→ 详见 docs/design-docs/(核心架构决策记录)

## 活跃任务
→ 详见 docs/exec-plans/(当前Sprint和技术债)

## 产品规格
→ 详见 docs/product-specs/(功能规格,带导航索引)

## 依赖层级(强制执行)
Types → Config → Repo → Service → Runtime → UI
每个业务领域内代码只能沿固定方向依赖。违反者会被CI拦截。

OpenAI的文档结构很清晰:

AGENTS.md # ~100行,目录+指针
ARCHITECTURE.md # ~200行,代码库地图
docs/
├── design-docs/ # 核心架构决策
├── exec-plans/ # 活跃任务和技术债
├── product-specs/ # 功能规格说明
├── references/ # 设计系统文档
└── decisions/ # 架构决策记录(Architecture Decision Records)

OpenAI 团队试过一个超大的 AGENTS.md,效果很差。全面的指令文件会挤占任务上下文和相关代码的空间。agent 在小而稳定的入口加上指向专业化知识的结构中表现更好。

Glob Scoping 的实战用法

Cursor 的文件模式作用域(glob scoping)是三个工具中最细粒度的方案。同一个项目里,编辑不同类型的文件加载不同规则。

# .cursor/rules/api-layer.mdc
---
description: API层编码规范
globs: src/api/**/*.ts
alwaysApply: false
---
# API层规范

- 所有API函数必须有返回类型注解
- 错误处理使用项目统一的 AppError 类
- 请求参数和响应类型定义在同文件顶部
- 不要在API层做业务逻辑判断
# .cursor/rules/components.mdc
---
description: React组件规范
globs: src/components/**/*.tsx
alwaysApply: false
---
# 组件规范

- 使用函数组件 + hooks,不用class组件
- Props类型定义用 interface,不用 type
- 单文件不超过200行
- 样式用 Tailwind,不用 CSS Modules

规则的四种激活模式:

模式说明适合
alwaysApply: true每次会话自动加载通用规范、项目结构
glob 匹配文件在上下文中时激活模块特定规则(API/组件/数据库层)
手动 @提及(@mention)用户显式触发偶尔需要的特殊规则(发布流程、迁移指南)
AI 判断根据 description 自动决策情境相关的规范(性能优化、安全审查)

实战上最有用的组合是:alwaysApply + glob 匹配。alwaysApply 放项目级的硬约束(依赖规则、禁用模式),glob 匹配放模块级的风格规则。手动 @mention 和 AI 判断谨慎用,前者容易忘,后者不稳定。

趋同:指令文件正在变成同一个东西

CLAUDE.md、AGENTS.md、.cursorrules、.windsurfrules、copilot-instructions.md、GEMINI.md、.clinerules、CONVENTIONS.md。

名字不同,本质上是同一件事:用 Markdown 文件告诉 AI 项目规则。

趋势已经不只是「发生」了,已经开始标准化。2026年3月,AGENTS.md 被纳入 Linux 基金会旗下的 Agentic AI Foundation 管理,背后推动者包括 Sourcegraph、OpenAI、Google、Cursor 和 Factory。这意味着 AGENTS.md 正在从一家公司的格式变成行业标准。

Windsurf 从2026年初开始自动识别 AGENTS.md,同一个仓库的规则可以同时被 Windsurf 和 Codex CLI 读取。GitHub Copilot 的 .instructions.md 格式也越来越像 AGENTS.md。Google 的 Gemini 推出了自己的 GEMINI.md。

统一标准不再是「可能」,而是「什么时候」的问题。但现在不必等。你写的任何一种指令文件,80%的内容在不同工具间是通用的:项目结构、编码规范、测试命令、架构约束。这些不绑定特定工具。

写好指令文件的三个原则

原则一:方向感而非僵化步骤

好的指令文件像地图,不像说明书。告诉 AI 项目的地形、重要路标、禁区在哪。别把每一步都写死。

僵化步骤:

创建组件时:
1. 先在 src/components/ 创建文件夹
2. 创建 index.tsx
3. 创建 types.ts
4. 创建 styles.module.css
5. 在 index.tsx 中导入 styles
6. 导出 default

方向感:

## 组件规范
- 共享组件放 src/components/
- 样式用 Tailwind,不用 CSS Modules
- 单文件 <200行,超过就拆
- Props用 interface 定义

僵化步骤看着全面,但 agent 遇到不完全匹配的情况就会卡住。方向感让 agent 保留判断空间,同时不跑偏。

如§06所述,OpenAI 的 AGENTS.md 只有约100行,给地图不给说明书。道理在所有工具上通用。

原则二:护栏优先于手册

与其告诉 agent 你应该这么做,不如告诉它你不能这么做。

OpenAI 的架构不变量(architectural invariants)用了一个反直觉但有效的表达方式:声明这里不存在什么。

# 架构不变量
- 这个项目不使用 ORM,所有数据库操作用原始SQL
- UI层不直接访问数据库,必须通过 Service 层
- 不存在全局状态管理库,用 React Context + hooks
- 没有任何微服务通信,这是单体应用

告诉 agent 不存在什么,比告诉它存在什么更能约束解空间。约束反而提升生产力。

原则三:犯错 → 记录 → 迭代的飞轮

Boris 的100行哲学(§08)讲的就是这件事:只记录 agent 真正犯过的错。如§07所述,Mitchell 的核心方法论同样是 agent 犯错才加规则。两位代表人物殊途同归。

团队在 PR 中用 @.claude 标签来更新 CLAUDE.md。每次纠正 agent 的行为,就在 CLAUDE.md 里加一条。日积月累,这个文件变成了团队的制度知识。

对每一行都问自己一个问题:删掉它会导致 agent 犯错吗?如果不会,就删掉。这是保持指令文件精简的最佳判断标准。

应该写什么,不应该写什么

应该写不应该写
agent 猜不到的命令(如 pnpm vitest run)agent 读代码就能发现的(如使用 React)
与默认不同的代码风格规则标准语言惯例
测试指令和首选测试运行器详细的 API 文档(链接即可)
分支命名、PR 惯例频繁变化的信息
项目特定的架构决策教程和长篇解释
常见陷阱和非显而易见的行为「写干净代码」之类不言自明的原则

好的指令文件,读起来像资深同事在你入职第一天给你的备忘录:关键信息、常见坑、谁负责什么。不是培训手册,是生存指南。

返回目录 ↑

§15 约束层:建议和约束是两回事

The Constraint Layer: Suggestions vs. Enforcement

在指令文件里写「请不要 push 到 main」是建议。用 hooks 在程序层面拦住它,是约束。这个区别是 harness 从 art 到 engineering 的转折点。

一个根本性的区分

你在 CLAUDE.md 里写了一行:

- 永远不要直接push到 main 分支

这是一条建议。Claude 大概率会遵守,但没有什么保证它一定遵守。上下文太长、任务太复杂、模型偶尔抽风,规则就可能被忽略。

现在换一种方式。你在 Claude Code 的 hooks 配置里写:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git push*main*)",
        "handler": {
          "type": "shell",
          "command": "echo 'DENY: 禁止直接push到main分支'"
        }
      }
    ]
  }
}

这是一条约束。不管 Claude 怎么想、上下文多混乱,push 到 main 的命令在执行前就会被拦截。程序级的,确定性的,不可绕过的。

Anthropic 的官方文档说得很清楚:

Anthropic官方:"Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens."
CLAUDE.md 的指令是建议性的,hooks 是确定性的,保证动作一定执行。

建议和约束,完全两回事。这个区别,是 harness 从 art 到 engineering 的转折点。

Claude Code 的 Hooks 系统

Hooks 是 Claude Code 的杀手锏。截至2026年4月(v2.1.90),它支持二十多种生命周期事件,七个最常用:

事件触发时机核心能力
PreToolUse工具调用前可以 deny 操作——安全策略的核心执行点;支持延迟(defer)决策(无人值守/headless 会话暂停恢复)
PostToolUse工具调用后审计、日志、自动格式化
SessionStart会话启动时动态加载上下文、环境初始化
Stopagent停止时确定性完成检查
PermissionRequest请求权限时自动化审批、路由到Slack等
PermissionDenied自动模式拒绝后记录被拒绝的操作、触发替代方案
PostCompact上下文压缩后响应压缩事件

最关键的是PreToolUse。它可以返回 deny(拒绝)信号,从程序层面阻止 Claude 执行某个操作。在所有 AI 编程工具中独一份。

四个实用的hooks示例

示例一:编辑文件后自动跑 lint

每次 Claude 编辑了文件,自动运行 ESLint 检查。不合格的话 Claude 会看到错误输出,自动修复。

// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "handler": {
          "type": "shell",
          "command": "npx eslint --fix \"$CLAUDE_TOOL_ARG_file_path\" 2>&1 || true"
        }
      }
    ]
  }
}

示例二:禁止修改关键配置文件

保护生产环境配置不被 agent 意外修改。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit(.env*)|Edit(*.production.*)",
        "handler": {
          "type": "shell",
          "command": "echo 'DENY: 生产环境配置文件受保护,不允许直接修改'"
        }
      }
    ]
  }
}

示例三:生成代码后自动做类型检查

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit(*.ts)|Edit(*.tsx)",
        "handler": {
          "type": "shell",
          "command": "npx tsc --noEmit 2>&1 | head -20"
        }
      }
    ]
  }
}

TypeScript 文件被修改后立即做类型检查。Claude 能看到类型错误并自主修复,不需要你提醒。

示例四:提交前必须通过测试

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git commit*)",
        "handler": {
          "type": "shell",
          "command": "pnpm test --run 2>&1 || echo 'DENY: 测试未通过,禁止提交'"
        }
      }
    ]
  }
}

一个有意思的细节:你可以让 Claude 自己写 hooks。对 Claude 说 Write a hook that runs eslint after every file edit,它就帮你配好了。agent 给自己套上约束。

OpenAI 的硬约束:机械化强制执行

Codex CLI 没有 hooks,但 OpenAI 团队用了另一套硬约束体系。他们的核心哲学:

OpenAI:"If you can articulate what it is about the code you don't like, the next step is to write that down."
如果你能说清楚代码哪里不好,下一步就是把它写成规则。

具体做法分三层:

第一层:依赖层架构

OpenAI 把依赖层架构(详见§06的 Types → Config → Repo → Service → Runtime → UI)作为 agent 时代的早期前提。跨领域关注点(认证、遥测、功能开关/Feature Flags)通过唯一显式接口(接入点/Providers)进入。

这层约束的关键洞察:有 agent 写代码之后,架构约束必须前置。agent 不会自觉维护一致性,只有约束能做到。

第二层:自定义 linter

OpenAI 让 Codex 自己生成了一套自定义 ESLint 规则和结构测试(structural test),专门检测违反层级边界的代码。linter 在 CI 中运行,违规的 PR 直接被阻断,合不进去。

错误信息不只说这里违规了,还带修复指导和文档链接。agent 看到错误信息后能自主修复,不需要人工介入。

第三层:CI 强制

所有上述检查都在 CI 中执行。不是建议,不是提醒,是物理上合不进主分支。

Codex 的 Sandbox:物理隔离

Codex CLI 有另一种硬约束思路:sandbox(沙箱)。

模式文件访问网络
workspace-write(默认)仅工作区可写关闭
danger-full-access全盘可写开放

默认模式下,agent 只能读写工作目录内的文件,网络访问完全关闭。.git/ 和 .codex/ 始终受保护,即使在 full-access 模式下。

最简单粗暴的约束:agent 做不了的事就是做不了。不是通过规则告诉它不要做,是在环境层面让它没法做。

约束谱系:从软到硬

把所有约束手段排列出来,你会发现一个从软到硬的谱系:

提示建议
→
规则文件
→
Hooks
→
Linter
→
CI
→
Sandbox
约束类型性质执行者可绕过工具支持
对话中的口头提醒即时的,一次性用户是所有工具
CLAUDE.md / AGENTS.md 规则持久的,建议性模型遵循是所有工具
Hooks(PreToolUse deny)持久的,强制性程序执行否Claude Code
自定义 Linter持久的,强制性静态分析否所有(自建)
CI 阻断持久的,强制性CI 系统否所有(自建)
Sandbox 隔离持久的,物理性操作系统否Codex CLI

越往右,约束越硬。越硬的约束越可靠,但也越不灵活。

好的 harness 是这些层次的组合。不是全用最硬的,也不是全用最软的。大多数规则用指令文件就够了,少数关键的安全线用 hooks 或 CI 守住。

建议 vs 约束的对比

建议(指令文件)

写在 CLAUDE.md 里:「请不要删除数据库迁移文件」

大概率被遵守,但不保证。上下文太长、任务太复杂时可能被忽略。适合编码规范、风格偏好、架构指引。

约束(Hooks / CI / Sandbox)

PreToolUse hook 拦截对 migrations/ 目录的删除操作。

100%可靠,不受上下文影响。适合安全红线、生产环境保护、不可逆操作拦截。

怎么判断一条规则该是建议还是约束?问自己:agent 违反了这条规则,后果是什么?

代码风格不一致?恼人但不致命,建议就行。删掉了生产数据库?灾难性后果,必须约束。推到了 main 分支?可以 revert 但很麻烦,约束。变量命名不对?审查时改就行,建议。

约束保护的是底线,不是偏好。

约束是转折点

调研这些工具的过程中,我发现一个清晰的分界线:只有 Claude Code 和 Codex CLI 提供了程序级的硬约束。Cursor、Windsurf、GitHub Copilot、Aider 都只有提示级的规则。

具体区别:

  • Claude Code 的 hooks 是可编程的——你可以写任意逻辑决定 approve 或 deny
  • Codex CLI 的 sandbox 是策略式的——选择一个预设级别,不支持自定义逻辑
  • 其他工具的规则是建议性的——AI「应该」遵守但「可以」违反

Cline 走了第三条路:用计划/执行(Plan/Act)双模式实现「社会性约束」。Plan 模式只分析不修改,Act 模式每步都要人工审批。不是技术上阻止 agent,而是流程上确保人工确认。

三种约束思路各有适用场景。但约束的存在本身,才是 harness 从一堆配置文件升级为工程系统的分水岭。

Martin Fowler 团队的分析也指向同一个结论:

Birgitta Boeckeler(ThoughtWorks):提高 agent 的信任度和可靠性,需要的恰恰是限制它的解空间。约束越多,反而越可信。

跟人类组织里的道理一样。没有规则的团队不是自由,是混乱。有清晰边界的团队,成员反而能在边界内放手干。

AI agent 也是一样。你给它越清晰的约束,它在约束内的发挥就越好。Harness 不限制 AI 的力量,harness 让 AI 的力量变得可信。

返回目录 ↑

§16 反馈层与记忆层

Feedback Layer and Memory Layer

前面讲了指令和约束,这两层管的是「AI 出手前要守什么规矩」。这一章讲反馈和记忆——「AI 出手后怎么知道自己做得对不对」和「下次怎么不再犯同样的错」。这两层合起来就是 agent 的复盘能力。

反馈层:让 AI 查 AI

AI 最大的问题不是写错代码,是以为自己写对了。

LangChain 在 Terminal Bench 2.0 的测试中发现(§10详述),agent 最常见的失败模式是:写完方案后重新读自己的代码,觉得看起来没问题就停了。没运行测试,没验证边界情况。

模型对自己的第一个可行方案有天然偏好。它不是不会做得更好,是太容易满足于「看起来可以」。

解法不是换更聪明的模型,是给它另一双眼睛。

GAN 的直觉

Anthropic 对这个问题的回应最彻底。他们搭的三 agent 架构(§08详述)灵感来自生成对抗网络(GAN):

规划者把简单指令扩展为详细规格,生成者按 Sprint 一次做一个功能,评估者用 Playwright 与运行中的应用交互,像真人 QA 工程师一样测试。

为什么不让生成者自己检查自己?Anthropic 的原话是:

工程化一个严厉的独立评估者,远比教一个生成者自我批判容易得多。分离角色创造了对抗性动态,怀疑论的 Evaluator 提供批判性反馈,帮助 Generator 突破瓶颈。

谁都不擅长批评自己,AI 也一样。原始的 Claude 模型当评估者表现很差,太宽容,容易说服自己 bug 不严重。换一个独立的、专门挑刺的评估者,效果完全不同。

给 Evaluator 装上眼睛

Evaluator 不是一个会说「这个看起来不错」的 AI。它必须能真的验证。

Anthropic 用 Playwright MCP 让 Evaluator 操作真实应用:打开页面、点按钮、填表单、看数据是否按预期更新。像人类 QA 一样,不是读代码,是用代码。

OpenAI 走了类似的路(§06详述)。他们把 Codex agent 连上了 Chrome DevTools Protocol,每次改完代码自己启动应用实例,比对修改前后的截图和日志。「启动时间低于800ms」从文档里的愿望,变成了 agent 可以自己验证的硬指标。

更进一步的是可观测性基础设施。每个 git worktree 配套一个临时的 Victoria Logs + Victoria Metrics 栈,agent 可以直接用 LogQL 查日志、用 PromQL 查指标。

共通的原则是:agent 看不到的等于不存在。反馈层的核心设计问题不是「要不要让 AI 审代码」,而是「怎么让 AI 看到真实发生了什么」。

反馈层的最小起步:开新对话查代码

三 agent 架构听着很重,反馈层的最小起步版本非常轻。

写完一段代码后,开一个全新的对话,把代码贴进去说:「找出所有问题。」

全新上下文的 AI 对你刚写的代码没有感情包袱,能发现很多第一个 AI 漏掉的问题。Boris Cherny 的原话:给 Claude 一种验证自己工作的手段,如果 Claude 有反馈循环,最终结果质量能提升2到3倍。

这就是§17会展开的「穷人版 Planner/Generator/Evaluator」。三个会话窗口就够了。

记忆层:让错误不再重犯

反馈层解决的是「这次做对了没」,记忆层解决的是「下次怎么不再犯」。

Agent 没有记忆就是金鱼。每次对话重新开始,同样的错犯两遍三遍。

2026年初,AI 编程工具的记忆能力差距巨大。大部分还停留在静态文件阶段。

工具自动记忆手动记忆跨会话持久化
Claude Codeauto-memory(自动记忆,自动保存观察)MEMORY.md + CLAUDE.md是
WindsurfCascade Memories(级联记忆,自动生成)Rules是
ClineMemory Bank MCP(需配置).clinerules是
Codex CLI无AGENTS.md静态文件
Cursor无.cursor/rules/静态文件
GitHub Copilot无instructions.md静态文件
Aider无CONVENTIONS.md静态文件

只有三个工具有动态记忆,其余全靠人工维护指令文件。记忆系统分三个层次:AI 自己决定什么值得记,通过工具调用显式管理,靠人手动更新文件。差距一眼就看出来了。

Claude Code 的 Memory 系统

Claude Code 有三套记忆机制互补。

auto-memory:Claude 自动将有用的观察保存到 ~/.claude/projects/<hash>/memory/。不需要你说记住这个,它自己判断什么值得留下。

MEMORY.md:用户手动维护的长期记忆。我的 MEMORY.md 记了工具偏好、项目背景、常犯的错、发布流程。每隔一段时间精简一轮,保持在100行以内。

CLAUDE.md 本身:项目级记忆。Boris Cherny 团队在 PR 中用 @.claude 标签来更新 CLAUDE.md。每一条新增的规则,都是 agent 过去犯过的错的制度化记录。他管这叫复利工程。

标志案例:Claude 玩 Pokemon

Anthropic 还发布了记忆(memory)工具公开测试版,让 agent 能在上下文窗口之外维护知识。最经典的例子是 Claude 玩 Pokemon。

Claude 在连续玩 Pokemon 多个小时的过程中,维护了一份精确的步骤计数笔记:「过去1,234步我一直在 Route 1 训练宝可梦。」上下文重置后,Claude 读取自己的笔记继续,无缝接上之前的训练序列。

没有这份笔记,上下文一重置,角色在哪、做了什么、下一步目标是什么,全归零。有了笔记,agent 相当于有了一本外挂工作日志。长任务里这种能力至关重要。

这个思路不只适用于游戏。写代码时的当前分支状态、已完成的功能、待处理的 bug 清单,都可以是笔记。笔记是结构化的、可查询的、可持久化的。它不占上下文,但 agent 需要时能随时读。

知识库管理

记忆解决的是「agent 记住什么」,知识库解决的是「agent 在哪找专业知识」。

以我的写作项目为例,知识库按主题分类:

_knowledge_base/
├── INDEX.md
├── 技术工具/
├── 行业人物/
├── 产品发布/
├── 报告资料/
└── 方法论/

每次调研完一个主题,成果保存到对应分类,附来源 URL 和日期。agent 写文章时自动检索相关文件。知识库不是堆资料,是给 agent 准备一张随时能查的索引。

OpenAI Codex 团队更激进(§06详述):创建了叫 ExecPlan 的自包含设计文档,把 Google Docs 里的规划文档迁入代码仓库,Slack 里的决策转为 markdown 存入 repo。仓库必须是唯一的真相来源。

上下文管理:不是越多越好

记忆和知识库都在往上下文里塞东西。但上下文窗口有物理极限。

Anthropic 发现了一个叫上下文腐烂(context rot)的现象:上下文 token 越多,模型准确回忆信息的能力越差。约100万 token 处有明显的性能天花板,超过这个点性能显著下降,不管技术上支持多大的上下文窗口。

面对上下文限制,有三种应对策略:

策略机制适用场景
压缩(Compaction)总结早期对话,在缩短的历史上继续连续性重要的长任务
上下文重置(Context Reset)完全清空窗口,用结构化交接状态启动新会话上下文焦虑严重时
开新会话任务切换时直接开新对话不相关任务之间

Claude Code 官方文档给了一个直觉判断:如果修正 Claude 超过两次还是错,清空重来比继续修正好。上下文被失败方案污染后,在上面继续修只会越修越歪。

能力层补充:Skills 和 MCP

这两层其实可以单独成章,但它们和反馈、记忆的关系更像是「工具」——给反馈层和记忆层提供能力扩展。

Skills 是 Claude Code 独有的无代码扩展方式。Skills 放在 .claude/skills/ 目录下,每个是一个 .md 文件,描述能力做什么、什么时候触发。平时不占上下文,Claude 根据当前任务自动判断要不要加载。写一个 .md 文件就能定义新能力,不需要 SDK。

MCP(Model Context Protocol)让 agent 连接外部世界。Claude Code、Cline、Windsurf 已经原生支持。Block 的 Goose 通过 MCP 连接3000+服务(§09详述)。

工具设计的核心原则是 Anthropic 提出的 Agent-Computer Interface(ACI):工具命名让 AI 理解意图,参数描述清晰,一个工具做一件事,错误信息告诉 agent 哪里出了问题。

LangChain 的 LLMToolSelectorMiddleware(§10详述)做了一个巧妙的优化:用一个快速 LLM 预筛选当前任务需要的工具,避免把所有工具描述都塞进上下文。工具多了之后,选择本身也需要被工程化。

两层合起来:agent的复盘能力

反馈层回答「这次对不对」,记忆层回答「下次怎么更好」。两层合起来,就是 agent 的复盘能力。

人类工程师在几十年的经验积累里学会了一件事:犯错不可怕,不复盘才可怕。每次线上事故后写 postmortem,每次项目结束后做 retrospective。知识就是在这些复盘里沉淀下来的。

Agent 也一样。反馈层让它当场知道错在哪,记忆层让它把「错在哪」变成持久化的教训。有了这两层,agent 才从「每次都是新人」变成「会成长的协作者」。

能力层和记忆层的对比总览

最后放一张横向对比表,看看不同工具在这两层的覆盖情况。

维度Claude CodeCodex CLICursorWindsurfGitHub Copilot
能力扩展Skills + MCP + Hooks桌面App + GPT-5.3Background Agents + BugBotMCP智能体模式(Agent Mode)+ 扩展(Extensions)
无代码扩展Skills(纯.md文件)无无无无
动态记忆auto-memory无无Cascade Memories无
跨会话三套互补静态文件静态文件工作区绑定静态文件
反馈能力Hooks + Playwright MCPChrome DevToolsComposer审查内置Agent模式自验

能力层的趋势是 MCP 标准化。记忆层和反馈层还在各自为战。这几层未来一年会快速拉齐——没有记忆和反馈的 agent 实在太痛了。

返回目录 ↑

§17 编排层:让十匹马同时跑

Orchestration: Running Ten Horses at Once

一个 agent 解决不了的问题,十个 agent 未必能解决。但如果编排对了,十个 agent 能做到一个 agent 永远做不到的事。这一节聊什么时候该用多智能体(multi-Agent),以及怎么用。

从一匹马到一支马队

前面所有章节聊的都是单个 agent 的 harness。但真实项目里,很多任务一个 agent 搞不定。

不是因为它不够聪明。上下文窗口是物理极限。一个 agent 同时处理前端、后端、数据库、测试、文档,上下文填满之后性能断崖式下降。Anthropic 的数据说得很清楚:约100万 token 就是天花板。

所以你需要多个 agent,每个 agent 有自己的上下文窗口,处理自己擅长的那一块。问题是:谁来协调它们?

Boris 的10-15并发会话

最朴素的编排方式:人来当编排器。

Boris Cherny(Claude Code 的创建者)日常保持10-15个并发 Claude Code 会话。5个在终端,编号1-5,用 shell 别名(za、zb、zc)快速切换。5到10个在浏览器。还有早上启动、后续查看的移动会话。

每个会话跑在独立的 git worktree 上,代码不冲突。部分工程师保留一个专用的「分析」worktree,只用于日志和查询,不写代码。

这不是什么高级架构,就是拿人当编排器。但 Boris 说这是他团队内部 the single biggest productivity unlock(最大的生产力解锁)。

操作方式:

1

创建多个 worktree

每个任务一个独立的工作目录,代码完全隔离。

2

每个 worktree 启动一个 Claude Code 会话

终端编号方便切换,关键会话开 OS 通知。

3

任务分配

每个会话处理一个独立模块或功能,互不干扰。

4

人工协调

你在会话之间切换,审查结果,解决冲突,合并代码。

好处是完全可控。坏处是你得一直盯着,任务之间的依赖关系只存在于你脑子里。

Anthropic 的三智能体架构

不想拿人当编排器呢?Anthropic 给了一个参考答案。

如§08所述的三智能体架构,用 Planner / Generator / Evaluator 三个角色流水线协作:

Planner
1-4句提示 → 完整产品规格
→
Generator
按 Sprint 增量实现功能
→
Evaluator
用 Playwright 端到端测试

灵感来自生成对抗网络(GAN),核心洞察是「工程化一个严厉的独立评估者,远比教一个生成者自我批判容易得多」。Anthropic 的 $9 vs $200 实验(§08详述)证明三 agent 不是可选项——贵了20倍,但单 agent 的产出核心功能不可用。不是花更多钱做得更好,是不花这个钱就做不成。

有意思的是,模型从 Sonnet 4.5 升级到 Opus 4.6 之后,Sprint 机制被完全移除了。模型原生就能处理长任务,Evaluator 从每 Sprint 评估变为全程结束后一次性评估。模型进步在简化编排。

你也可以用 Planner/Generator/Evaluator

三智能体架构看起来很重,但核心思路可以简化到日常使用。

1

Planner:用 Plan Mode 做规划

复杂任务先进 Claude Code 的 Plan Mode(Shift+Tab 两次),让 AI 制定详细实现计划。Boris 建议:一个 Claude 写计划,启动第二个 Claude 以资深工程师(staff engineer)身份审查计划。

2

Generator:切回普通模式(Normal Mode)执行

计划确认后切到自动接受模式(auto-accept mode)让 AI 写代码。事情出错时,切回 Plan Mode 重新规划,而不是硬推。

3

Evaluator:开新会话审查

写完后开一个全新对话,把结果贴进去:「找出所有问题」。全新上下文的 AI 没有对自己代码的偏见,能发现很多第一个 AI 漏掉的问题。

这就是三智能体架构的穷人版。不需要搭复杂系统,三个会话窗口就够了。

Agent Teams:Claude Code 的内置多智能体

Claude Code 的 Agent Teams 是目前唯一支持 agent 间直接通信的方案。

一个会话担任 team lead,分配任务、综合结果。Teammates 之间可以直接通信,不必通过 lead 中转。每个 agent 有独立的上下文窗口。

和 Boris 的手动模式相比,Agent Teams 的优势是自动协调。你描述一个大任务,lead 自己拆、自己分配、自己收集结果。适合并行调研、独立模块开发、竞争假设调试。

Cursor 2.0 支持最多8个 AI agent 并行运行,数量最多,但每个 agent 独立工作,没有通信机制。八匹马各跑各的,没有缰绳把它们连在一起。

Codex CLI 的 Subagents 继承父 agent 的 sandbox 策略和审批设置,运行在主 agent 的上下文内,只能向上汇报。适合探索性子任务,不适合长时间独立工作。

作者/审查者(Writer/Reviewer)并行模式

多智能体不一定要搞复杂架构。最实用的模式可能也是最简单的:一个写,一个审。

Anthropic 官方推荐的做法:一个 Claude 写代码,另一个 Claude 用全新上下文审查。避免对自己写的代码有偏见。

这个模式可以扩展。批量处理时:

for file in $(cat files.txt); do
  claude -p "Migrate $file from React to Vue. Return OK or FAIL." \
    --allowedTools "Edit,Bash(git commit *)"
done

每个文件独立处理,失败不影响其他文件。并行度取决于你愿意同时跑多少个进程。

Stripe 的流水线(Pipeline)编排

企业级编排的标杆案例是 Stripe 的 Minions 系统。

Slack消息
→
触发Minion
→
自动编码
→
自动化测试
→
PR等待review

工程师在 Slack 中发一条消息,走开,回来时 PR 已经 ready。每周超过1300个 PR,全部零人类手写代码。

关键基础设施:每个 Minion 运行在标准化的 AWS EC2 实例(devbox)上,预装 Stripe 完整代码树、预热的 Bazel 和类型检查缓存。从热启动池(warm pool)启动一个 devbox 不到10秒。

Stripe 的核心洞察:Minions 能 work 的首要原因跟 AI 模型本身几乎无关,而是 Stripe 在 LLM 出现之前就为人类工程师建设了多年的基础设施。全面的测试覆盖、合成端到端测试、蓝绿部署支持快速回滚。harness 是建在基础设施之上的,基础设施不好,harness 也搭不起来。

每个 AI 生成的 PR 仍然需要人类审查。但审查过程严重依赖自动化信心信号。人还在回路(loop)里,只是位置变了。

什么时候该用多智能体

多智能体编排很诱人,但大部分场景单 agent 就够了。Anthropic 在 Building Effective Agents 中给了一个判断标准:

能用单次 LLM 调用解决的,不要用 Agent。Agent 适合无法预测步骤数、无法硬编码固定路径的开放式问题。

同样的逻辑往上推一层:能用单 agent 解决的,不要用多 agent。

场景推荐模式理由
改个 bug、加个功能单 agent上下文足够,没有并行需求
重构一个模块单 agent + Plan Mode需要全局视角,拆开反而丢上下文
同时改5个独立模块手动多会话(Boris 模式)任务独立,不需要 agent 间通信
写代码 + 审代码Writer/Reviewer 双会话消除自我审查偏差
复杂全栈应用从零开始Planner/Generator/Evaluator任务跨越前后端,需要规划和验证
大规模迁移/批量处理流水线脚本编排任务高度重复,可并行
1000+PR/周的企业规模Stripe Minions 式平台需要专用基础设施

编排的复杂度应该匹配任务的复杂度。三个会话窗口能搞定的事,不需要搭 Agent Teams。从最简单的开始,真的需要了再升级。

返回目录 ↑

§18 经验工程:谁来设计下一代的缰绳

Experience Engineering: Who Will Design the Next Harness

这一章不给答案。

Martin Fowler 团队的 Kief Morris 画了一张图,把人在 AI 编程中的位置分成三层。

In the loop(在回路中):你逐行审查 agent 的输出,手动修改不满意的代码。人在环内,什么都过手。

On the loop(在回路上):你不看代码本身,而是构建和改进 harness。规格说明、质量检查、工作流引导。你管缰绳,不管马腿。

Out of the loop(在回路外):你只说想要什么,agent 自己搞定。Vibe coding。

Morris 说了一句话,值得停下来想想:

in the loop 和 on the loop 的区别,在你对结果不满意的时候最明显。in the loop 的人会去改代码。on the loop 的人会去改 harness,让它下次产出更好的结果。

On the loop 听起来是更好的工作方式。你不再重复劳动,而是改进系统本身。

但这里有个麻烦。

如果太早把人移到 on the loop,甚至 out of the loop,将来谁来设计 harness?

Morris 的原话是这样的:新人从第一天起就不接触代码的细节,只在高层操作 agent,那当 harness 出了问题需要有人理解底层发生了什么的时候,谁来?

Martin Fowler 在播客里把这个问题说得更尖锐:

初级开发者(junior developer)最重要的属性不是他们现在能产出什么,而是他们能成长为资深开发者(senior developer)。

如果 AI 替代了初级开发者的产出,但同时也剥夺了他们的成长路径,这不是效率提升,是在透支未来。

这个担忧不是空穴来风。Shopify 把实习生项目从25人扩大到1000人,理由是实习生用 AI 的方式更有趣。Block 以 AI 提升效率为由裁员40%。两个方向,同一个问题:中间层在消失。

Mitchell Hashimoto 能给 Ghostty 写好 harness,因为他理解终端模拟器的每个细节。那个配置文件里每一行都对应着 agent 过去犯过的一次错,而他知道那些错为什么是错。

OpenAI 那3个工程师能驾驭100万行代码产出,因为他们知道什么架构是好的、什么会在三个月后爆炸。

Kent Beck 能写出那个 TDD 驱动的 CLAUDE.md,因为他发明了极限编程,花了几十年理解什么样的代码是好代码。前两次尝试失败了,复杂度积累太多,AI 完全卡住。第三次才找到正确的介入方式。

设计好 harness 的人,都有深厚的领域经验。问题是这些经验从哪来。

我自己是个有意思的样本。

前面§12讲过我的背景:零代码经验,所有产品都是 AI 写的。我的 harness 从零开始,在和 AI 互动中一点一点长出来,没有任何编程经验可以迁移。

但我得对自己诚实。

我能设计 harness,不是因为我天生懂系统设计。是因为我在和 AI 协作的上千小时里,观察到了它的行为模式。它什么时候偷懒,什么时候幻觉,什么时候需要硬约束而不是温柔提醒。

这些判断力不来自写代码的经验,但来自另一种经验:和 AI 反复较劲的经验。

问题是,这种经验能教吗?

我说不清楚。

我知道 CLAUDE.md 该怎么写,但让我教别人为什么这么写,我会卡住。很多决定是直觉做的。直觉来自踩坑。踩坑来自大量重复。大量重复来自时间。

这和老程序员说「你写几万行代码自然就懂了」其实是一回事。

所以问题可能不是「写代码的经验」能不能被替代。

而是:不管你积累的是什么经验,足够多的经验本身就是设计 harness 的前提。没有捷径。换了个赛道而已。

以前的赛道是写代码、调 bug、重构、被线上事故搞到半夜。

现在的赛道是写 CLAUDE.md、配 hooks、被 AI 的幻觉搞到半夜。

痛苦的形状变了。痛苦的总量可能没变。

也许 Martin Fowler 担心的不是「没人写代码了」。

而是「没人愿意花够多时间踩够多坑了」。

呼应 Boris 在§08的观点:工程师的核心贡献是判断力——判断构建什么、如何验证、何时信任输出、何时反驳。

判断力从哪来?

从做了很多次之后知道哪些路走不通来。

84%的开发者已经在使用或计划使用 AI 工具。Anthropic 的报告说工程师在60%的工作中用 AI,但只能完全委派0-20%的任务。中间那40-60%是人和 AI 协作的地带。判断力生长的土壤。

Dario Amodei 在2026年3月说了句话:6个月内,90%的代码将由 AI 编写。

如果他说对了,那片土壤会怎样?

Karpathy 已经在身体力行了。2025年12月起他不再手写代码。他的 AutoResearch 项目——630行代码加一个 markdown 提示词(prompt)——2天跑了700次实验。一个人加上一套 harness,做了一个团队几周的工作量。

但 Karpathy 能这么做,因为他是 Karpathy。他知道什么实验值得跑,什么结果值得追,什么发现是噪音。那个 markdown 提示词之所以有效,是因为写它的人有几十年的研究直觉。

如果这片土壤被全自动抽干了呢?

我不知道答案。

我只知道我自己的 harness 是在上千小时的较劲中长出来的。如果有人问我怎么快速学会设计 harness,我想说的第一句话是:你不能快速。

顺便说一件事。GitHub Copilot 从2026年4月24日起,免费和 Pro 用户的交互数据默认用于模型训练。你和 AI 协作的方式、你的 harness 思路、你的指令文件风格,都会变成下一代模型的训练数据。

你在教 AI 怎么做,AI 在学你怎么教。

这个循环里,谁在设计缰绳,可能比谁在骑马更重要。

这个我也不确定。留给你想。

本书的下一步

如果你读完想动手,《Claude Code 从入门到精通》橙皮书从零开始讲 Claude Code 的所有能力,在微信读书可以直接搜索到。

返回目录 ↑