从让 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 应该做什么。
系统的质量不取决于最强的那个组件。取决于组件之间的边界定义得有多清晰。
不要追逐更强的模型。构建更好的系统。
模型会过时。系统会积累。
这是属于你的复利。
写代码的时代正在结束。设计系统的时代正在开始。你准备好了吗?