软件工厂的本质是规模化运行的循环。你可以让人类参与循环(浅度工厂):以判断力和专注力换取速度和风险。也可以忽略人类(深度工厂),让这些 Agent 自主规划、构建和交付代码,而无需任何人真正阅读细节。但如果人们停止阅读,他们就会停止理解你的软件。现在你最艰巨的任务是,知道该构建哪些检查机制,以及该委托多少自主权。
软件工厂这个概念最早可以追溯到 Bob Bemer 在 1968 年发表的论文《程序生产的经济学》。半个世纪以来,许多人梦想着这样一个世界:软件成为一种可重复、可衡量的生产过程(类似于工厂里冲压汽车零件),而不是孤立的个人手工艺。从历史上看,这个梦想通常(尽管并非普遍)以失败告终,部分原因在于,想法本身难以被“冲压成型”。
然而,在过去两年里,情况发生了翻天覆地的变化,以至于现在重新审视这个古老的梦想变得很有意义。而且,由于一些细微之处很容易被忽略,我们有必要精确地指出,哪些是真正的新事物,哪些可能是伪装成新机遇的旧陷阱。
@dexhorthy,HumanLayer 的联合创始人,最近在 AI Engineer World's Fair 上发表了一场精彩的演讲,题为 "约束工程还不够:为什么软件工厂会失败。",非常值得一看。

循环是原子。工厂是规模化后的循环。
结构决定一切,一切始于微小的单元。整个体系实际上由三个层层叠加的概念组成:循环、约束框架和工厂。
循环,就是一个 Agent 重复执行单一任务的过程:收集上下文,采取行动,检查结果,然后再次循环,直到满足某个条件。它是 Agent 工作的最小单元,在其之上的所有东西,都只是循环的叠加。
循环工程 的重点在于,你不再一步步地提示 Agent,而是设计一个能自动为你提示 Agent 的小型系统。
约束框架,就是围绕循环的边界:它运行的沙盒、它能接触到的工具、在运行之间存活下来的记忆,以及决定“完成”意味着什么的门控。循环是行为;约束框架是行为运行的环境。
给一个原始模型不提供约束框架,它会愉快地永远运行下去。约束框架就是围绕它的一切,使其变得有用且安全。
软件工厂,就是许多带约束的循环同时运行,由一个工作队列提供输入,并通过一个审查门控输出到生产环境,而人类则从顶层掌控全局。它不是更大的 Agent;它是一个由循环构成的组织架构图。
最终的范式转变是从编写代码,转向构建和运行那个编写代码的工厂。工作单元向上提升了一个层级,变成了循环、约束框架以及它们之间的流程,而不是单个的代码差异。

循环 → 约束框架 → 工厂。工厂不是一个更聪明的 Agent;它是许多带约束的循环,输入到一个审查门控,并由人类控制外部循环。工厂,如图
Dex 花费最多时间讲解的核心幻灯片非常出色,因为它是一个清晰的结构图,将原本可能看似普通的循环可视化了出来。这是我的理解:

工厂是一个闭环:意图和生产信号进入一个队列,约束框架进行构建,自动检查和审查门控进行验证,部署交付,监控则将生产环境数据转化回信号。意图来自工程领导层的愿景,以及工程师的直接输入,它们进入待办事项队列。由事件和用户请求驱动的信号,也输入到同一个队列。
约束框架就是从队列中选取一个项目并为其构建变更的工具。在约束框架之外,我们可以看到所有为使变更安全地进入生产环境而必须的自动检查。这些自动检查同时运行,毫不费力,无需工程师有意识地参与,这要归功于 CI、测试、静态分析和各种扫描。这里唯一的决策点是审查门控。批准后,变更被部署到生产环境并进行监控,监控数据反馈回最初启动循环的信号。
总的来说,这个图表中的每个环节几乎都是零成本的:生成、测试、扫描。它们都可以以可忽略的成本规模化运行。只有一个环节成本高昂,且难以抗拒规模化,那就是审查门控。这个闪亮的琥珀色盒子代表着“判断力”,也是关于我们能否让开发更快、更频繁的争论的核心所在。
为什么我们称之为“深度”
深度工厂在物理上关灯运行,因为车间里只有机器,机器不需要光就能看见。深度软件工厂也是如此:代码在没有人类阅读的情况下交付,仅由其他机器验证。
这个概念借自制造业。它的起源是物理的,而非数字的,根植于关灯、由机器人执行工作的工厂。自 2001 年起,日本的发那科(FANUC)就在运行这种关灯工厂;2024 年,小米也开设了自己的高度自动化深度工厂。它们的共同点是,产品在组装和交付过程中,没有任何人类阅读过其中的任何内容。当“阅读”这个行为从流程中被移除时,“深度”就出现了。
我借用这个概念,并非为了追求它的氛围,也不是作为贬义。尽管这个术语有点令人不安,但这里的“深度”只是一个简单的物理事实:在原来的工厂车间里,只是没有了光。在软件领域,车间就是代码差异。编写代码差异的人、审查它的人、交付它的人,这些人类都不在了,剩下的只是一个仅由构建它的机器验证过的代码差异。
这是一件出奇容易做到的事情,至少在最初如此。之所以容易,是因为缺失的审查步骤阻碍了其他一切。它的缺失会让你感觉团队的垂直吞吐量突然变得极其巨大。仿佛你已经突破了音障。尽管看起来很容易,但要在这些深度工作流中坚持下去,并承受其隐藏的成本,却比想象中要困难得多。
约束工程还不够
编排、沙盒化原型设计以及工具调用(当模型与世界和彼此交互时)的约束框架,将变得越来越强大和有效。然而,在长期维护代码库质量并通过增量变更来跟上节奏方面,存在一个内在的模型内失败。我认为有充分的理由相信,仅靠模型本身最终将无法赢得对抗理解债务的战斗。
理解债务,是指代码量与其被人类理解的程度之间日益扩大的差距。深度工厂不会偿还这笔债务;它会尽最大可能地积累债务,而测试却始终是绿色的。
这是一个重要的区分,因为模型在某些任务上表现良好。但对于任何不是对代码库一小部分进行即时变更的任务,尤其是在复杂的棕地系统中,仅靠模型的自动化编码会面临一个难以逾越的障碍。绿地应用、周末玩具项目和副项目都具有共同特点:几个月的开发周期通常足以让一切正常运行,或者至少接近正常运行。
但是,一个已经开发了十年或更久的企业级系统则是另一回事;它必须以专业的速度在专业环境中进行维护。项目开始三到六个月后,你已经在未读代码中挣扎了。那种环境,尤其是生产代码所施加的约束,即使是一个强大的 Agent 也会表现不佳,这与开发周末玩具项目的开发者所享受的“氛围编码”形成鲜明对比。
Dex 根据经验指出,这是一个重大的失败,以至于需要一丝不苟的手动调试才能定位。这来自于运行一个全自动代码工厂大约四个月的经验,在此期间没有人看过编写的代码。这种体验背后是两种相互冲突的指标之间的权衡。一种是最大化 Token 利用率,这是我们目前视为进步的数字。另一种,它悄悄最小化的是,在任何时刻,系统中的任何人类参与者仍然能理解多少内容。
深度工厂真正擅长的地方,在于它能够在测试保持绿色的同时,快速消耗掉全新的代码。最终的清算,当它到来时,不会是一个戏剧性的“一切突然崩溃”的时刻。它会悄无声息地到来,而且为时已晚。

深度和浅度是相同的流水线,只是灯的位置不同。浅度版本不仅仅是在末尾重新添加审查——它还将人类的判断力向上游移动,进入设计和架构环节。瓶颈从来不是生成
软件工厂的根本限制不在于我们能产出多少代码:而在于我们验证代码的速度有多快。
反压原则是:你只能授予一个循环与其廉价且可靠地验证的能力相匹配的自主权,不能多一分。验证,而不是生成,才是工厂的真正限制。
因为无限的生成能力与有限且不可扩展的人类注意力资源处于持续的紧张状态,核心问题是廉价生成与有限审查之间的差距。看看这个漏斗:只要代表验证的瓶颈没有变宽,它就会堵塞。正如 Dex 指出的,数量本身不是问题;我们真正面临的是大量低质量 PR 的盈余。当你拥有高产量却没有可信赖的门控时,制造缺陷是不可避免的。这又回到了反压原则:自主权不能扩展到超出其被廉价且可靠地验证的能力。
第二个层次的问题是,为什么改进模型不应该自动缩小它能生成的内容与能被验证的内容之间的差距。在架构良好的系统上进行训练,可以说比通过简单测试更困难:记住,衡量架构卓越性的成本函数不是以秒甚至分钟来衡量的,而是以月和年来衡量的。清晰的梯度在功能上是不可能计算的,因此,一个期望对复杂设计决策进行清晰、即时评估的系统,不太可能通过好的例子进行训练。
生成是一个宽阔的入口;验证是一个狭窄的瓶颈。加快入口的速度只会加深瓶颈处的堆积。
重新打开灯
浅度工厂是相同的流水线,只是在判断力所在的地方灯是亮着的。Agent 仍然完成大部分构建工作,但在代码交付之前,会有人类阅读其输出,并且在任何代价高昂的错误决策可能发生的地方,灯都是亮着的。
浅度版本不是把审查附加到末尾,而是将人类的判断点向上游移动,移到产品、设计和架构层面,在 Agent 开始循环之前。
那提前花费的一个小时的一大好处是,它减少了实施阶段的小时数。它将一次漫长、令人沮丧的代码审查,变成了一次快速阅读两百行计划的过程。你在决策被构建之前就审查它,所以之后你就不必在两千行生成的代码中翻找,才发现决策到底是什么。有些决策成本高昂且影响持久,你希望有人尽早参与,在成本叠加之前。当然,即使你提前投入了时间,有时你仍然需要查看代码差异。
你可能会觉得这听起来并不那么光鲜。你说得对。这个安全网由我们一直都知道但大多忽略的、极其普通的架构实践组成:良好的类型和方法签名,以便错误由编译器而不是在生产环境中捕捉;测试接缝,我们可以固定行为并使变更可观察;精心布局代码,以便下一个阅读者(无论是人类还是模型)知道在哪里找到他们关心的内容;保持调用栈短小且清晰;保持组件边界清晰,这样变更就不会有巨大的爆炸半径;以及依赖注入,这样我们可以换掉一个组件。这些都不是新东西。我们一直说我们关心良好的架构。但现在我们使用了自动化编码 Agent,这个架构终于承担了第二个角色,成为一个廉价且难以伪造的安全网,来捕捉 Agent 会犯的错误。
这个安全网必须在模型之外,因为模型不会提供它。那些感觉最强大的编码 Agent,如 Claude Code 和 Codex,都是通过针对它们自己的约束框架和工具进行强化训练而得到的:它们对行业中的所有工具和习语都很流利,但缺乏对长期可维护性等问题的理解。我们一直谈论的深思熟虑的架构,正是捕捉这种债务的工具,我们对它的投入,就是我们在买回我们的自主权。
将其与安全的基础设施结合起来,你就可以运行一些紧密、低风险的循环,无需人工值守。Horthy 在最近的一篇文章中描述了一个例子:一个夜间的 GitHub Actions 定时任务,修复一个特定的反模式,例如一个 lint 违规或一个不必要的可选属性,然后提交,并打开一个小的 Pull Request,全部自动完成,这样团队醒来时面对的是一个稍微好一点的代码库和一个足够短的可读差异。但对于风险足够高的循环,你不想冒醒来时发现认证系统、计费引擎或公共 API 契约被破坏的风险。在那里的灯要亮着,相信一个具有判断力和对系统有真正工作知识的人会抓住错误。
什么能让循环获得“深度”资格
这个规则适用于你称之为反压、验证还是灯开关。
一个循环只有在其检查成本低廉、运行频率高,并且依赖于某种不易被轻易伪造的东西时,才能获得完全自动化的状态。绿灯或红灯的预言机、类型门控、属性测试,以及结合了真实评分标准的审查 Agent,都符合条件。你还需要预言机能够立即回答,并且不会随时间漂移。当“完成”不仅可以由你,而且可以由机器证明时,你就达到了自动化。
短循环比长循环更容易验证。Dex 的经验法则:一个 Agent 能保持状态三到十步,超过二十步后就开始失去线索。原因是上下文积累:Agent 携带的上下文越多,它就越有可能偏离方向。当循环很短时,验证它的成本很低。庞大的循环会在角落里隐藏错误,这从另一个角度说明它们从未赢得过关灯运行的权利。
保持灯亮着则相反。如果错误的答案代价高昂,并且只有人类才能发现,那么循环就需要审查。无法通过测试捕捉的细微生产错误、大的爆炸半径,以及将塑造未来一年或更长时间工作的决策,都属于此类。在这些情况下,你的注意力才是真正的产品,是昂贵且不可或缺的部分。
危险在于忘记切换每个开关,而是将它们全部设置为相同的模式。全部深度,四个月后你就得推倒重来。全部浅度,没有人能及时完成审查,你就会被巨大的瓶颈卡住。困难且需要技巧的工作,在于决定每个开关应该放在哪里。
循环、图还是状态机?
你应该阅读 @DavidKPiano 的《两分钟理解状态机》。
当你给 Agent 一个任务时,你很可能要围绕它构建一个图,无论你把这个图称为有限状态机,还是一组有条件链接的服务调用。这是一种框架,软件不仅仅是遵循一些抽象规则,而是遵循一个结构化的工作流:每个节点是一个明确的步骤,节点之间的每条边是一个明确的条件。
这听起来结构很多,但其中大部分在任何软件中都存在,因为任何代码都可以表示为一个控制流图。所以唯一真正的新颖之处在于,一个坚持自主权的 Agent,实际上只是在遍历一个特定的图,它的自由被限制在一个节点内部。而这里有一个人们容易忘记的部分,Dex 一年前就写下来了:软件本来就有那种结构。我们过去用流程图来画程序,是有原因的。
真正的新尝试是试图扔掉这个图表,依赖一个循环,让模型一个接一个地调用工具来选择路径,直到它自己宣布完成。这感觉像是解放,直到它遇到一个十年的代码库,而现在每个人都在重新发现的纪律,即掌控你的控制流,实际上只是让图重新围绕循环运转。所以,我们是否应该从循环回归到图的问题,几乎是在承认我们一直都需要流程图。
这是它在实践中的样子。以修复一个 Bug 为例。作为一个纯粹的循环,你坐下来思考:找出问题所在,修改一些代码,运行测试,看看会发生什么,如果这一轮没有解决问题,就循环回去重新开始。整个过程是边走边决定的:你追查哪个问题,修改哪段确切的代码,运行哪些测试以及以什么顺序,是否运行测试,以及你是重试还是宣布胜利。
作为一个图,你首先要做的是规划出应该发生的事情。重现 Bug 或去寻求更多信息,找到原因,尝试修复,运行测试,让失败的运行路由回修复步骤,而通过的运行则进入审查,只有批准才能到达完成状态。Agent 在每个盒子里仍然很聪明;它只是不能偏离你批准的路径。Santi 用一个图表清晰地展示了这种差异。
当然,这个图的真正吸引力在于,它是一个以图表形式呈现的反压规则。你放弃了 Agent 的部分自由,换来了强制性的检查和清晰的失败点,这样当一次运行失败时,你可以指向导致失败的节点。这与 Dex 直白的说法如出一辙:大多数所谓的 Agent 根本没那么“Agent 化”,它们“主要是确定性的代码,只是在恰当的位置点缀了 LLM 步骤。” 这不仅仅是人们目前构建方式的偶然产物:你可以在 LangGraph 和 LlamaIndex Workflows 中看到这种模式,在 Jerry Liu 的混合工作流-图-覆盖-Agent 模式中,一个外部循环在运行时生长出图的某些部分,以及在 David Khourshid 的提醒中,这实际上只是状态机和 Actor 模型换上了新装。
需要澄清一点,因为这个术语被严重滥用了:当我一直称其为“图”时,我指的不是知识图谱。我指的是一个预定义的有向图,描述了工作应该如何流动,包含条件边等所有内容,为循环赋予一个你真正可以信任的形状。
人类究竟在哪里
注意,人从未离开过工厂。他们只是换了位置。
我认为工程师需要越来越多地掌控外部循环。 Agent 可以调查 Bug,撰写诊断报告,实施修复,运行测试,并撰写报告。这是内部循环的执行,它们可以像任何人一样高效地完成。但这从来都不是工作的全部。你所掌控的部分,我称之为外部循环:决定这是否是解决问题的正确方法,验证诊断和实施是否合理,批准变更,并承担错误判断的后果。两个循环之间的边界是证据:代码差异、测试、日志,以及一个将它们联系起来的简短解释。类型、接缝和评分标准,使你能够在不每次都为每个变更做大量工作的情况下,监督这一切。
这样理解很有用:你不再是在生产线上编写变更;你是在生产线的末端设计它,并守护着大门。你可以做很多事情来让模型更好,让约束框架更强大,但我观察到,识别那些长期来看代价高昂的问题,通常不是你能够自动化处理掉的。核心工作仍然是,比任何纸面和计算能力的流程都更好地运用人类的判断力。
机器人在黑暗中运行没问题,但人类需要看到他们在做什么。如果工厂车间里一片漆黑,你什么都看不见,甚至找不到开关,那才是危险所在。
Pangram 评估这篇文章为 100% 人类撰写。





