Harness Engineering 远远不够:为什么软件工厂模式会失败?
- 现在最火的做法叫「关灯工厂」:AI 写代码、AI 审代码,人一行都不读。HumanLayer 创始人 Dex Horthy 连发上下两篇长文说这条路跑不通,而且这不怪你姿势不对,问题出在模型是怎么被训出来的
- 他引的 Faros 数据覆盖 22000 名开发者两年:人均完成的大需求确实涨了 66%,但每个 PR 对应的线上事故涨了 242.7%,一次评审都没过就合进主干的 PR 涨了 31.3%
- 根子在打分方式:模型练编程时,裁判只看「要修的那个测试过了没、别的测试挂了没」,两个都满足给 1 分。怎么修的一分都不影响得分,所以到处套 try catch 把异常吞掉,也是满分
- 而「写得烂」没法进奖励,因为它没有快速裁判:跑测试几秒出结果,烂架构的账单几周几个月后才到,中间那条因果链倒推不回去
- 他给的解法不要求你少用 AI,只要求把力气挪到动手之前:产品评审、系统架构、程序设计、竖切四段。按他的估算,一小时规划把评审从 6 小时压到 20 分钟,而八成的预期痛苦在最开始十分钟里就消掉了
2026 年 7 月,HumanLayer 创始人 Dex Horthy 在 AI 工程师世界博览会(AI Engineer World's Fair)上做了一场主题演讲,题目就叫《软件工厂为何失败》。会后他把这场演讲扩写成一篇长文,因为 X 对单篇能放的图片视频有数量上限,7 月 24、25 日拆成上下两篇发了出来。
上篇的副标题是「外壳还不够」。业内把套在 AI 编程模型外面的那层东西叫 harness,中文一般译作外壳:给模型什么工具、怎么喂上下文、跑几轮、失败了怎么重试、上几道自动审查。这一年所有人都在往这层外壳上使劲,追求的是一条不用人插手的流水线。他要论证的是:这条路解决不了软件质量的问题,因为问题不在外壳,在模型是怎么被训出来的。
下篇叫「把灯重新打开」,讲的是他自己团队踩完坑之后改用的那套做法。下面把两篇合起来讲。
软件工厂的现状与盲目「全自动化」
Faros AI 拉了 22000 名开发者、4000 个团队两年的工程数据。这些数字没有一条来自问卷,全是直接从代码仓库、持续集成流水线、事故系统、工单系统和编辑器里抓出来的。他们在同一批公司内部做对比:AI 用得少的那段时间,和 AI 用得多的这段时间。
产出那一栏很好看。再往后看,事故和 bug 全在涨。
大需求(epic)
吞吐
PR 条数
线上事故
(上一年是 +9%)
中位耗时
这里的 PR 指程序员提交的一次改动,等着别人过目再合进主代码。第四个数字要留意:它是「每个 PR 对应多少事故」,已经把提交量变多这件事除掉了,交得更勤本身解释不了这个涨幅,是每一次交出去的东西更容易出事。Faros 自己的解释是:跳过评审的人多半没打算跳过,更可能的原因是审的人跟不上 AI 出活的速度。同期,一次评审都没过(人审、机审都没有)就合进主干的 PR 涨了 31.3%。
Dex 拿这组数字开场,是想说明一件事:代码确实产得更多了,只是账没在产出这一栏结,结在了下游。
软件工厂是什么,关灯关掉的是哪一步
先说清「软件工厂」指什么。它就是一条流水线:想法进队列,有人做,有人审,上线,出了事再回炉。这套东西不是 AI 时代才有的。
AI 来了之后,这条线只换了一格:「有人做」变成「Agent 做」。Ramp、Stripe、WorkOS、Brex 今年都发过文章,说自家 75% 的代码是 Agent 写的(这是作者对各家说法的转述,各自按什么口径算没有逐家核过)。但换完这一格,麻烦就来了:做一件事从几小时几天掉到几分钟几小时,审一件事还是几小时几天。于是审的那一格成了整条线上最堵的地方。
你可以继续往上加自动化:让 Agent 审代码、让 Agent 拿浏览器把以前的功能全跑一遍看有没有被改坏、把线上事故直接扔回队列让它自己修。但审这一格总还是慢。于是有人干脆把它拿掉了。
2022 年的样子:做和审都由人干,两边都是几小时到几天。
Agent 接手「做」这一格之后:做只要几分钟到几小时,审还是几小时到几天,于是审成了整条线最堵的地方。
关灯工厂的选择:把人审这一格直接划掉,省下的力气全押到自动测试、沙箱、自动审查、监控和灰度上。
「关灯」这个说法是 Dan Shapiro 起的,取的是工厂里没有人、连灯都不用开的意思。最常被拿出来讲的案例是 StrongDM:这条线上没有人写代码,也没有人读代码。到这一步,整条线上只剩一个问题了:还能往队列里塞多少活。
他自己关掉这一步,四个月后靠手工重铺两周收场
这套听起来很美。Dex 真去干了:2025 年 7 月,他的团队全面关灯,只读需求和工单,小活中活全交给后台 Agent,整套都上。
然后就撞上了那种 Agent 怎么都修不好的问题。他说凡是认真这么跑过几个月的人,结局都一样:你把相关的代码和文档全翻出来喂给它,你让它换十种办法把这个毛病再犯一次给自己看,都不行。最后只能自己动手,翻那个已经三个月没读过的代码库,一行行找哪里坏了。而在他找的这段时间里,网站是停的,用户在骂。
第一次出这种事,他忍了,跟自己说这点风险换来的速度是值的。同样的事又发生了几回,到 11 月大约第三次的时候,他们判断重写比继续修更省事,于是联合创始人打开 VS Code(连 Cursor 这类 AI 编辑器都没用),手工把那一整套写法重新铺了两个星期。
这是一家小公司的一次经历,他没给任何量化数据。不过这个过程很多人都熟:一开始爽得飞起,几个月后打开代码库,面对的是一座自己都看不懂的屎山。
Agent 修一个 bug 修得很好,从零做一个新页面也很好。为什么同一个 Agent 长期维护的代码库,会越写越难改?他找到的答案不在提示词里,也不在工作流里,在模型是怎么被训出来的。
为什么外壳(Harness)救不了 AI
遇到这种事,最常听到的说法是你姿势不对:提示词写得不够好、流程没搭对、审查 Agent 上得不够多。所以先把这条路堵死。
套在模型外面的这层外壳,你确实能随便改;模型内部那几千亿个数字(权重),你改不了。而下面这层能把上面那层的成果吃掉。Claude Code 就是最清楚的例子。
Claude Code 之前,aider、cline、codebuff 这些命令行编程工具早就有了,上下文工程做得也好,工具集几乎一样:读文件、写文件、改文件、按关键词搜代码、跑命令。但用起来时不时就抽风:你眼看着它在同一个改动上试三次都改不对,最后只能自己打开编辑器动手。
2024 年那篇 SWE-Agent 论文把这件事拆得很细:工具的形状改一点点,Agent 的表现就差一截。比如给读文件的结果加上行号,或者把改文件的工具从「查找替换」换成「按行号范围改」。
后来 Claude Code 上线,很快就起来了。有人说这是因为 Anthropic 本来就有渠道,但更被接受的解释是:Anthropic 头一回拿即将发货的那套工具,去训模型本身。调工具定义、调评测、找模型最顺手的那个形状,这件事很多人干过;而能直接改模型内部那些数字、让它更会用某一套工具,是另一回事。OpenAI 团队在 11 月一场演讲里说的是同一个意思:你搭外壳但拿不到权重,永远比不过两头都占的团队。
模型训练的缺陷:没有一项在罚「不好维护」
外壳这条路堵死了,那问题究竟在哪?在模型是怎么被教出来的。它被教的时候,压根没有一项在罚「这代码以后不好维护」。
裁判只数两件事:修好了没、有没有砸到别处
外壳这条路堵死了,那问题究竟在哪?在模型是怎么被教出来的。
三步:让模型把同一道题跑出一堆不同的解题过程;用一个裁判给每次过程打分(编程任务的裁判是一段自动跑测试的程序,不是另一个模型);然后调整模型内部的数字,让得分高的过程以后更容易出现,得分低的更不容易出现。这三步重复几百万次,跑上几周几个月。
外壳(harness):模型外面那一圈东西:给它什么工具、怎么喂上下文、跑几轮、失败了怎么重试。同一个模型换个外壳,表现能差很多。
这就像教孩子应试打卡:这道题的答案对了,就给 100 分。至于他是真会了,还是背了个套路蒙对的,卷面上看不出来,也就没人扣他的分。几百万遍下来,他学会的是怎么让卷面对,不是怎么把事想明白。
模型最后长成什么样,全看裁判在数什么。那么编程这件事,裁判到底在数什么?
走一遍真题:那两件事里,没有「写得好不好」
裁判在数什么,看一道真题最清楚。拿 SWE-bench Multilingual 这套业内通用的编程考卷举例:题目是从 Redis、jq、Django 这些知名开源项目里扒下来的真实 bug,一道大概十五分钟的活。裁判只看两件事:你要修的那个测试从「不过」变成「过」了没有(FAIL_TO_PASS),以及你有没有把本来就过的测试搞挂(PASS_TO_PASS)。两个都满足给 1 分,否则 0 分。
他挑了一道真的。用大白话说,这段程序拿到一样根本不存在的东西,还伸手去问它「你是空的吗」,于是当场崩掉。具体是 Ruby 项目 fastlane 里的打包动作:它有两个可选参数,你不填的时候,程序照样拿它们去问。
'zip_command': undefined method 'empty?' for nil:NilClass
- @include = params[:include] - @exclude = params[:exclude] + @include = params[:include] || [] + @exclude = params[:exclude] || []
评测的时候,模型拿到的是这段报错,加上修复落地前那一刻的仓库快照。它看不到上面这个标准答案,也看不到用来给它打分的那段测试。它交上补丁之后,流程是这样的:先把它对测试文件做的所有改动统统扔掉,因为逮到过模型偷偷把失败的测试注释掉,或者塞一个假的替身进去让测试形同虚设;再把官方那段测试补丁贴上去;最后跑一遍整个测试套件。
它是怎么修的,一分都不影响得分。
几百万轮下来,模型学出的就是下面这种写法。第一种把整段包进 try catch,出错就打一行日志、返回一个空值,故障被吞掉了,但测试是过的。第二种连转两次类型,绕开语言自带的类型检查再往上挂字段。类型检查本来是让你写错时当场被拦住,这么一转,这层保护就没了,但测试还是过的。
训练里对「把代码结构搞烂」没有任何扣分项。几百万轮之后,模型自然就长成了这个样子。
为什么不能把「写得烂」也加进去:账单几周后才到
那为什么不给「写得烂」也加一项扣分?有人想过。算不出来。
跑一遍就有答案,所以强化学习能拿它跑几百万轮。
账单要等到有人来改这块代码才寄出来,那时候跑几百万轮的窗口早关了。
「架构烂不烂」这一头具体是这样的:某天有人打开那个文件想改一行,发现改不了。当初那段代码写得太随手,同一处改动现在得在十一个地方各改一遍,还得祈祷三个文件外的东西不要悄悄崩。这就是 Martin Fowler 说的霰弹式修改(shotgun surgery)。
更麻烦的是,等这笔账真的寄到(线上出了事故),你已经没办法把它退回给几个月前那个写歪了的决定。训练模型靠的正是把最终的好坏一路回推到中间每一步,再据此调整模型内部的数字,这一步叫反向传播(backprop)。而这条链在这里是断的。
不难想象,如果模型真能可靠地分辨好代码和烂代码,它一开始说不定就写出好的那一版了。
Dex Horthy,《Why Software Factories Fail》
行业前沿的尝试与现状
这事没被放弃。有三家在动打分方式本身,Dex 认为方向是对的。
| 谁 | 换了什么打分方式 |
|---|---|
| SWE-Marathon Abundant AI | 把题目做到 400 小时量级,比如「把 Excel 的每一个功能都克隆一遍」,不再只给 0 分或 1 分,而是拆成几个维度各给一部分分。 |
| DeepSWE Datacurve | 专挑开源仓库上、现实中从没被真正做出来的大活,从构造上保证答案不可能已经躺在训练数据里。这解决的是抄答案,不解决质量。 |
| Frontier Code Cognition | 题目跨多个 PR,并且用一个不靠模型判断的招数评质量:你写的测试如果在打补丁之前就能通过,说明它根本没测到东西,扣分。另外再上一个模型,拿代码质量规则去审那份改动。 |
但让模型去当质量裁判,能走多远是有限的。Dex 说他还是不敢拿自己的代码库赌这三家里的任何一家,不过这是他见过第一批真在给可维护性打分的评测,没有停在过还是不过。至于多上几个评审 Agent、多烧点 token,他认为那能把下限抬高、把蠢错误捞出来,却抬不动上限,因为上限就是强化学习教给模型的那些东西。强化学习需要一个又快又可靠的裁判,而可维护性上我们还没有。
重新把灯打开:把代码评审拿回来
既然上限一时抬不动,质量这一关还得人来把,那就把关灯时砍掉的那一步装回去:人重新读代码。然后用 AI 干另一件事:把力气往动手之前挪,让每次交到你面前的东西一开始就少出错。按他的经验,动手前花一小时,评审能从 6 小时压到 20 分钟。
软件行业几十年前就发现了同一件事:写代码要几小时到几天,审代码也要几小时到几天,所以团队会在动手之前一起做规划、过架构方案、开排期会。好处有两个,一是返工少了,因为大家在没人写代码之前就对齐了;二是评审快了:你要是读过一份长但做得很到位的 PR,就知道那种几乎不用停下来的顺畅感。
他把「动手之前」拆成四段。
写代码之前,用 AI 做好四个阶段的提前规划
可以把现在的 Agent 想成一个手很快、很听话、但完全没有大局观的实习生。你跟他说「帮我做个某某功能」,他会闷头写上几千行,测试还都能跑通,可结构烂到你没法改。等他写完你再去纠,已经晚了。
所以真正省力的地方在动手之前:趁他还没动手,先把要做的事跟他吵清楚。他们把「动手之前」拆成四段,每一段都用 AI 起草、人来定稿。下面逐段讲。
第一段 · 产品需求(Product Review)
一份短文档,写清两件事。第一是要解决的问题:用户实际在受的罪,用用户的话说,不用技术的话说。第二是怎么算成功:东西发出去之后,你看什么就能判断这活值不值得干。最好是用户层面的结果,比如某个流程用时变短了、新用户更早走到某一步;有时候是错误率、响应快不快这种更偏技术的指标;有时候就是「关于 X 的工单不再来了」。
这里最实在的一条是:涉及界面的部分别用文字描述,直接让 AI 糊一个 HTML 原型出来。三段话吵不完的架,一张粗糙的界面图当场就定了。
不是所有事都要走这一段。改个文案、写个一次性脚本、修一个复现步骤明确的 bug,照旧一句话丢给 Agent。这一段是留给那种改动的:Agent 要是理解错了你的意图,返工的代价会很大。还有一条他们一直在用的规矩:谁会来审这个 PR,就提前把方案发给他看一遍,把评审时才会冒出来的分歧提前到还没写代码的时候解决。
第二段 · 系统架构(System Architecture)
这一段对齐的是服务、接口、数据表、队列、存储之间怎么说话,先不进到代码内部。为了把人和 Agent 之间的沟通带宽拉满,这一段他们大量用画出来的东西:时序图、接口契约、建表语句。
PUT /api/resources/:slug
request: { destination: string }
response: { resource: Resource }
他自己也留了句提醒:mermaid(用文字描述、自动画成流程图的那种写法)该用的时候好用,但有时候是杀鸡用牛刀,而且会给你一种「我们已经对齐了」的错觉。架构这一段最省力,能在这儿拦掉不少模型的坏习惯,但光靠它还产不出高质量的代码。
第三段 · 程序设计(Program Design)
大多数人觉得架构定对了,模型就能自己发挥了。你可以这么干,但交回来的东西你不一定满意。
在任何人(包括 AI)动手写实现之前,他们会再往下走一层,把代码的形状定下来:有哪些类型,关键函数的签名长什么样,文件怎么摆,调用栈怎么走。他说这一段在 AI 编程的讨论里被严重低估了。
他们第一版的程序设计 skill(挂给 Agent 的技能包)做得很糟,读起来累人。mermaid 也试过,不够用。最后真正好用的,是三种轻量的伪代码材料。
entrypoint runCommand + handleCreateResource + ResourceClient.create(input) + POST /resources + renderResult - legacyCreateFlow
src └── resource + ├── resource-client.ts # NEW - wraps API contract calls + ├── resource-client.test.ts # NEW - covers request/response mapping ~ └── resource-route.ts # MODIFIED - wires create action into UI
interface Item {
id: ItemId
parentId: ItemId | null
// ...
}
interface Cursor {
position: ItemId
direction: 'up' | 'down'
// ...
}
resolveTarget(items: Item[], cursor: Cursor) -> ItemId | null
这三样东西模型起草得很快,你跟它来回争几轮就定了。而它们里面的每一条,你不在这时候定,就会拖到代码评审的时候被迫定。那是改主意最贵的时刻。
第四段 · 垂直切片(Vertical Slices)
这一段可以叫「切成小香肠慢慢吃」:别让 AI 一口气把数据库、后端、前端全做完,切成一小块一小块能跑通的功能,写一点、看一点、审一点。
而模型排计划有个天生的偏好,正好相反:按技术分层,从最底下往上做。
这么干的问题是,中途没有任何一刻你能打开看一眼、点一下试试。用代码测当然可以,但他做过的几乎每个功能,读完测试之后还是得在浏览器里点开看看,或者拿命令行去戳一下接口。在 AI 之前,很少有人会一口气写完两千行、甚至五百行代码,中间一次都不检查。
他自己在 AI 之前的习惯是从中间往外做:先把接口契约立起来、喂假数据,用命令行戳通;再做界面去读这些假数据,在浏览器里调到顺眼;然后把接口接到服务层,服务层还是先返回假的;再补数据库迁移、把服务层接上真库;最后才是大量的业务逻辑和错误处理。每一步都能跑起来看一眼。
还有两点。一是前沿模型在没人盯的情况下基本不会这么排计划,而且这事很难按代码库、甚至按任务去总结成通用规则,所以这一步他坚持自己盯着。二是他一次只放一到三个切片出去,边做边审:检查一两百行然后调头,比等到两千行之后再去找哪儿坏了便宜得多。
怎么扛住 AI 时代的代码评审负担
走完这四段,你还是会收到一堆等着看的 PR。他对这件事只有一句:你不是 PR 太多,你是烂 PR 太多。
需要返工的 PR,AI 之前就一直有,不是新鲜事。而一份做得好的 PR 读起来是享受:你一个文件一个文件翻下去,代码是干净的,你和团队那些吵出来的决定、攒下来的偏好,它全照着做了。
反过来,一份 PR 哪怕只需要返工两成,对交的人和审的人都是双重折磨:既费脑子,也熬心态。他自己的估计是,AI 一把梭出来的 PR,返工比例通常更接近五成。就算交这份 PR 的是 AI,背后总有个人按下了开始、或者顺手润色过、或者至少在乎这活干成什么样。
你不是 PR 太多,你是烂 PR 太多。
所以前面那四段规划,省的不是写代码的时间,省的是这份折磨。而怎么判断一件活值不值得走全套,他在单独写的那篇支线里给了一个可以直接拿来用的判断法。
这套流程他们并不是每件事都跑。按他的估算,大约 40% 的任务直接一句话丢给 Agent,一两轮轻反馈就完事;中等的活把产品和架构合成一份计划文档,不拆阶段;只有大活才走全套,遇上大重构会跳过产品那一段。
那怎么判断一件活值不值得花时间规划?他另外单独写过一篇,里面给了一个可以直接拿来用的判断法。先把「预期痛苦」定义成两件事相乘:你得返工的概率,乘上返工有多疼。
然后取三个点。两分钟随手丢一个提示词进去,拿到一份能直接合并的结果大概是五五开,也就是有 50% 的概率要返工。换成一个在这套代码里泡了十年、见过上百个项目的资深工程师,花五个小时手写一份足够细的规格,返工概率掉到 10% 左右。最极端那头,花二十个小时把每一行代码都自己写,返工归零,但你也放弃了 AI 本来能帮你省下的全部力气。
他自己也补了一句:返工的概率和返工有多疼本来是两个变量,为了把这件事讲清楚,他硬把它们压成了一个百分比。要是模型有 50% 的概率把某个按钮样式弄错,但改回来只要一句提示,那这份预期痛苦其实很低。
一件活要是头十分钟就能消掉八成的预期痛苦,就别花六个小时去规划它。
接受约束,找到真正的杠杆
他说他当初也很期待那样一个世界:随口提需求,让模型自己做,拿回来的是能长期演进、不会烂掉的生产级软件。但他一路试下来,撞到的全是做不到的地方:模型有些事做得好,有些事做不好。问题就变成了,在这些约束里,你的流程该怎么摆。
行业里流行的口号是快 10 到 100 倍。他的原话是,你可能太忙着追这个数,忙着说服自己代码质量已经不重要了,以至于忘了还有另一条路:接受这些约束,稳稳地快 2 到 3 倍。
他给的收尾就四句话。
被点名的 StrongDM 回了一条
Dex 在文章里提了一句:StrongDM 那个公开的进展页,从 2 月到 6 月只有零星更新。被点名的这一方在 Hacker News 上回了。
StrongDM AI 实验室的 jaytaylor 7 月 23 日说,他们更新的节奏不算零星,有值得说的进展才更新,从 2 月起平均一个月一次。他还说他们正在写新文章公布最新发现,整体判断依然乐观:几乎所有软件问题都能被工厂那套方法组合解决,模型越强,效果越好。Dex 回复说想听他们做一个五六个月的复盘,什么判断对了、什么错了,并且把这条讨论加进了原文。
AI 写的代码越写越难改,根子在模型被训出来时的打分方式
HumanLayer 创始人 Dex Horthy 连发两篇长文,拆解「关灯软件工厂」为什么跑不通,一页带图讲完他的证据、机制和解法。
↓ 一页读完 · 有一张会动的图
Faros AI 从 22000 名开发者、4000 个团队两年的工程数据里做了一组对比:同一批公司,AI 用得少的那段时间,和 AI 用得多的这段时间。产出那一栏确实好看,往下游看就变了。
PR 指程序员交上去、等人过目再合进主代码的一次改动。中间那个数字已经把「交得更勤」除掉了,它说的是每一次交出去的东西更容易出事。同期,一次评审都没过(人审、机审都没有)就合进主干的 PR 涨了 31.3%。三项数字均出自 Faros AI 的遥测报告,Dex Horthy 引用;口径是同一批公司前后两个阶段的自比,Faros 自己把它定性为统计上显著的相关,没有做对照实验。
出了事最常听到的诊断是姿势不对:提示词写得不够好、审查 Agent 上得不够多。这条路得先堵死。
工具的形状改一点点,表现就差一截 , 2024 年 SWE-Agent 那篇论文把这件事拆得很细
多上几个评审 Agent、多烧点 token,能把蠢错误捞出来
Claude Code 之前,同类命令行编程工具的工具集几乎一样,用起来时不时就抽风;更被接受的解释是 Anthropic 头一回拿即将发货的那套工具去训模型本身
OpenAI 团队给的判断是:搭外壳但拿不到权重的人,永远比不过两头都占的团队
模型练编程走的是强化学习:同一道题跑很多遍,一个裁判给每次的过程打分,得分高的加权重、低的减权重,重复几百万次。裁判在数什么,模型最后就长成什么样。
那为什么不加一项质量分?有人想过,卡在时间上。
这事没被放弃。Abundant AI 的 SWE-Marathon 把题目做到 400 小时量级并拆成多个维度给分,Cognition 的 Frontier Code 用一个不靠模型判断的招数评质量:你写的测试如果在打补丁之前就能通过,说明它根本没测到东西,扣分。Dex Horthy 认为方向对,也说自己还不敢拿代码库赌其中任何一家。
他团队的做法是把关灯时砍掉的那一步装回去 , 人重新读代码;同时用 AI 把力气往动手之前挪。他对评审这件事只有一句:你不是 PR 太多,你是烂 PR 太多。按他的估计,AI 一把梭出来的 PR,返工比例通常接近五成。
Agent 做,Agent 审,直接上线。
大需求
就干多少活
线上事故
过目的一次改动
写得不够好?
上限在训练里。
所以能拿来跑几百万轮。
已经晚了
- × 以后好不好改
- × 结构有没有搞烂
- × 一处改动要动几个文件
代码读一遍。
产品评审 → 系统架构 → 程序设计 → 竖切。
一次只放一到三个切片出去,边做边审。
10-100 倍一路没见到





