同一个模型,为什么在聊天框里和在生产环境里像两个产品
很多人第一次把大模型接进真实业务时,都会遇到一个落差:在聊天框里,它讲得头头是道;一旦让它读文件、调接口、改代码、跑流程,就开始漏步骤、编参数、忘记目标,甚至在同一个错误上反复打转。
直觉上,我们会觉得是模型还不够聪明。但更常见的情况是:模型本身不差,缺的是一套能把它接进现实世界的外壳。
这套外壳,最近常被叫作 Harness Engineering。Harness 原意是马具、安全带,放在 AI 语境里,指的是模型之外的运行时系统:它负责给模型提供上下文、工具、状态、循环、验证、权限和观测。模型决定能力上限,harness 决定这套能力能不能稳定交付。
模型不是程序,它只是一次接一次的 token 预测
不管模型多强,它都有几个绕不开的限制:
- 没有真正的记忆。每次调用都从当前上下文重新开始,上次做过什么、哪些路走不通,不会自动留在脑子里。
- 没有手和眼。它不能自己打开网页、读数据库、运行测试、修改文件,除非你把这些能力包装成工具交给它。
- 不会天然多步执行。它可以在一次回答里推理,但“做一步、看结果、再决定下一步”的循环,需要外层来驱动。
- 不知道自己不知道。模型很容易给出一个看起来合理、实际上没有验证过的答案。它不会像工程师那样,先跑一遍测试再下结论。
所以,模型更像一个能力很强但只能坐在房间里说话的顾问。要让它真正干活,你得给它资料、给它工具、给它反馈,还要在它做错时兜住。
聪明模型仍然会失败的五个原因
1. 长任务里的错误会累积
假设模型单步正确率是 95%,听起来很高。但一个任务如果有 20 个步骤,每一步都独立地保持 95%,最终全部做对的概率只有大约 36%。真实任务里,步骤之间还会相互影响,错误更容易被放大。
这不是靠“再聪明一点”就能完全解决的。工程上的办法是:把长任务拆短、在关键节点做检查、允许回滚,而不是指望模型一次走对。
2. 上下文不是免费的
很多人以为,把资料全部塞进上下文,模型就能自己找到重点。实际上,上下文越长,模型越容易漏掉中间的信息,也越容易被无关内容带偏。指令一多,优先级还会互相打架。
Harness 要做的不是“塞更多”,而是“在正确的时刻给正确的信息”:该检索的检索,该摘要的摘要,该丢掉的丢掉,该固定下来的写成状态。
3. 工具不好用,模型就会乱用
工具的名字、参数、描述、报错信息,都会直接影响模型的行为。一个叫 do_stuff、参数是一大坨 JSON、失败时只返回“error”的工具,模型很难用对。
好的工具设计更像给新同事写接口文档:名字说明用途,参数少而明确,示例覆盖典型场景,报错告诉对方下一步该怎么做。工具不是给机器看的,是给一个“会推理但会犯错”的协作者看的。
4. 没有验证,就没有可信度
模型可以写出语法正确的代码,但未必能通过测试;可以总结出一份漂亮的报告,但未必没有漏掉关键数据;可以规划出一条看似合理的操作路径,但未必没有副作用。
所以,harness 里最重要的部分之一,不是“让模型做得更多”,而是“让结果可以被检查”:跑测试、做类型检查、对比 diff、 dry-run、人工确认、失败回滚。没有验证的自动化,只是把错误执行得更快。
5. 权限和副作用不能靠自觉
当模型可以删文件、发邮件、改数据库、发布文章时,光在提示词里写“请谨慎”是不够的。Harness 需要用系统的方式限制它:最小权限、沙箱、操作分级、不可逆操作二次确认、完整审计日志。
这不是不信任模型,而是承认任何执行者都会犯错。工程系统不应该建立在“它应该不会”的假设上。
Harness 到底在工程什么
可以把一套 Agent harness 拆成六层。层与层之间不是严格隔离的,但这六层基本覆盖了“让模型稳定干活”的主要工作。
第一层:上下文层
负责决定模型每一步能看到什么。包括系统指令、任务目标、历史对话、检索到的资料、当前状态、工具返回结果,以及必要时的摘要和压缩。
核心问题不是“能放多少”,而是“哪些必须放、哪些可以晚点放、哪些应该被写成外部状态”。上下文是预算,不是仓库。
第二层:工具层
负责把外部世界包装成模型可以调用的动作。包括工具 schema、参数校验、权限检查、超时重试、错误信息、幂等性设计。
一个好工具应该让“正确的用法”很容易,让“危险的用法”很难。比如删除操作默认 dry-run,写入操作要求明确的资源 ID,失败时返回可操作的错误,而不是一串堆栈。
第三层:控制层
负责驱动“计划—行动—观察—修正”的循环。包括最大步数、时间预算、token 预算、停止条件、重试策略、子任务拆分、子 Agent 协作。
没有控制层的 Agent,很容易陷入两种极端:要么一步就停,要么无限循环。控制层的价值,是让它在不确定的环境里知道什么时候继续、什么时候停、什么时候求助。
第四层:状态层
负责把“做过什么、做到哪、接下来做什么”放在模型之外。可以是一个任务文件、一份检查清单、一个数据库记录、一组 artifacts,也可以是一段结构化摘要。
状态外置的好处是:上下文丢了可以恢复,任务中断可以续跑,多个 Agent 可以交接,人也可以随时接手。不要把所有状态都押在模型的上下文窗口里。
第五层:验证层
负责判断“做完的结果是不是对的”。不同任务有不同的验证方式:代码跑测试和静态检查,数据对口径和总量,文档查引用和事实,操作看 diff 和回滚结果。
验证层最好独立于生成层。让写代码的模型自己判断代码对不对,往往不如让测试来判断;让写报告的模型自己检查数据,往往不如让脚本对一遍源数据。
第六层:治理层
负责权限、安全、审计和成本。包括沙箱、最小权限、操作审批、敏感信息脱敏、调用链追踪、token 与费用统计、异常告警。
这一层平时最容易被忽略,但一旦出事,它决定了你是能快速定位和回滚,还是只能看着日志猜。
一个具体的例子:修一个 bug
用户说:“登录页在 Safari 上点提交没反应,修一下。”
没有 harness 的做法是:把报错贴给模型,模型给出一个看起来合理的修改,复制进代码,祈祷它能用。
有 harness 的做法,会把这件事拆成一条可验证的链路:
- 读取项目结构和相关文件,确认登录页的实现位置;
- 复现问题,拿到浏览器报错或测试失败信息;
- 让模型提出假设,并只修改最小范围;
- 运行相关测试和构建,确认没有引入回归;
- 生成 diff,检查改动是否符合预期;
- 需要时再让人确认,最后提交。
模型仍然负责“想”和“写”,但“找文件、跑测试、看结果、拦住错误”由 harness 负责。模型的能力被保留,错误被系统性地减少。
常见的五个反模式
- Prompt-only:以为写一段更长的提示词就能解决所有问题。提示词重要,但它替代不了工具、状态和验证。
- 工具堆砌:给模型几十个功能重叠的工具,指望它自己选。工具越多,选择成本越高,误用概率越大。
- 无限循环:没有步数、时间、预算上限,Agent 在失败后反复重试,烧钱又烧时间。
- 上下文塞满:把所有文档、日志、历史都塞进去,结果关键信息被淹没,指令互相冲突。
- 没有评估集:每次改提示词或换模型都靠感觉,无法判断到底变好了还是变坏了。
另一个容易被忽略的反模式是过度工程:把流程限制得太死,模型明明有更好的解法,却只能按固定路径走。好的 harness 应该给模型足够的发挥空间,同时在关键边界上兜底。
如果你要开始搭一套 harness
- 先选一个窄而明确的任务。比如“根据日志定位一个已知类型的报错”,而不是“自动运维整个系统”。
- 先做确定性工具,再做自主循环。工具稳定了,模型的行为才可预测。
- 先有验证,再放 autonomy。没有测试和回滚,不要让它直接操作生产环境。
- 把状态外置。任务清单、进度、产物都落到文件或数据库里,别只留在上下文。
- 从第一天开始记录 trace。每次工具调用、每次失败、每次人工介入,都是后面优化的依据。
- 建立一个小型评估集。用真实任务做回归测试,改一次 harness 就跑一遍。
最后,把 harness 当成产品来维护:它有版本、有测试、有监控、有明确的边界。模型会换,harness 里的领域知识和工程约束会沉淀下来。
最后
模型越聪明,harness 越不是可有可无的“外壳”。恰恰相反,模型能力越强,它能触达的系统越多、能造成的副作用越大,越需要一套可靠的工程结构去承接。
模型是发动机,harness 是底盘、传动和刹车。发动机升级当然重要,但一辆只有发动机、没有底盘和刹车的车,是上不了路的。
如果你正在做 Agent 产品,不妨问自己一个问题:把模型换成一个稍弱一点的版本,这套系统还能不能稳定完成任务?如果答案是否定的,说明你真正缺的,可能不是更强的模型,而是一套更好的 harness。