从让AI写代码到为AI设计系统:Harness Engineering的第一性原理

从让AI写代码到为AI设计系统:Harness Engineering的第一性原理

大多数人在问:“AI什么时候能替代程序员?”

这是一个错误的问题。

真正的变化不是AI取代了谁,而是工程的重心从“写代码”转移到了“设计AI工作的系统”。

你不会问一匹马:“汽车什么时候能替代你?”你会问:“道路该怎么修?”


一、真正的转变

过去二十年,软件工程师的核心能力是把想法变成代码。

现在,AI可以写代码了。而且写得越来越快,越来越便宜。

但这不意味着工程师消失了。恰恰相反——工程师的价值正在从“生产代码”跃迁到“定义代码生产的边界”。

想想看:工厂出现后,铁匠没有消失,他们变成了工程师。他们不再亲手锤打每一块金属,而是设计模具、定义工艺流程、把控质量标准。

软件行业正在经历同样的跃迁。

你不再是铁匠。你是设计锻造系统的人。

这个过程有一个名字:Harness Engineering。

它不是一个新框架,不是一个工具,不是一个可以npm install的东西。它是一种根本性的思维方式转变——从“我如何写好这段代码”到“我如何让AI在正确的约束下持续产出好代码”。

大多数团队还没意识到这个转变已经发生了。他们还在用旧的思维框架理解新的现实。


二、隐性知识的显性化

每个资深工程师脑子里都有一套没写下来的规则。

“这个模块不能直接调那个服务。”“日志要这样打,不能那样打。”“这里用事件驱动,不要用轮询。”“这段遗留代码别碰,碰了会塌。”

这些规则从来没有文档化。它们活在老员工的大脑里,通过code review口口相传,在午餐时间偶然提起,在新人踩坑后才被发现。

AI不吃午饭,也不做code review。它只认识被写下来的东西。

所以,Harness Engineering的第一个动作是:把隐性知识变成显性规则。

这听起来很简单,但它是整个范式转变的核心。因为——

你的经验如果不能被编码为约束条件,它在AI时代就等于不存在。

想想这有多深刻。你十年积累的技术直觉,你对系统架构的精微理解,你知道哪些“看起来优雅但实际上是坑”的设计模式——如果这些东西没有被转化为AI可以理解和遵守的规则,它们的价值就是零。

不是接近零。是零。

因为AI会绕过你所有的隐性知识,直接按照它训练数据里的“最佳实践”来干。而训练数据里的最佳实践,往往是脱离上下文的通用方案。

Harness Engineering就是把经验变成环境。不是教AI你知道什么,而是构建一个系统,让AI只能在你定义的边界内行动。

就像河流不需要“知道”应该流向哪里。河床决定了一切。

你不是在训练AI。你是在塑造河床。


三、从手艺到工厂

软件工程一直被视为一种“手艺”。

每个程序员都是工匠,代码是他们的作品。我们甚至用“craft”这个词——software craftsmanship。我们谈论“优雅的代码”“漂亮的架构”,好像在谈论一件艺术品。

这个时代结束了。

软件正在从“手艺模式”进入“工厂模式”。这不是降级,这是升维。

手艺模式里,价值在于你能亲手做出什么。工厂模式里,价值在于你能设计什么样的生产系统。

一个木匠可以做出精美的椅子。但设计宜家平板包装系统的人,改变了全世界的人坐什么椅子。

哪个创造了更大的杠杆?

人在上移,不是在出局。 从执行层上移到设计层,从操作层上移到架构层,从写代码上移到定义代码的生成规则。

这里有一个关键区别:上移不是变得更“抽象”。不是画更多的架构图,开更多的会议,写更多的PRD。

上移意味着你的工作变成了:

  • 定义系统的边界条件
  • 设计验证循环
  • 构建AI可以在其中安全工作的“赛道”
  • 当AI产出偏离时,调整赛道而不是修改产出

你不是在管理AI。你是在工程化AI的工作环境。

这就是Harness这个词的含义——驾驭,束缚,利用。不是控制每一步,而是设计让正确行为自然涌现的结构。


四、AI的过度设计倾向

给AI一个简单的任务,它会给你一个复杂的方案。

这不是bug,这是特性。或者说,这是它的本性。

AI被训练来展示能力,不是来展示克制。

你让它写一个用户登录功能,它会给你加上OAuth2.0、JWT刷新机制、多因素认证、设备指纹、风控引擎的接口预留、国际化支持、无障碍访问优化。

你只需要一个简单的邮箱密码登录。

这就是AI在设计阶段的核心问题:过度设计。

为什么?因为在AI的训练数据里,“更完善”的方案得到了更多的正面反馈。Stack Overflow上获赞最多的回答,往往是最全面的那个,不是最简洁的。技术博客里被转发最多的架构设计,往往是最精巧的那个,不是最朴素的。

AI学会了一个错误的等式:复杂 = 专业。

但真正的工程智慧恰恰相反。

最好的架构不是你再也无法添加什么的架构,而是你再也无法删除什么的架构。

AI不懂得删除。它只懂得添加。

它不会说“这里不需要”。它会说“这里可以加上”。每一次“可以加上”,都是技术债务的种子。

一百个种子长成一片杂草丛,你的系统就窒息了。

这就是为什么在设计阶段,AI的输出必须被视为“初始提案”而非“最终方案”。它是原材料,不是成品。

需要有人做减法。


五、人类审查的核心价值:做减法

大多数人以为code review的价值是找bug。

错了。

在AI时代,code review的核心价值是做减法

Bug可以通过测试找到。逻辑错误可以通过形式化验证发现。安全漏洞可以通过扫描工具检测。

但“这个东西根本不应该存在”——这个判断,只有人能做。

AI擅长回答“怎么做”。人擅长回答“该不该做”。

当你review一个AI生成的PR时,你最重要的工作不是检查代码是否正确。而是检查——

这段代码是否多余?

这个抽象是否必要?

这层封装解决了真实问题还是想象中的问题?

这个配置项真的会被改变吗?

这个接口预留是基于真实需求还是基于“万一以后要用呢”?

每一行你删掉的代码,都比你写的代码更有价值。

因为删除的代码永远不会有bug,永远不需要维护,永远不会成为技术债务。

这就是为什么在Harness Engineering的框架下,人类审查不是瓶颈。它是系统中最关键的过滤器。

不是AI写得不够好。是AI不知道什么时候该停下来。

一个好的工程师,不是写了什么惊天动地的代码。而是挡住了一百个不应该存在的功能,删掉了一千行不需要的代码,说了一万次“不”。

这种能力——知道什么不该做的能力——是AI最难学会的东西。

因为“不做”在训练数据里没有正面样本。没有人会因为“什么都没做”而获得GitHub star。

但最好的系统,恰恰是被无数个“不做”雕刻出来的。


六、系统原语:AI放大的基础

现在我们来谈一个核心概念:系统原语(System Primitives)。

系统原语是你架构中不可再分的基本构件。它们是AI构建一切的地基。

日志系统是原语。错误处理模式是原语。数据访问层的接口契约是原语。消息队列的使用规范是原语。配置管理的层级结构是原语。

原语不是你“选择”的。它们是你“定义”的。区别很大。

选择意味着从现有选项中挑一个。定义意味着你决定了这个东西在你的系统里是什么样子,有什么行为,有什么边界。

AI是一个放大器。它放大你的原语。好的原语被放大成好的系统。坏的原语被放大成灾难。

这就像复利。

如果你的利率是正的,时间是你的朋友。如果你的利率是负的,时间是你的敌人。

原语就是你的利率。

一个设计良好的错误处理原语,会让AI在每个模块里都产出一致的、可追踪的、容易调试的错误处理代码。一千个模块,一千次正确。

一个设计糟糕的错误处理原语——比如“catch所有异常然后打个日志”——会让AI在每个模块里都吞掉异常。一千个模块,一千个定时炸弹。

你不需要审查AI写的每一行代码。你需要确保你的原语是对的。

因为原语对了,AI的输出大概率是对的。原语错了,无论AI多强大,输出都会系统性地偏离。

这就像物理学。如果牛顿定律是对的,你可以推导出整个经典力学。如果牛顿定律是错的,你推导得越多,错得越远。

原语是你的定律。

投资时间在原语上。这是整个Harness Engineering中杠杆最大的一个动作。


七、真原语与伪抽象

但这里有一个陷阱。

不是所有看起来像原语的东西都是原语。很多时候,我们创造的是伪抽象——看起来像基础设施,实际上是不必要的复杂性。

真原语简化系统。伪抽象复杂化系统。

怎么区分?

真原语有三个特征:

第一,它解决了一个你真实遇到过的问题,不是一个你想象中可能遇到的问题。

第二,它减少了使用者(包括AI)需要做的决策数量。好的原语让你不用想。坏的抽象让你想得更多。

第三,它在不同上下文中的行为是可预测的。你不需要查文档就知道它在这个场景下会怎么表现。

伪抽象恰恰相反:

它解决的是假设性问题。“万一以后我们需要换数据库呢?”于是你建了一个数据库抽象层。三年后你没换数据库,但每个新功能都要跟这个抽象层搏斗。

它增加了决策数量。“我应该用AbstractBaseRepository还是ConcreteRepositoryAdapter?它们有什么区别?为什么有两个?”

它的行为因上下文而异。“在这个场景下用configV2,在那个场景下用legacyConfig,但如果是测试环境要用mockConfig,除非是集成测试。”

AI特别擅长制造伪抽象。因为伪抽象在代码层面看起来很“专业”。

它有清晰的接口定义,有完整的类型标注,有详细的文档注释。一切看起来都很好。除了一个事实——这些东西根本不需要存在。

所以当你为AI定义系统原语时,坚守一个原则:

如果你不能用一句话解释为什么这个原语必须存在,它就不应该存在。

不是“它很有用”。不是“它很优雅”。是“如果没有它,系统会在某个具体场景下出问题,而这个场景我们真实遇到过”。

从真实的痛苦中提炼原语,而非从想象中的完美中推导原语。

这是第一性原理思维的核心。


八、验证循环比更强的模型重要

行业里有一种迷信:模型越强,问题越少。

这就像说“司机技术越好,就越不需要交通规则”。

不是这样的。

GPT-7不会让你不需要验证。Claude 5不会让你不需要测试。未来的模型不管多强,在你的特定业务上下文中,它仍然会犯错。

因为它不了解你的业务上下文。它不可能了解。你的上下文是独特的、动态的、充满历史遗留决策的。

真正决定AI工程质量的,不是模型的能力上限,而是验证循环的严密程度。

什么是验证循环?

AI生成代码 → 自动化测试 → 静态分析 → 规则校验 → 人工审查 → 反馈修正 → AI再次生成。

这个循环的每一个环节都在做同一件事:缩小AI的可能输出空间,直到它只能产出正确的答案。

想象一个漏斗。

AI的原始输出是漏斗的顶端——巨大,充满可能性,也充满错误。每一层验证都收窄一点。最终流出来的,是经过多层过滤的、高度可靠的代码。

漏斗设计得越精密,你对模型本身的依赖就越小。

这意味着:一个普通模型配上精密的验证循环,胜过一个顶级模型配上松散的流程。

这是一个违反直觉但极其重要的洞察。

大多数团队把80%的时间花在选择和调优模型上,把20%的时间花在设计验证流程上。

应该反过来。

验证循环是可以被你完全控制和持续改进的。模型是别人的产品,你无法控制。

把精力花在你能控制的事情上。这是Harness Engineering的基本纪律。

一个好的验证循环应该具备什么特征?

快。快到AI每次生成后都能在秒级得到反馈。如果验证需要半小时,AI就会在错误的方向上走半小时。

全面。覆盖功能正确性、代码规范、架构约束、安全规则、性能边界。每一层都是一道防线。

可解释。当验证失败时,失败信息必须清晰到AI可以理解并自我修正。“测试失败”是没用的。“在处理空列表时,期望返回空数组但实际返回了null”——这才有用。

可演进。每发现一个新的问题模式,就新增一条验证规则。系统像免疫系统一样,遇到的病原体越多,就越强壮。

验证循环是活的。它不是你搭建一次就忘记的基础设施。它是你最重要的工程资产,需要持续投入和迭代。


九、每个Bug都是一条未被书写的规范

当AI产出了一个bug,大多数人的反应是修复bug。

这是正确的。但不够。

每个bug都是一条未被书写的规范。

这句话值得反复读。

AI为什么会在这里犯错?不是因为它“笨”。是因为在你的系统规范中,有一个空白地带——一条你以为是“常识”但从未明确写出来的规则。

用户ID不能为负数——你觉得这是常识。但你写在规范里了吗?

金额计算不能用浮点数——你觉得这是常识。但你的原语里有这条约束吗?

删除操作必须软删除——你觉得这是常识。但AI不知道。

在AI的世界里,没有“常识”这个概念。只有“已定义”和“未定义”。

未定义的空间,就是bug的温床。

所以,当你修复一个AI产出的bug时,不要只修复代码。要回溯:

这个bug对应的规则是什么?

这条规则为什么没有被写下来?

把这条规则写下来之后,它应该在验证循环的哪一层被检查?

如果这条规则更早被写下来,AI一开始就不会犯这个错误吗?

每修复一个bug,就多一条规范。规范越完善,AI犯错的空间就越小。这是一个正向飞轮。

最好的团队不是bug最少的团队。是规范增长最快的团队。

因为规范的增长速度决定了AI可靠性的提升速度。

这也回到了前面说的——经验的显性化。每个bug都是一次显性化的机会。不抓住这个机会,同样的bug就会以不同的面貌反复出现。

你消灭的不是bug本身,而是产生这类bug的条件。

这才是真正的根因分析。不是“为什么这段代码有bug”,而是“为什么我的系统允许这种bug存在”。

前者修复一个点,后者封堵一个面。


十、从“写代码的人”到“定义边界的人”

让我们把这一切串起来。

工程师的角色正在经历一次根本性的重新定义。

过去,你的工作是写代码。你的价值由你写的代码的质量和数量决定。

现在,代码由AI写。你的工作变成了——

定义AI工作的边界。

什么是边界?

边界是规则。“在这个系统中,所有API响应必须遵循这个格式。”

边界是约束。“任何数据库操作必须通过这个原语层,不允许直接SQL。”

边界是验证。“每次提交必须通过这组检查,不通过不允许合并。”

边界是接口。“这个模块对外暴露这三个方法,其余全部私有。”

边界是“不”。“不,我们不在这一层做缓存。”“不,这个功能不需要配置化。”“不,这个抽象不必要。”

你的价值不再是“我能写什么”,而是“我能定义什么样的边界,让AI在其中产出正确的东西”。

这是一种完全不同的能力。

写代码需要的是技巧——语言特性、算法知识、框架用法。

定义边界需要的是判断力——什么是必要的,什么是多余的,系统的真正约束在哪里,灵活性应该开放在哪里。

技巧可以被训练。判断力只能通过经验和反思获得。

这就是为什么资深工程师在AI时代不会贬值。恰恰相反——他们的判断力,是整个系统中最稀缺的资源。

一个初级工程师可以学会使用AI写代码。任何人都可以。

但只有经历过系统崩溃的人,才知道哪些边界是不可逾越的。

只有维护过遗留系统的人,才知道哪些“优雅的设计”最终会变成噩梦。

只有上线过大规模服务的人,才知道哪些假设在真实流量下会崩塌。

这种经验无法通过训练获得。这就是Naval所说的“specific knowledge”——独属于你的、无法被标准化传授的知识。

AI时代,specific knowledge的载体从“手指上的代码能力”变成了“脑子里的系统判断力”。

载体变了,本质没变。


十一、如何面对那些贩卖焦虑的口号

“程序员将在两年内被取代!”

“AI已经可以独立完成项目了!”

“不学AI你就完了!”

深呼吸。

口号的目的是制造情绪,不是传递信息。

每一次技术变革都伴随着同样的叙事结构:新技术出现 → “旧技能将消亡” → 恐慌 → 卖课 → 现实逐渐展开 → 变化确实发生了但远没有口号说的那么极端。

还记得“no-code will replace developers”吗?

还记得“blockchain will replace databases”吗?

还记得“agile will eliminate project failure”吗?

变化是真实的。口号描述的方式是失真的。

判断一个变化是否真实,看它是否改变了底层的激励结构。判断一个口号是否失真,看它是否过度简化了这个改变。

AI确实改变了底层激励结构。写代码的边际成本趋近于零——这是真实的。这意味着能写代码不再是竞争优势——这也是真实的。

但“程序员消失”?这就是过度简化了。

代码生产的自动化不等于软件工程的自动化。代码只是软件的一部分——甚至不是最难的部分。

最难的部分是什么?

理解业务需求中的矛盾和模糊。

在不确定性中做出不可逆的技术决策。

管理一个系统在多年演进中的复杂性。

协调多个团队对“什么是正确的”的不同理解。

在紧急故障中快速判断根因。

这些能力,AI在可预见的未来都无法替代。不是因为AI不够强。是因为这些问题本身没有确定的答案,需要在特定上下文中做出权衡。

AI能解决有确定答案的问题。人解决需要权衡的问题。

所以,面对口号,保持两种能力:

第一,区分信号和噪音。AI改变工程方式——这是信号。“程序员两年消失”——这是噪音。

第二,把焦虑转化为行动。与其恐惧被取代,不如问自己:我的哪些能力是AI放大器的一部分?我的哪些能力只是在做AI已经可以做的事情?

聪明的人不恐惧变化,也不无视变化。他们重新定位自己在变化中的位置。


十二、普通团队的实操系统

理论说够了。谈谈一个普通团队,明天早上该怎么做。

好的系统不需要英雄。它需要流程。

以下是一个Harness Engineering的实操工作系统,你可以从明天开始使用。

第一步:盘点你的系统原语

花一天时间,和团队一起列出你们系统中的所有原语。

不要想象。去看代码。

你们的错误处理是怎么做的?有统一模式吗?还是每个模块各自为政?

你们的日志是怎么打的?有规范吗?还是每个人凭感觉?

你们的API设计遵循什么约定?URL命名?参数校验?响应格式?错误码?

数据库访问有统一的抽象吗?事务怎么管理?连接池怎么配置?

列出来,分成三类:已有且好的、已有但差的、缺失的。

第二步:补齐和修正原语

先修正“已有但差的”。这些是你系统中正在被AI放大的负面模式。

再补齐“缺失的”。每个缺失的原语都是一个AI可能犯错的灰色地带。

每个原语都应该有三样东西:一个清晰的接口定义,一组使用示例,一组反面示例(“不要这样用”)。

反面示例特别重要。AI很容易从正面示例中“过度泛化”。告诉它“不要”比告诉它“要”更有效。

第三步:建立验证循环

从最简单的开始:

一套覆盖核心路径的自动化测试。不需要100%覆盖率。先覆盖最重要的20%路径。

一组架构规则检查。“不允许直接导入内部模块。”“不允许在Controller层调用数据库。”“不允许在工具函数中使用全局状态。”这些可以用简单的lint规则实现。

一个PR review检查清单。不是代码层面的,而是架构层面的:“这个PR是否引入了新的依赖?”“是否修改了公共接口?”“是否新增了抽象层?”如果答案是“是”,就需要更严格的人工审查。

第四步:建立“Bug→规范”的转化流程

每次修复AI产出的bug时,多做一步:

这个bug对应什么规范?规范是否已经存在?如果不存在,创建它。创建后,添加到验证循环中。

这个流程不需要复杂的工具。一个共享文档加上纪律就够了。

关键不是工具,是纪律。

第五步:渐进式信任

不要一开始就让AI做所有事情。

从低风险的任务开始:写测试、写文档、做简单的CRUD。验证AI在你的原语系统中是否表现良好。

逐步扩大范围:更复杂的业务逻辑、跨模块的功能、性能敏感的代码。每扩大一步,都确认验证循环能捕获问题。

信任是earned,不是granted。对AI也是一样。

第六步:持续迭代

每周回顾:

本周AI产出了多少需要大幅修改的代码?

哪些修改是因为原语不清晰导致的?

哪些修改是因为验证循环有漏洞导致的?

哪些修改是因为模型本身的局限导致的?

前两类是你能控制的。第三类不是。

把精力花在前两类上,持续缩小AI犯错的空间。

这不需要专门的“AI工程师”。这是每个工程师的日常工作的一部分。就像测试不需要专门的QA团队(虽然有也好),原语维护和验证循环也是每个工程师的责任。


十三、真正的竞争优势

最后,让我们谈谈竞争。

AI模型是公共资源。GPT、Claude、Gemini——所有人都能用同样的模型。

模型不是竞争优势。从来不是。

真正的竞争优势是:谁能最快地把组织经验转化为AI可执行的系统。

想想这意味着什么。

公司A有十年的行业经验,但这些经验全在老员工的脑子里。AI对公司A来说就是一个通用工具——能写代码,但写出来的代码跟任何其他公司的AI写出来的没有本质区别。

公司B同样有十年的行业经验,但他们把这些经验编码成了系统原语、验证规则、架构约束、反面模式库。AI在公司B的系统中工作,就像一个浸泡了十年的资深员工——它自动遵循公司B独有的实践,产出的代码体现了公司B独有的工程哲学。

公司A的AI是通用AI。公司B的AI是定制AI。两者之间的差距,就是Harness Engineering的差距。

这不是关于谁用了更贵的模型。这是关于谁把自己的独特知识变成了系统。

再说直白一点:

模型是发动机。你的Harness是底盘、悬挂、轮胎、导航系统。同一台发动机装在不同的车身上,表现天差地别。

大多数公司在拼发动机。聪明的公司在造车身。

而造车身的能力——把组织经验系统化的能力——是不可复制的。因为每个组织的经验是独特的。这就是你的护城河。

不是AI的能力。是你驾驭AI的能力。

不是模型有多聪明。是你的系统有多聪明。


结语:回到第一性原理

把所有的噪音去掉,AI对软件工程的影响可以用一句话概括:

代码生产的边际成本趋近于零。

从这一个事实出发,所有的推论都是必然的:

既然代码便宜了,那么决定代码质量的因素——原语、约束、验证——就变得更重要了。

既然AI能写代码了,那么人的价值就从“写代码”转移到“定义什么样的代码应该被写”。

既然产出变多了,那么过滤和审查——做减法——就成了最稀缺的能力。

既然模型是公共资源,那么竞争优势就在于你的Harness——你的系统、原语、验证循环、组织知识的编码化。

这就是Harness Engineering。不是一套工具。是一种思维方式。

它的核心信念是:

AI不需要被“管理”。它需要被“约束”在正确的结构中。

人的价值不在于做AI做不了的事。而在于定义AI应该做什么。

系统的质量不取决于最强的那个组件。取决于组件之间的边界定义得有多清晰。

不要追逐更强的模型。构建更好的系统。

模型会过时。系统会积累。

这是属于你的复利。


写代码的时代正在结束。设计系统的时代正在开始。你准备好了吗?