人物雷达|Mitchell Hashimoto:每次agent犯错就改造环境的朴素工程哲学
今天我想跟你聊一位工程师——Mitchell Hashimoto。他是 HashiCorp 的联合创始人,你可能没听过这家公司,但你一定用过它的产品:Terraform、Vault、Consul、Vagrant。过去十年云计算的基础设施,有相当一部分是他参与设计的。
但今天不聊云。今天要聊他关于 AI agent 的一个观点。这个观点极其朴素,朴素到你第一反应可能是“就这?”——
当 agent 犯错,就花时间工程化一个解决方案,让它不再犯同样的错。
就这。他把这件事命名为 harness engineering(驾驭工程)。
这个观点的魅力,恰恰在于它看起来毫不性感。你想想,在关于 AI 的讨论里,大家平时都在谈什么?谈模型又更新了;谈 agent 能不能替代人;谈某个公司估值又涨了;谈今年 AGI 是不是就要来了。声音越大越戏剧,流量越大。
Mitchell 不凑这种热闹。他只讲一件事——agent 犯错之后,人该干嘛。 我越琢磨这件事,越觉得它可能是整个 AI 编程讨论里,最经得起时间考验的一句话。
咱们分几层来拆。
第一层:先搞清楚 agent 到底是什么
很多人对 AI 编程的理解,其实停留在“会写代码的聊天框”。你问它,它答;你复制,它生成。这是 chatbot 模式。
Mitchell 在《My AI Adoption Journey》里做了一个非常重要的区分——chatbot 和 agent 是两种不同的东西。
chatbot 主要靠模型已有的知识回答问题。它不进入你的环境,它不知道你的代码库长什么样,它也不会主动跑任何东西。你给它一段代码,它给你一段建议;中间要来回复制粘贴。你要纠正它,得靠你自己读完输出、发现问题、再告诉它。
agent 不是这样。agent 的最低标准,他给得很具体——至少要能读文件、执行程序、发起 HTTP 请求。 也就是说,agent 不是在回答,它是在“行动”。它能进入一个工作环境,尝试一件事,看结果,再决定下一步做什么。
这个区分看着简单,但它改变了整个协作方式。chatbot 是“我问它答”,agent 是“我给目标,它在环境里尝试”。前者每一次失败都回到 prompt——“这次我该怎么说才能让它听懂”;后者每一次失败都回到系统——“这个环境该怎么设计才能让它更容易做对”。
划重点:把 AI 当 chatbot 的人,最重要的杠杆是 prompt;把 AI 当 agent 的人,最重要的杠杆是环境。
这就是 Mitchell 观点里最重要的前提。如果你不接受这个前提,下面的所有话都听不进去。
第二层:agent 犯错意味着什么
好,假设我们接受 agent 是一个会在环境里行动的东西。那它会犯错吗?一定会。
这时候普通人会怎么想?三种本能反应:
第一种,骂模型。“Claude 就是笨。” “GPT 更新之后反而更蠢了。” 这种反应最多,因为便宜。
第二种,重写 prompt。“我再把需求讲得更清楚一点。” “我再给它加几个例子。” 这种反应看起来很勤奋。
第三种,自己上手。“算了,它搞不定,我自己写吧。” 这种反应最干脆。
Mitchell 的反应不是这三种里的任何一种。他的反应是——把这次错误,变成环境的一个永久约束。
我给你举个具体的例子。
Ghostty 是一个终端模拟器,代码在 GitHub 上开源。它的 src/inspector 目录下有一个小文件叫 AGENTS.md。这文件里写了什么?写了五句话——
- inspector 类似浏览器的开发者工具。
dcimgui.h这个头文件在哪个位置。- widget 的例子在哪里可以参考。
- macOS 上构建时,要加哪些特定参数。
- 这个包没有单元测试。
就这五条。没有高深理论,没有 AI 指南,没有 prompt 模板。全是 agent 之前犯过错的地方——它找不到 dcimgui.h 时胡乱猜测、它用错构建参数时反复失败、它不知道这个包没有测试时以为可以跑测试。每一次错误,Mitchell 都把它写成了一句环境说明。
这就是 harness engineering 的基本形状:把 agent 的每一次具体错误,沉淀成环境里的一条具体约束。
他把 harness 的形式分成两类——一类是这样的隐式提示文件,改变的是 agent 的认知上下文;另一类是程序化工具,比如截图脚本、过滤测试脚本、轻量的模拟环境,改变的是 agent 的行动能力和反馈质量。
你细想一下:这不就是你工作了十年的老工程师天天在做的事吗?写文档、建脚本、加测试、立规矩、把口头知识落成文字。只不过以前这些东西是给新员工看的,现在是给 agent 看的。
重点:harness engineering 不是什么 AI 新学科,它只是把老工程师的常识,搬进了一个新场景。
第三层:为什么这比“更好的 prompt”更值得投入
你可能会问——“写个 prompt 不就好了?为什么要搞这么重的基础设施?”
好问题。我用一个类比回答。
prompt engineering 和 harness engineering 的区别,像“出门前嘱咐孩子”和“把楼梯口装上防撞条”的区别。
出门前嘱咐孩子“别在楼梯口跑”——这是 prompt。你说得越具体越好。但嘱咐这件事的收益是一次性的,这次管用,下次可能就忘了,换一个孩子可能完全没用。
给楼梯口装一个防撞条——这是 harness。一次性投入,永久生效。不管是哪个孩子、哪天、什么状态,都有效。
这两件事都重要。但从投入产出比来看,只要是你会反复做的事情,投入到环境里的成本,收益会复利累积;投入到 prompt 里的成本,收益会随着对话消失。
Mitchell 的工作方式就是这样:他允许自己这一次写一个 prompt 把问题解决掉,但如果同一类问题出现了第二次,他会停下来想一下——这件事能不能变成一条环境里的规则?如果能,就花时间写进去。
这种思路在软件工程里叫“把人工 checklist 自动化”。它在 AI 之前就存在了几十年——写测试、做 CI、统一环境、封装脚本、加 lint、把散落的知识写进文档。Mitchell 的原创之处在于,他把这套思路显性地移植到了 AI agent 时代,并给它起了一个名字。
OpenAI 后来自己讨论 Codex 的一篇文章里,也采用了非常类似的框架——他们说,当 agent 失败时,不要问“怎么让模型更努力”,而要问“这里缺了什么能力?这个能力怎么让 agent 可读、可执行、可约束”。LangChain 干脆把这件事写进了定义——Agent = Model + Harness。模型提供智能,harness 让智能变得可用。
这些都是后来发生的事。Mitchell 更早就已经在做了。
第四层:架构不外包,agent 是 junior engineer
现在还有一个疑问——harness 做得再好,agent 不还是会犯错吗?那人类到底还干什么?
Mitchell 对此有一个非常清晰的比喻:和 agent 合作,像指导一个 junior engineer。
这个比喻我要稍微展开一下,因为它特别准。
设想你刚带一个实习生。他聪明、听话、能写代码,唯一的问题是没有工程经验——不知道你们团队的约定、不理解系统的历史包袱、对“哪里不能碰”没有感觉。这时候你会怎么安排他?
有经验的带人者,不会说“你去优化我们的订单系统”。他会说——“你看这个接口,加一个重试逻辑,重试条件是 A 和 B,不要改 C,写一个对应的单元测试,完成后我 review 一下。”
区别在哪?前者是一个无边界的开放式问题,后者是一个边界清楚、护栏齐全、验证明确的小问题。junior engineer 在后一种任务上能干得非常好;在前一种任务上,99% 会出事。
agent 目前的位置,几乎和一个聪明但没经验的 junior 完全一样。 它不是笨,它是缺上下文、缺约束、缺反馈。
所以 Mitchell 从不把架构外包给 agent。他负责代码结构、数据流、状态归属——这些决定“这个系统长什么样”的问题,他一个都不交。他把设计做好,把问题切成合适的形状,然后让 agent 在那个形状里行动。
他在 Zed 的访谈里说过一句很实在的话——如果你只告诉 agent “这个 bug 存在,修一下”,它可能真能修,但很可能是用一种锤子砸钉子的方式把症状敲掉,留下一个你以后一定要还的债。
划重点:agent 不是项目的价值判断者,不是架构负责人,更不是最终责任人。它是团队里一个速度很快、但需要被安排合适形状任务的成员。
第五层:一个不能外包的东西——责任
这是我认为 Mitchell 最有分量的一块。
他在 2025 年 10 月写过一篇文章叫《Vibing a Non-Trivial Ghostty Feature》,公开了他用 AI 完成 Ghostty 一个具体功能的全过程——16 次 agentic coding session,成本 15.98 美元,8 小时墙钟时间。很多人引用的是这些数字。
但我想让你记住的是另一段。
他在做这个功能的过程中,遇到了所谓的 slop zone——agent 生成的代码看起来合理,能跑,测试都能过,但里面藏着一个关键 bug。他尝试了几次更精确的 prompt,都没修好。
这时候,常规的工程师本能有好几条路——再换一个 prompt、再换一个模型、等下个版本出来。
Mitchell 选的都不是。他停下来,自己去学 Sparkle 框架,自己去看 Obj-C 的 protocol,自己去理解 bug 的原理。然后他在博客里写了一句,我觉得是整个 AI 编程讨论里最该被加粗的一句话:
如果 agent 找到了解法,我会学习。如果我不理解,我就回退。我不交付自己不理解的代码。
这句话为什么重要?因为今天关于 AI 编程的讨论,大部分都停在速度层面——更便宜、更快、更多产出。这些都是真的。但 Mitchell 想让你记住的另一件事是——你理解了吗?你能维护吗?它会不会回归?下一个读这段代码的人,会更容易还是更困难?
AI 可以写代码。但代码的责任不会因此外包。你可以让 agent 试、写、改、跑测试;但最终合进代码库的是你。用户坏了不会说“这是 Claude 写的所以不算”;维护者也不能把不可理解的复杂性推给模型。
划重点:AI 时代真正成熟的工程师,和不成熟的工程师,最大的差别不在于谁写 prompt 写得漂亮,而在于谁更敬畏“自己不理解的代码”。
第六层:为什么这条原则很难过时
我知道你可能会说——“这些经验不都是暂时的吗?等模型更聪明了,不就不用搞这一套了?”
Mitchell 自己就承认这一点。他在 Open Source Ready 里说,今天很多 AI 协作技巧——比如怎么管理 context、怎么打开正确的 buffer、怎么塑造反馈回路——可能都是几年后不再需要的“临时技能”。
这种自我警觉非常珍贵。很多 AI 讨论者的问题,恰恰是把当下的具体技巧说成永恒真理。
但是请注意,即使具体技巧会过时,harness engineering 背后的姿态不会过时。这个姿态是什么?
把错误当成系统的缺口,而不是模型的偶然失误。
不要指望下一次它会变聪明,要让下一次它更难犯同样的错。
用反馈回路替代人工祈祷。
让机器做重复劳动,人做判断和创造。
这些原则,软件工程已经用了三十年。它们在 Vagrant 解决“环境难复现”的时候成立;在 Terraform 解决“基础设施难声明”的时候成立;在今天 Mitchell 做 agent harness 的时候成立;在未来某个更聪明的模型来临时,很可能仍然成立。
Mitchell 自己在 2019 年接受 WIRED 采访时就说过一句话——“我这辈子做的事情有一条连续的线索:自动化那些我不想做的事。人擅长创造,计算机应该做重复劳动。”
你看,这句话放到 2026 年的 agent 时代,一个字都不用改。变的只是“重复劳动”的内容——以前是搭虚拟机、写配置、管理 secret;现在是查资料、跑测试、写样板、做 refactor。工具变了,工具背后的那条线没变。
最后划一个特别重要的重点:一个观点能不能穿越技术周期,关键看它绑定的是“当下的工具”,还是“不变的原则”。 绑定工具的观点,工具变就死了;绑定原则的观点,工具怎么变都活着。
第七层:给你的三条可直接用的 takeaway
好,理论讲完了,给你三条可以今天就用上的行动建议——
第一条:别一上来就追求一个完美 AI 流程。 Mitchell 的 harness 不是设计出来的,是从错误里长出来的。agent 跑错命令,就记录;误用 API,就加说明;忘记跑测试,就写脚本。一次修一个错,半年之后你会发现自己已经有了一整套 harness。追求一次到位的人,往往最后什么都没做。
第二条:给 agent 的任务,要像给 junior engineer 的任务。 不要说“把这个系统优化一下”,要说“只改这个模块,先读这几个文件,不要改公共 API,新增这个测试,运行这个命令”。agent 的速度会诱惑你把问题丢大,但 Mitchell 的经验恰恰相反——小块工作更容易 review、理解和迭代。
第三条:不要 ship 你自己不理解的代码。 不管 agent 多聪明,多便宜,多快——代码合进去了,责任就是你的。如果 agent 修了一个你看不懂的 bug,停下来,去学,去研究。如果学不会,回退。这个规矩听起来像在给你踩刹车,但它其实是 AI 时代最保护你的一条。
Mitchell Hashimoto 的价值,不在于他提出了什么新词,也不在于他用了哪个模型。他的价值在于,在一个嘈杂到让人恍惚的时刻,他用非常朴素的一句话,把 AI agent 这个看起来很玄的东西,拉回了工程师最熟悉的地面——环境、约束、反馈、自动化、责任。
他让你相信一件事——AI 时代的成熟工程师,可能不是最会写 prompt 的人,而是最会把一次错误,变成永久护栏的人。
这是一种很笨的智慧。但好多笨的智慧,最后都赢了。