Software Factories, Light and Dark
TL;DR · AI 摘要
软件工厂通过结构化循环实现规模化开发,需平衡人类控制与AI自主性。核心挑战是设计安全的控制装置和合理的工作流。
核心要点
- 软件工厂由循环(loop)、控制装置(harness)、工厂(factory)三层结构组成
- 过去两年AI工程能力提升使软件工厂概念重新具备可行性
- 人类需在工厂顶层负责关键检查,避免完全自动化导致的失控风险
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- 软件工厂架构
- 核心组件
- 循环(loop)
- 原子工作单元
- 控制装置(harness)
- 安全边界定义
- 工厂(factory)
- 规模化组织架构
- 关键挑战
- 人类监督
- 平衡自主权与检查机制
- 范式转变
- 从代码编写到工厂构建
金句 / Highlights
值得收藏与分享的关键句。
循环是原子单位,工厂是规模化循环的组织架构
未加控制装置的模型会无限循环,控制装置决定安全边界
过去两年工程能力突破使软件工厂从理论走向实践
软件工厂:光明与黑暗 —— Addy Osmani
软件工厂:光明与黑暗
循环、工具链、工厂与工程师为何需要掌控外部循环
2026年7月22日
软件工厂的本质是规模化地驾驭循环。你可以让人类参与其中(光明工厂):用判断力和专注度换取速度和稳定性。或者你可以完全忽略人类(黑暗工厂),让代理自主完成需求分析、开发和部署,而无需任何人真正审视细节。但若人们停止阅读代码,他们将逐渐失去对软件的理解。你当前最艰难的任务是:判断需要构建哪些检查机制,以及应该赋予多少自主权。
"软件工厂"这一概念最早可追溯至Bob Bemer于1968年发表的论文《程序生产的经济学》。半个世纪以来,人们一直梦想着软件能像工厂流水线生产汽车零件一样,成为可重复、可量化的生产过程,而非依赖个人手工劳动的孤立创作。历史上,这一愿景(尽管并非完全)因"思想难以标准化"的困境而屡屡受挫。
但在过去两年中,变化已足够显著,值得重新审视这个古老的愿景。由于一些微妙之处容易被忽略,有必要明确区分真正的新变化与可能伪装成新机遇的重复陷阱。
HumanLayer联合创始人Dex Horthy最近在AI工程师世界博览会发表了精彩演讲《仅靠工具链工程是不够的:为什么软件工厂会失败》,该演讲值得深入阅读。
循环是基本单元,工厂是规模化循环
结构决定一切,一切始于最小单元。整个技术栈本质上是三个概念的叠加:循环、工具链和工厂。
循环是单个代理重复执行单一任务:收集上下文、执行操作、检查结果,直到满足某个条件。它是智能体工作的最小单元,所有上层结构都是循环的嵌套堆叠。
循环工程的核心在于:不再逐轮提示代理,而是设计一个自动提示代理的小型系统。
工具链是循环的边界:它运行的沙盒环境、可访问的工具、跨运行的持久化内存,以及判定"完成"的门禁规则。循环是行为,工具链是承载该行为的环境。
如果给原始模型没有任何工具链约束,它将无限循环下去。工具链正是围绕模型的全部基础设施,使其既实用又安全。
软件工厂是多个工具链约束的循环同时运行,通过工作队列注入任务,经评审门禁流入生产环境,而人类始终掌控全局。它不是一个更大的代理,而是由循环构成的组织架构图。
最终的范式转变是:从编写代码转向构建并运行编写代码的工厂。工作单元的层级提升至循环、工具链及它们之间的流程,而非单个代码差异。
循环 → 工具链 → 工厂。工厂不是更聪明的代理,而是多个工具链约束的循环共同流向一个评审门禁,由人类掌控外部循环。
工厂示意图
The central slide Dex spent most time on was brilliant because it’s a clarifying wiring diagram that visualizes what otherwise is an obvious loop. Here’s my take on it:
The factory is a closed loop: intent and production signals feed a queue, the harness builds, automated checks and review gate it, deploy ships it, monitoring turns prod back into signals.
Intent flows from the vision of engineering leadership, and directly from engineers, into a queue of things to be done. Signals driven by incidents and user requests drive the same queue. The harness is just the thing that picks an item from the queue and builds a change for it. Beyond the harness, we can see all the automated checks required to make changes safe enough to let into production. These automated checks run at once, effortlessly, without any conscious involvement from engineers, thanks to CI, tests, static analysis, and scanning of all kinds. The only decision point here is the review gate. After approval, changes are deployed and monitored in production, with monitoring data feeding back into the signals that kicked the loop into motion to begin with.
By and large, every box in this diagram is almost zero cost: generation, tests, scanning. They all run at scale for negligible cost. There is only one expensive box that proves stubbornly resistant to scaling, and that’s the review gate. That shiny amber box is “judgment”, and where the crux of the argument about whether we can make development faster and more frequent resides.
Why we call it “dark”
A dark factory runs with the lights physically off, because the only things on the floor are machines and machines don’t need light to see. A dark software factory is the same move: code ships that no human has read, verified only by other machines.
The image is borrowed from manufacturing. Its origins are physical rather than digital, rooted in facilities where the lights are turned off and the work is carried out by robots. FANUC in Japan has been running lights-out factories of this sort since 2001 ; Xiaomi, in 2024, opened a heavily automated dark factory of its own. What these have in common is a product assembled and shipped without a single human having read any of it. The “dark” comes in when that act of reading is removed from the process.
I’m not borrowing the concept for its vibe or as an insult. For all its creepy buzz, “dark” here is a simple physical claim: the original factory floor, but without light. In software, the floor is the diff. Whoever wrote the diff, whoever reviewed it, whoever shipped it, those humans are gone, and what remains is a diff verified only by the machines that built it.
This is a surprisingly easy thing to do, at least at first. It’s easy because that missing review step gets in the way of everything. Its absence makes your perception of your team’s vertical throughput seem suddenly and radically higher. It feels as if you’ve broken the sound barrier. For all its apparent ease, it’s harder than it seems to survive those dark workflows, with all their buried costs.
Harness engineering is not enough
通过编排、沙盒原型设计和工具调用等机制,模型在与世界和彼此交互时将变得越来越强大和高效。然而,试图在长期维护和增量修改中保持代码库质量时,模型本身存在内在的失效风险。我认为,仅靠模型最终将在这场与理解债务的较量中败下阵来。
理解债务是指代码总量与人类仍能理解的代码量之间的差距。暗工厂不会偿还这种债务,反而会以最快的速度积累债务,同时保持所有测试通过。
这是一个重要的区分点,因为模型在某些任务上表现优异。但对于任何非局部小范围代码修改的任务,尤其是在复杂的遗留系统中,仅依赖模型的自动化编码将面临无法克服的障碍。周末玩具和副项目相似之处在于,几个月的开发周期通常足以让系统进入可用状态,或至少接近可用。但一个已开发十年以上的企业级系统则是另一回事;它必须在专业环境中以专业速度持续维护。项目进行三到六个月后,你已经淹没在未读代码中。这种环境,尤其是生产代码施加的约束,即使是最强大的智能体也会表现不佳,与周末玩具开发者享受的“氛围编码”形成鲜明对比。
Dex根据经验报告称,这是个重大失败,严重到需要耗费大量精力进行手动调试才能定位问题。这源于运行了约四个月的全自动代码工厂,期间没有任何人查看生成的代码。这次经历揭示了两个相互冲突指标之间的权衡。一个是最大化token利用率,这是我们目前视为进展的指标。另一个是任何时刻人类参与者仍能理解的系统部分,这个指标却被悄然最小化。
暗工厂真正的优势在于其能在测试保持绿色的同时快速消耗纯净代码。最终的清算不会是戏剧性的“一切失控”时刻,而是安静且迟来的。
暗工厂和亮工厂本质上是同一条流水线,只是灯光的位置不同。亮工厂版本不仅在最后重新引入代码审查,还将人类判断提前到设计和架构阶段。
瓶颈从来不是生成
软件工厂的根本限制不是我们能生成多少代码:而是我们能多快验证这些代码。
背压规则指出,你只能赋予循环与其能廉价可靠验证的自主权,多一分都不行。验证,而非生成,才是工厂真正的限制因素。
由于无限的生成能力与有限的、不可扩展的人类注意力资源之间存在持续紧张,核心问题在于廉价生成与有限审查之间的差距。看看这个漏斗:只要代表验证的瓶颈部分没有扩大,它就会持续积压。如Dex所指出的,问题本身并非体积:我们真正面临的是大量低质量PR的泛滥。当高产量缺乏可信的审查关卡时,人为制造的缺陷不可避免。这依然是背压问题:自主权无法扩展到超出廉价可靠验证范围之外。
第二类问题是为什么改进模型不应自动弥合其生成能力与可验证性之间的差距。在良好架构的系统上进行训练,可能比通过简单测试更具挑战性:请记住,衡量架构卓越性的成本函数不是以秒或分钟计算,而是以月和年为单位。整洁的梯度在功能上无法计算,因此一个期待对复杂设计决策进行清晰、即时评估的系统,不会基于良好的示例进行训练。
生成是宽大的嘴巴;验证是狭窄的颈部。加快嘴巴的运作只会加深颈部的堆积。
重新点亮灯光
点亮的工厂是同一流水线,但判断力所在的位置保持灯光开启。代理仍然完成大部分构建工作,但人类会在代码发货前阅读输出内容,且在任何错误决策代价高昂的位置保持灯光开启。
点亮版本并非将审查附加在流程末端,而是将人工判断的节点前移,使人类在代理开始循环之前,就能对产品、设计和架构进行判断。
这种提前投入的小时数带来了显著的好处:它减少了后续的实现工作量。它将漫长的、令人沮丧的代码审查转化为快速阅读一份200行的计划。你可以在决策构建前就进行审查,因此之后不需要在2000行生成代码中搜索才能弄清决策内容。某些决策代价高昂且持续时间长,你希望在成本累积前就让相关人员参与其中。当然,即使你提前投入了时间,仍然会有需要查看差异(diff)的时刻。
你可能觉得上述内容听起来不够吸引人。你说得对。这个安全网由我们一直了解但大多忽视的普通架构实践构成:良好的类型和方法签名,使错误在编译时就被捕获而非在生产环境中;可插入行为的测试断点,使变更可观察;合理布局代码,使下一位阅读者(无论是人类还是模型)都能快速找到关心的内容;保持调用栈简短易读;明确组件边界,使变更不会产生巨大的影响范围;以及依赖注入,使我们能够轻松替换组件。这些都不是新概念。我们一直声称关心良好的架构。但如今使用自动化编码代理后,这种架构终于承担了第二项工作——作为低成本且难以伪造的安全网,防止代理犯错。
那张安全网必须存在于模型之外,因为模型本身无法提供它。那些感觉自己能力最强的编码代理(包括Claude Code和Codex)都通过自身的Harness和工具进行强化训练:它们对各种工具和行业惯用语都得心应手,却对长期可维护性之类的问题并不擅长。我们一直强调的刻意架构正是用来捕捉这种技术债务的工具,而我们在其上的投入实际上是在重新夺回自主权。将这一点与安全的基础设施结合,就能实现一些低风险且高度自动化的闭环。Horthy在最近的一篇博文中描述了一个实例:一个GitHub Actions定时任务,每晚运行一次,专门修复一个反模式(比如代码规范违规或不必要的可选属性),自动提交代码并创建一个小型拉取请求,无需人工干预。团队醒来时会发现代码库略有改进,且差异足够简短,可以直接阅读。但对于涉及高风险的闭环,你并不希望醒来时发现认证系统、计费引擎或公共API契约出现故障。在这些场景中,保持系统稳定运行至关重要,你必须相信一个具备判断力且真正理解系统的人员能够及时发现问题。
什么让一个闭环获得“全黑”资格
无论你称其为反压(back pressure)、验证(verification)还是灯光开关(light switch),这条规则都适用。
只有当检查成本低廉、运行频率高且依赖于难以被轻易伪造的机制时,一个闭环才能获得完全自动化的地位。绿色或红色的预言机(oracle)、类型门(type gate)、属性测试(property test),以及配备真实评分标准的评审代理(review agent)都符合这一条件。你还需要预言机能够立即给出答案且不会随时间漂移。当完成状态不仅能被你证明,还能被机器验证时,你便实现了真正的自动化。
短闭环比长闭环更容易验证。Dex的经验法则指出:代理在3到10步内表现稳定,超过20步后就会开始失去线索。原因在于上下文积累——代理携带的信息越多,越容易偏离主题。当闭环较短时,验证成本低廉。而庞大的闭环会将错误隐藏在角落,换句话说,它们从未获得过“无人值守”的资格。
保持系统运行是完全相反的情况。如果错误答案代价高昂且只有人类才能发现,那么闭环就需要人工审查。无法通过测试发现的微妙生产环境漏洞、影响范围巨大的错误、以及将影响整个年度工作的重大决策,都属于此类情况。在这些场景中,你的关注本身就是真正的“产品”——那个昂贵且不可或缺的“产品”。
危险在于忘记切换每个开关,而是将所有开关统一设置为相同模式。全部设为“全黑”模式,四个月后你将被迫推倒重来;全部设为“全亮”模式,评审工作将积压成山,你将陷入巨大的瓶颈。真正困难而需要技能的工作,是决定每个开关应该放在哪里。
循环、图结构还是状态机?
当你给代理分配任务时,很可能会围绕它构建一个图结构,无论你将这个图称为有限状态机(finite state machine)还是一组条件链接的服务调用。这是一种框架视角:软件不仅遵循抽象规则,而是执行结构化的流程——每个节点都是一个明确的步骤,节点之间的每条边都是一个明确的条件。
这听起来似乎结构复杂,但事实上任何软件中都已存在这些结构,因为任何代码都可以表示为控制流图。真正的创新点在于,一个坚持自主性的代理实际上只是在特定图中移动,其自由度仅限于节点内部。这里有一个人们常忽略的要点,Dex 一年前就写下了:软件本来就会有这种结构。我们过去之所以用流程图来绘制程序,是有原因的。真正的新尝试是试图抛弃这种图表,依赖于一个循环,模型通过逐步调用工具来选择路径,直到它自行宣布完成。这种感觉起初像是解放,直到它遇到一个十年历史的代码库,人们现在重新发现的纪律——掌控自己的控制流——实际上只是将图重新绕回循环。因此,我们是否应该从循环回归图的问题,几乎等于承认我们一直需要流程图。
在实践中,这看起来是怎样的?假设你要修复一个漏洞。作为纯粹的循环,你坐下思考:找出问题所在,修改部分代码,运行测试,观察结果,如果这次尝试没有让程序崩溃,就回到循环起点重新开始。整个过程在执行过程中决定:你追踪哪个问题,修改哪段代码,运行哪些测试以及顺序如何,是否运行测试,以及是再次尝试还是宣布胜利。作为图,你首先要绘制出应该发生的事情:重现漏洞或请求更多信息,找到原因,尝试修复,运行测试,让失败的运行路径返回修复步骤,而成功的运行则进入审查阶段,只有获得批准才能完成。代理在每个节点内部依然聪明,只是不能偏离你设定的路径。Santi 用一张图清晰地展示了这种差异。
当然,这种图真正的吸引力在于它以图表形式呈现了反压机制。你放弃部分代理的自由度,却获得了强制检查和清晰的失败点,当运行失败时,你可以直接指向导致失败的节点。这与 Dex 直白的评论不谋而合:“大多数所谓的代理实际上并不具备很强的自主性,它们只是在适当位置插入了大语言模型步骤的确定性代码。”这并非只是当前人们偶然构建方式的产物:你可以在 LangGraph 和 LlamaIndex Workflows 中看到这种模式,在 Jerry Liu 的混合工作流图(在运行时动态扩展图结构的外部循环)中,在 David Khourshid 提醒我们这本质上只是状态机和演员模型以新形式出现的论述中,都能看到这种模式。
一个澄清:由于“graph”这个词被过度使用,我需要说明:当我反复称其为“图”时,并非指知识图谱。我的意思是预定义的有向图,明确说明工作应该如何流动,包括条件边,从而为循环赋予一个你可以真正信任的形状。
人类实际去向何处
请注意,这个人从未离开过工厂。他们只是移动了。
我认为工程师需要越来越多地掌控外循环。代理可以调查一个错误、撰写诊断报告、实施修复方案、运行测试并编写总结报告。这是内循环的执行过程,他们能像任何人一样高效完成这些工作。但这些从来就不是他们的职责。你真正需要负责的是外循环:判断这种解决方式是否恰当、验证诊断和实现是否合理、批准变更并承担错误的后果。两个循环之间的界限是证据——代码差异、测试结果、日志记录,以及一个能将它们串联起来的简要说明。类型定义、接口缝合点和评估标准使得在不为每次变更投入大量精力的情况下,仍能全面监督整个过程。
我认为这样描述很有帮助:你不再身处一线编写代码变更,而是站在生产线末端进行设计并把守关口。你可以通过很多方式改进模型、增强工具链的能力,但我的观察是,识别那些长期代价高昂的问题,通常无法通过自动化完全解决。目前仍然属于工程师职责核心的是:比任何纸面流程或计算能力的组合都能更好地行使人类判断力。
机器人在黑暗中工作没有问题,但人类必须看清自己在做什么。如果工厂车间一片漆黑,你什么都看不见,甚至找不到电灯开关,这才是真正的危险所在。
Pangram 评分系统将这篇文章标记为 100% 由人类撰写。