AI 时代之后,越来越多的词已经很难被定义。
比如 AI 本身。现在大家说的 AI,和几年前说的 AI,已经不再泛指同一个东西了。很多年前,A*算法可以被叫做 AI,后来大家说 AI,更多是在说机器学习,深度学习或者强化学习, 而现在,AI 在很多语境里几乎已经变成了 LLM,以及围绕 LLM 构建出来的一整套Application/Agent。
AI 衍生出来的很多词也是这样。比如 Agent,AI Native,还有这篇主要想聊的 Harness Engineering。
这些词的问题不是它们完全没有意义,而是它们的边界越来越模糊。不同的人在不同语境下使用同一个词,但说的可能根本不是一件事。
而在这些词里面,Harness Engineering 可能是最让我不舒服的一个。经过很多阅读,也和 LLM 反复聊了很久之后,我决定写一篇文章,整理一下我对这个词的反思和理解。
我不确定这篇文章最后会不会得出一个非常明确的结论。它可能更多还是一种 rant。但至少我想把自己的不舒服说清楚。
Harness Engineering 到底是什么?
我很多年前就接触过 harness 这个词。我之前的工作原因会接触硬件,经常会从国外寄过来一些设备,以及设备需要的连接线材。当时这些线材一般就会被叫做 cable harness 或 wire harness。
它具体的表现形式,就是一些固定的线材和接头被绑在一起,如下图所示。
在我的理解里,它的作用很直接:让两个或多个设备之间更方便、更稳定地连接。因为线和接头是固定的,所以当你发现接头多一个或者少一个的时候,你立刻就知道哪里不对。 所以在我的第一印象里:
harness ≈ 线束
我甚至一直不知道它还有“马具”的意思。对我来说,harness 从来不是“驾驭”什么东西,而更像是一个主要设备周围的连接结构或者辅助结构。
第二次接触harness,是在学习 TDD。有一个很常见的词叫 test harness。这个词对我来说也比较直观。
硬件设备的 harness 是连接各个硬件的线束,那test harness 就是围绕测试目标的一些辅助工具,用来更好地执行测试,比如 stub、mock、fixture、test runner 等等。
所以在我原来的认知里,harness 不是一个玄学词。
它大概就是:
一个复杂主体以外的,周边的一些设备。
这个理解其实挺朴素的。
但 AI 时代来了之后,Harness Engineering 突然横空出世,好像一下子变成了一个很高级的词。
问题是,似乎没有人真正给过它一个准确、稳定、被广泛接受的定义。
OpenAI 那篇很有名的文章 Harness engineering: leveraging Codex in an agent-first world里,更多是在描述他们过去几个月里如何从一个 empty folder 开始,逐步构建一个多人协作的代码仓库,以及如何让 Codex 参与这个过程。
这篇文章很有意思,但它其实并没有直接告诉你:
Harness Engineering到底是什么?
Anthropic 甚至更谨慎一点。他们在 Effective harnesses for long-running agents
和 Harness design for long-running application development里,更多使用的是harness,而不是 Harness Engineering。
也就是说,他们讨论的是:
怎样设计一个 harness,让 long-running agent 更可靠地工作?
所以我现在对 Harness Engineering 的感受很微妙。
它不是完全没意义。但它又经常被说得太大、太虚、太像一个万能词。
我目前看到互联网上对 Harness Engineering 的理解,大概可以分成三类。
1. 面向 (Coding) Agent 的局部脚手架
这是最常见的一类定义。
很多文章、视频,在说完 Harness Engineering 之后,立刻告诉你:
你需要把某些规范写到 AGENTS.md 里。 你需要把某套工作流“蒸馏”成一个 skill。 你需要马上使用 Superpower、GSD、OpenSpec。 你需要让 Claude Code 或 Codex 遵循某种固定范式。
这类东西当然不是完全没用。
比如一个 repo 里有明确的 AGENTS.md,告诉 agent 项目结构、测试方式、不要碰哪些文件、常见命令是什么,这当然可能有帮助。一个 skill 把重复流程沉淀下来,也可能有帮助。 但在我看来,这些东西更像是:
面向某个具体
agent(大概率是coding agent)的使用手册。
它不是没有价值,但它也没有那么神奇。很多时候,它只是把一个工程师自己的工作习惯写成文档,然后强迫agent这个software本身,按照这个习惯执行。
比如Superpowers 喜欢 TDD。TDD 是一种成熟方法论,也有很多人喜欢。但我其实并不喜欢TDD。一个成熟工程师完全可能有另一套不同的稳定工作方法。只要这个方法能在项目里稳定产出结果,就不一定非要用TDD。
所以我不太认同一种说法:
只要你把 agent 约束进某套流程,你的工程质量就会提高。
这件事没那么简单。
有些人好像认为,自己项目代码质量低、维护困难,是因为项目缺少一些神奇的XX.md文件。只要补上这些文件,项目就瞬间变成一个实际生产级别的项目。
这在我看来有点匪夷所思。
明明很多时候是工程能力的问题,最后却被包装成流程问题。
2. 多 Agent 协作,或者说 Agent Cosplay
第二种理解更进一步。它不只是给一个 coding agent 加规则,而是把现实工作流里的各种角色都模拟成 agent。
比如:
- PM Agent 做项目管理
- Architect Agent 做架构设计
- SWE Agent 写代码
- QA Agent 做测试
- Evaluation Agent 做评估
- Reviewer Agent 做代码审查
然后这个系统就被称为Harness Engineering。
这个方向乍一听很有吸引力。因为它非常像现实里的软件团队。现实中一个复杂项目确实不是一个人完成的,而是由 PM、工程师、QA、架构师 等等一起完成。
所以把这些角色映射到 agent 上,似乎是一件很自然的事情。
但我对这里也有很强的不适感。
因为很多所谓多 agent 协作,本质上只是 role cosplay。
你告诉一个模型:
You are a PM.
它不会因此真的变成 PM。 你告诉另一个模型:
You are a Principal Engineer.
它也不会因此真的拥有 Principal Engineer 的经验、责任和判断力。 现实里的团队分工之所以成立,不只是因为大家 title 不同,而是因为不同的人有不同经验、不同上下文、不同权限、不同责任、不同激励,也会从不同角度对同一个问题施加约束。
但很多的多 agent 系统里,这些 agent 背后可能是同一个模型,拿到的是类似的上下文,使用的是类似的推理方式,只是 system prompt 里换了一个角色名。
这时候所谓的 PM Agent、QA Agent、Architect Agent,到底是真的分工,还是只是让模型表演不同角色? 如果只是让几个 agent 轮流说话,最后互相总结、互相认可、互相评价,那我会本能地觉得很假。这只是在玩模拟公司。
3. Agent = LLM + Harness
第三种定义是最宽泛的,也是我觉得最有意思、但实践上最没用的一种。
LangChain 有一篇文章The Anatomy of an Agent Harness提出这个观点:
Agent = Model + Harness
LLM 本质上只是 next token generator。它自己不会真正管理状态,不会调用工具,不会可靠地记忆长期信息,也不会天然遵守某个业务系统的约束。
所以在 LLM 之上,你需要很多东西:
context management
memory management
state management
routing
tool calling
structured output
validation
retrieval
eval
retry
permission control
然而这些东西都可以被叫做 harness。 从概念上说,这个定义其实挺合理。因为它把 Agent 去神秘化了。所谓 Agent,不是一个突然具有自主意识的神奇东西,而是:
LLM + 一整套围绕 LLM 的软件系统
从这个角度看,harness 就是模型外部的软件。
这个定义的问题也在这里。它太宽了。如果除了模型权重本身,其他所有东西都叫 harness,那最后就变成:
上下文管理是 harness。
记忆是 harness 。
状态机是 harness 。
工具调用是 harness 。
eval 是 harness 。
业务逻辑是 harness 。
甚至整个 application 本身都是 harness。
那 Harness Engineering 和 Software Engineering 的区别到底是什么?
如果 Agent = LLM + Harness,那我们做的事情,不就是软件工程?
当然,这个定义也有它可取的地方。
它至少把很多玄乎的 AI/Agent 工程重新拉回了软件工程。所谓 context management、memory management、state management,看起来像 AI 时代的新词,但很多思想在传统软件工程里早就存在对应物。
只是现在这些东西围绕 LLM 重新组合了一次。所以这个定义在概念上可能是最正确的,但在实践指导上又是最没用的。
因为它没有告诉我具体要做什么。它只是告诉我:你需要在模型外面做软件工程。
这句话当然对,但也几乎什么都没说。
我为什么不喜欢 Harness Engineering?
我不喜欢 Harness Engineering 这个词,原因很简单:我很难通过这个词知道你到底在说什么。 用比较 AI 的说法,它自己没有做好上下文管理。
当一个人说:
这个项目需要加一点 Harness Engineering。
那他到底是什么意思?
- 是要写
AGENTS.md? - 是要给 Claude Code 做一个
skill? - 是要用
Superpowers或OpenSpec? - 是要搞一个多
agent工作流? - 是要做
context management? - 是要接
tool calling? - 还是只是想说“我们应该把这个 agent 系统做得更工程化一点”?
这些东西每一个都有自己的问题、方法论和实践技巧。单纯用 Harness Engineering 这个 umbrella term,把它们全部装进去,我觉得反而降低了讨论精度。
它听起来像一个高级方法论,但很多时候只是在用一个模糊的词覆盖一堆完全不同的问题。
这也是为什么,当一个人跟我讨论 Harness Engineering 的时候,我很多时候会本能地觉得:这个人可能还没有想清楚自己到底想解决什么问题。
不是因为这个词一定错,而是因为这个词本身太容易让人停止思考。
一旦说:
这是 Harness Engineering。
好像事情就被解释了。但实际上没有。你只是给一组复杂问题贴了一个新标签。
流行词本身的力量
其实这种事情在软件圈发生过很多次。
我是 Android 开发出身。回想起来,早些年的RxJava,或者各种 MVX 架构,都有类似的逻辑。
比如 MVVM 和 MVP 的区别到底是什么?你怎么定义它们的边界?
甚至 Google 自己的 ViewModel,在很多人的理解里,实际做的事情更像 Presenter 的职责。那到底它是 ViewModel,还是 Presenter?还是只是大家给类似问题起了不同名字?
FRP就更有趣了。
有的人只是用了 RxJava。
有的人把整个 App 的数据流都改造成 RxJava,然后强烈谴责别人不够 Reactive。
还有人会认真区分 Functional Programming、Reactive Programming 和 Functional Reactive Programming,认为它们是三种完全不同的东西。
这些争论不是完全没意义,但也经常会变成名词战争。最后大家花了很多时间讨论:
- 你这个到底算不算真正的 FRP?
- 你这个到底是不是 MVVM?
- 你这个是不是足够 reactive?
但真正重要的问题其实是:你到底在用什么办法解决什么问题?
这些历史给了我一个很深的教训:
追求流行词本身的准确定义,很多时候没有意义。
更有价值的事情,是理解它背后到底在解决什么具体问题。然后把其中有用的方法消化成自己的知识,而不是追着词跑。
- 十年前,有人要把自己的 App 改造成 “Full Reactive”。
- 今天,又有人要把自己的代码仓库改造成 “Harness Engineering 最佳实践”。
这两件事其实非常相似。不是说 reactive 没价值。也不是说 harness 没价值。
而是流行词一旦开始获得自己的生命力,就会让很多人把注意力从问题本身转移到名词本身。
这也是我对 Harness Engineering 的态度。我不是反对它。我只是觉得,当我们说 Harness Engineering 的时候,最好还是先把话说清楚。
- 如果你说的是
AGENTS.md,那就讨论AGENTS.md。 - 如果你说的是
workflow engine,那就讨论workflow engine。 - 如果你说的是
context management,那就讨论context management。 - 如果你说的是
state management,那就讨论state management。
这些东西都值得讨论。
但如果它们全部被塞进Harness Engineering这个词里,那这个词本身就很难再提供什么额外信息。
它听起来像方法论,实际上很多时候只是把旧的软件工程问题,重新包装成 AI 时代的新名词。 而真正有价值的问题,从来不是这个词叫什么,而是:
你到底遇到了什么问题? 你到底用了什么办法? 这个办法到底有没有解决问题?
离开这些具体上下文,Harness Engineering 讨论的再多,也都没有意义。