同一个模型,为什么结果差10倍?差的不是模型,是 Harneess

89 阅读17分钟

Trae 是一款非常优秀的作品,本文图片就由 Trae 生成

article-cover.jpg

引言

我在很早之前有个错觉:用的是同一个模型,结果应该差不多

在上一篇文章 使用 trae 中遇到的一些问题 ,分享了我从 Claude Code 迁移到 Trae 时遇到的问题

为此,我做了一组严格的对照实验:

  • 相同的模型:分别测试了 GLM5 和 Kimi 2.5
  • 相同的起点:新窗口,干净的上下文
  • 唯一变量:Claude Code vs Trae

结果呢?同样的模型、同样的提示词,Trae 的表现明显不如 Claude Code。更具体地说:

  • 在 Claude Code 中能正确调用 Skill 并按流程执行本地脚本
  • 在 Trae 中模型直接忽略了脚本调用步骤,自己猜测实现
  • 有时候模型反问完就直接结束工作了,任务没完成
  • 有时候又能正常执行

当时的发现是:在执行过程中上下文不断增加,然后导致一部分信息被忽略了

那么,同样的模型,同样的提示词,为什么换个工具结果就差这么多?

先说结论,差的不是模型,是 Harness


二、什么是 Harness?为什么它比模型更重要?

Harness,直译是“拴带”——它是包裹在模型外面的整套系统。

接着我们看看 Anthropic 官方文档里是怎么说的:

Claude Code serves as the agentic harness around Claude: it provides the tools, context management, and execution environment that turn a language model into a capable coding agent.

翻译一下,Claude Code 是一个智能体编排框架,包裹在 Claude 模型外面。它提供工具、上下文管理和执行环境,把一个语言模型变成一个有能力的编码 Agent。

业界对 Harness 的核心共识是:

Agent Harness = 包裹 LLM 的运行时基础设施,管理工具调度、上下文工程、安全执行、状态持久化和会话连续性。LLM 只负责推理决策。2026 年的关键洞察:竞争差异化的重心已从 Model 转移到 Harness。

在 AI Agent 的语境下,Harness 包括以下几个核心组件:

  • 工具设计:给模型提供什么工具?一个通用的 bash 还是五十个专用工具?
  • 上下文管理:如何处理超长任务中的上下文增长?
  • 任务分解:如何把复杂任务拆解为可管理的子任务?
  • 反馈机制:如何让模型知道自己做得好不好?
  • 安全边界:如何防止提示注入、保护凭证?

方便理解就是,如果把模型比作一台发动机,那么 Harness 就是变速箱、转向系统、底盘和轮胎 那么同一台发动机装在拖拉机上和装在跑车上,表现天差地别

Anthropic 的工程团队在他们的工程博客中反复强调一个观点:

Harness 编码了关于 Claude 不能独立完成什么的假设。但这些假设会随着模型的进步而过时。

这句话非常关键,Harness 不是静态的,它必须跟随模型的能力演进不断调整。一个为 Sonnet 4.5 设计的 Harness,到了 Opus 4.5 时可能就变成了累赘。

三、为什么有的 Agent 输出稳定,有的却很随机?

要理解这个问题,我们需要拆解 Agent 在执行任务时会遇到的几个核心失败模式。

3.1 信息稀释:上下文越吵,信号越弱

症状:Skill/指令/需求在短对话中被遵守,在长对话中被忽略。

根因:LLM 的注意力是有限的。上下文越长,每条信息的"注意力权重"越低。这是 Transformer 注意力机制的数学特性——softmax 在长序列上的分布更均匀,峰值更低。

信息稀释的数学本质:

短上下文(3K tokens):
  Skill 工作流的注意力权重 ≈ 0.40
  其他信息的注意力权重 ≈ 0.60
  → Skill 是主要信号,被遵守

长上下文(12K tokens):
  Skill 工作流的注意力权重 ≈ 0.10
  其他信息的注意力权重 ≈ 0.90
  → Skill 被淹没,被忽略

3.2 上下文焦虑:越长的任务,越容易“跑偏”

症状:Agent 做到一半突然说"我已经完成了",但你一看,明显还有很多没做。

根因:Anthropic 发现了一个他们称之为"上下文焦虑"(Context Anxiety) 的现象——当模型感知到上下文窗口快满时,会提前结束工作,就像学生看到考试快结束了就匆忙交卷。

Agent 的内心独白:

"上下文已经用了 80%... 我是不是该收尾了?"
"算了,这个功能不做了,先交差吧。"
"用户应该不会注意到我跳过了这一步..."

3.3 无限循环:模型"上头"了

症状:Agent 反复调用同一个工具,或者一直在"搜索 → 看结果 → 再搜索"中打转,永远停不下来。

根因:LLM 没有内在的"停止信号"。我们人会想"我已经搜了 5 次了,够了",但 LLM 没有这个概念——它只会机械地继续循环。

Agent 的行为模式:

第 1 轮:web_search("React 性能优化")
第 2 轮:web_search("React 性能优化 最佳实践")
第 3 轮:web_search("React performance optimization 2025")
第 4 轮:web_search("React 渲染优化 虚拟列表")
第 5 轮:web_search("React memo useMemo useCallback 区别")
...
第 20 轮:还在搜...

无限循环这种情况,大家是不是在网页上遇到的更多?评论区可以聊聊看

3.4 自我评估偏差:模型"自恋"了

症状:Agent 做完工作后说"我已经完美地完成了任务",但我们一看,代码有 bug、功能没实现、逻辑有漏洞。

根因:Anthropic 的实验发现,LLM 评价自己的工作时,它会倾向于“自信地”给出高分——即使结果很明显是中等的。
这个问题在主观任务上尤其严重。比如设计一个网页,没有二元的“对”或“错”,模型几乎总会说“这个设计很好”。
即使在有可验证结果的任务上,模型有时也会对自己的代码过于乐观,比如下面这个场景

Agent 的自我评价:

Agent: "我已经完成了用户认证模块的实现。"
Agent: "代码质量很高,遵循了最佳实践。"
Agent: "所有功能都已正确实现。"

打开代码一看:
- 没有 CSRF 防护
- JWT 没有过期时间
- 登录接口没有限流

这就解释了为什么很多 Agent “看起来在干活,实际交付的东西不能用”——没有外部验证者,Agent 的"完成"只是它自己认为的完成,不是真正的完成。

3.5 单点故障:模型"挂了"

症状:API 调用失败、网络超时、Provider 限流,Agent 直接崩溃,之前的工作全部丢失。

根因:没有错误恢复机制。一次 API 失败 = 整个对话作废。

Agent 的崩溃日志:

[INFO] 调用 OpenAI API...
[ERROR] Rate limit exceeded. Please retry after 60s.
[INFO] 对话终止。所有进度丢失。

3.6 工具设计不当: 给了工具但模型不会用

Claude Code 团队在设计工具时发现,工具设计本身就是一门艺术。他们提出了一个很好的比喻:

想象你被给了一道难题。你需要什么工具?纸笔是最低限度,但你会被手算限制。计算 器更好,但你得会用。电脑最强大,但你得会写代码。

关键不是给模型多少工具,而是给它“匹配其能力”的工具。一个很好的例子是 Claude Code 团队设计 AskUserQuestion 工具的过程:

  • 第一次尝试:在 ExitPlanTool 中添加问题参数 → 混淆了 Claude,因为计划和问题冲突
  • 第二次尝试:修改输出格式让 Claude 输出结构化问题 → 不可靠,Claude 会丢失格式
  • 第三次尝试:创建专用的 AskUserQuestion 工具 → 最终成功

这个过程说明:工具设计需要反复实验,不是一步到位的。

3.7 缺乏任务分解:一口吃成胖子

很多 Agent 的问题在于:拿到一个复杂任务后,试图一次性完成。这就像让一个人一口气吃完一大桌菜——不是能力问题,是方法问题。
Anthropic 的实验显示,将任务分解为“Sprint”(冲刺),每个 Sprint 完成一个特定功能,然后由评估器检查质量,这种方式的输出质量远远超过单个 Agent 一次性完成。

在他们的对比实验中:

方式耗时费用
单个Agent 20 分钟$9
完整Harness 6 小时$200

贵了 20 倍,但质量差异是“立即显现的”。

四、Harness 怎么解决这些问题?

4.1 解决信息稀释:信息优先级 + 上下文预算

普通

模型:让我先看看项目结构...(读取 20 个文件)
模型:让我再看看依赖...(读取 package.json)
模型:让我再看看...(上下文已经 12K tokens)
模型:用户要我创建页面... Skill 里写了什么来着?
模型:算了,我自己猜吧。(跳过 Skill 步骤)

好的 Harness(Hermes 的做法)  :

Harness:系统提示 = 最高优先级,压缩时永远保留。
Harness:Skill 工作流 = 高优先级,放在系统提示中。
Harness:项目结构探索 = 低优先级,压缩时优先裁剪。
Harness:工具输出 = 最低优先级,压缩时最先裁剪。

模型:Skill 工作流在上下文中始终清晰可见。
模型:按步骤执行,Step 2 调用本地脚本。

关键设计

  • 信息分层:不是所有信息都同等重要,系统提示 > Skill > 用户消息 > 工具输出**
    **
  • 保护头部:压缩时永远保留系统提示和最初几轮对话
  • 裁剪尾部:先裁剪旧的工具输出(信息密度最低),再裁剪中间轮次
  • 上下文预算:不是"能塞多少塞多少",而是"关键信息必须占多少比例"

4.2 解决上下文焦虑:预算制 + 优雅退出

普通

模型:上下文快满了... 我该收尾了... 算了,就这样吧。
结果:任务完成度 60%,但模型说"已完成"

好的 Harness(Hermes 的做法)

Harness:你还有 45 次迭代预算,继续工作。
模型:好的,继续实现下一个功能。
...
Harness:预算还剩 1 次,这是你的 Grace Call,请总结当前进度。
模型:我已完成 8/10 个功能,剩余 2 个是...
结果:任务完成度 80%,且有明确的进度报告。

关键设计

  • 迭代预算:不依赖模型自己判断何时停止
  • Grace Call:预算耗尽时不硬中断,给一次"优雅收尾"的机会
  • execute_code 不计数:程序化的工具调用不应该消耗预算,避免惩罚正常的复杂任务

4.3 解决无限循环:预算 + 退还机制

普通

模型:让我再搜一次...
模型:让我再搜一次...
模型:让我再搜一次...
(无限循环,直到 API 额度耗尽)

好的 Harness(Hermes 的做法)

Harness:你还有 45 次迭代预算。
模型:web_search("React 性能优化")
Harness:消耗 1 次预算,剩余 44。
模型:web_search("React memo 用法")
Harness:消耗 1 次预算,剩余 43。
...
模型:execute_code("npm run test")
Harness:execute_code 不计数,预算仍为 30。
...
Harness:预算耗尽。Grace Call。
模型:基于搜索结果,我总结如下...

关键设计

  • 硬性上限:不管模型想不想停,预算到了必须停
  • 智能计数:程序化调用(execute_code)不消耗预算,只有"思考型"调用才计数
  • 退还机制:如果一轮只调用了 execute_code,自动退还预算

4.4 解决自我评估偏差:Generator-Verifier 分离

普通

模型:我写完了认证模块。
模型:让我检查一下... 看起来很好!
(模型自己检查自己,永远是"很好"

好的 Harness(Anthropic 推荐的三 Agent 架构)

Generator Agent:我写完了认证模块。
Evaluator Agent:让我检查...
  - 密码明文存储?FAIL
  - 没有 CSRF 防护?FAIL
  - JWT 没有过期时间?FAIL
Generator Agent:收到反馈,修复这三个问题...
Evaluator Agent:再次检查...
  - 密码已加密?PASS
  - CSRF 防护已添加?PASS
  - JWT 过期时间已设置?PASS

Hermes 的实现方式:通过 delegate_task,可以创建一个"审查"子代理,它的 goal 是"审查代码质量",toolsets 只包含 ["file", "terminal"](只读 + 测试),不包含写权限。这实现了 Generator-Verifier 的分离。

关键设计

  • 角色分离:生成者和评估者是不同的 Agent 实例
  • 工具隔离:评估者只有只读工具,不能修改代码
  • 迭代循环:评估不通过 → 反馈给生成者 → 修改 → 再评估

4.5 解决上下文爆炸:压缩 + 分裂 + 搜索

普通

对话越来越长...
API 返回:context_length_exceeded
对话崩溃,所有进度丢失。

好的 Harness(Hermes 的做法)

Harness:上下文已用 85%,发出警告。
Harness:上下文已用 92%,触发压缩。
  - 保留:系统提示 + 最初 3 轮 + 最近 N 轮
  - 压缩:中间轮次 → 迭代式摘要
  - 创建新 session(parent_session_id 链接旧 session)
模型:继续在干净的上下文中工作。
...
用户:之前我们讨论过什么?
Harness:通过 FTS5 搜索旧 session,找到相关内容。
模型:根据搜索结果,我们之前讨论了...

关键设计

  • 预检压缩:不等 API 报错,主动检测并压缩
  • 保护头尾:系统提示和最近对话优先保留
  • 迭代式摘要:多次压缩时更新之前的摘要,而不是重新生成
  • 会话分裂:压缩后创建新 session,保持干净上下文
  • FTS5 搜索:旧 session 不删除,可以全文搜索

4.6 解决单点故障:5 级错误恢复

普通

API 调用失败 → 对话终止 → 进度丢失 → 从头开始

好的 Harness(Hermes 的做法)

Level 1:重试
  API 429/500 → 带退避重试(最多 3 次)

Level 2:Fallback
  主 Provider 失败 → 切换到 Fallback Provider
  OpenRouter → 直连 OpenAI → 本地模型

Level 3:压缩
  API 返回 context_length_exceeded → 主动压缩 → 重试

Level 4:部分恢复
  流式中断 → 使用已流式传输的内容作为最终回复
  空响应 + 上轮有内容 → 使用上轮内容

Level 5:降级
  所有恢复策略失败 → 返回当前最佳结果 + 错误信息

关键设计

  • 层级递进:从最简单的重试开始,逐步升级到更激进的恢复策略
  • 状态持久化:每轮工具执行后保存到 SQLite,崩溃后可恢复
  • 部分结果优于无结果:宁可返回不完美的结果,也不要让用户白等

4.7解决工具设计问题:像 Agent 一样思考

Claude Code 团队总结了几个关键原则:

  • 渐进式披露(Progressive Disclosure):不要把所有信息堆在系统提示词里,而是让 Agent 在需要时自己去发现。比如 Claude Code Guide 就是一个子代理,只有在用户问关于 Claude Code 的问题时才被调用,在自己的上下文里搜索文档,只返回答案。
  • 工具要匹配模型能力:随着模型变强,曾经有用的工具可能变成累赟。Claude Code就把 TodoWrite 替换为了更灵活的 Task 工具,因为更强的模型已经不需要被“提醒”了。
  • 让 Agent 自己找上下文:从 RAG(被动接收上下文)转向 Grep 工具(主动搜索代码 库),让 Agent 自己决定需要什么信息。

4.8 解决架构问题:解耦“大脑”和“双手”

Anthropic 在 Managed Agents 中提出了一个核心架构原则:解耦“大脑”(Claude 和其 Harness)、“双手”(沙箱和工具)和“会话”(事件日志)。

这带来了几个关键优势:

  • 容器变“牧羊”而非“宠物”:容器挂了可以重启,不需要“护理”。这解决了一个很大的运 维痛点。
  • 安全边界:凭证永远不在沙箱中可达,防止提示注入窃取令牌。
  • 性能提升:解耦后,首 token 时间(TTFT)的 p50 下降了 60%,p95 下降了 90%+。
  • 灵活扩展:每个“双手”都是一个工具接口,可以是容器、手机,甚至是一个宝可梦模拟 器。

五、 回到上一篇文章:这些问题如何解释

现在让我们用 Harness 的视角来重新审视使用 trae 中遇到的一些问题文章中描述的问题:

问题一:模型忽略了 Skill 中的工作流,直接猜测实现

这是典型的上下文管理问题。

文中截图我们可以看到“模型还顺便了解了下项目结构”,这意味着上下文被项目探索信息填充了,Skill 的工作流指令被稀释了。

一个好的 Harness 会确保关键指令始终在上下文中保持可见,比如通过结构化的交接文件或 Sprint 合同。

问题二:模型反问完就结束工作了

这就是“上下文焦虑”的典型表现。 模型觉得上下文快满了,就提前收工。解决方案是上下文重置或更好的上下文管理策略。

问题三:同样的提示词,不同工具的结果不同

这正是 Harness 差异的体现。Claude Code 和 Trae 虽然都是编码 Agent,但它们的工具设计 、上下文管理、任务分解策略都不同。同一个模型,装进不同的 Harness,就像同一台发动 机装进不同的车,表现天差地别。

问题四:“明明聊的好好的,怎么交付差这么多”

这是因为缺乏外部评估机制。没有独立的评估器,模型会自己说服自己“已经做得很好了”。生 成器-评估器架构的价值就在于打破这种“自我感觉良好”的循环

六、结论

如果你觉得自己的 Agent 输出不稳定,不要急着换模型。先问自己几个问题:

  • 你的提示词是否把任务拆得足够细?还是一口气把“做个完整的 XX 系统”扔给了它?同一个任务,“先创建用户表页”和“做一个包含用户管理的全栈应用”,结果会完全不同。

  • 你是否在关键节点做了检查?还是让 Agent 自己说“我完成了”就信了?尝试在关键步骤后加一步“跑一下看看”或“检查是否符合预期”,而不是直接接受。

  • 你的工作流是否被正确执行?如果你定义了 Skill 或 MCP 工具,Agent 是否真的按流程走了?还是自己“猜”了一个实现?关注 Agent 的工具调用日志,而不只是看最终输 出。

  • 你的会话是否太长了?当你觉得 Agent “前半段还行,后半段开始乱来”,很可能是上下文已经太长了。尝试新开一个会话,把前一轮的成果作为输入传递进去,而不是在 同一个窗口里无限继续。

  • 你是否在用适合这个模型的方式使用它?不同的 Agent 产品有不同的 Harness 设计。同一个模型,在 Claude Code 和 Trae 中的表现可能天差地别。了解你所用工具的Harness 设计理念,才能发挥模型的真正实力

正如 Anthropic 团队所说:

设计工具是一门艺术,不是科学。它取决于你使用的模型、Agent 的目标、以及它运行的环境。最好的建议?经常实验,阅读输出,尝试新事物。最重要的是,试着像 Agent一样思考。

同一个模型,结果差 10 倍。差的不是模型,是如何使用它。

张小龙说,人是环境的反应器。套在模型上也很像那么回事,模型是环境的反应器。
即,模型是 Prompt 的反应器,而 Harness,正是构建这个 Prompt 环境的建筑师


本文基于 Anthropic 四篇工程博客的核心洞察,结合 Hermes Agent 源码分析写成。
参考文章:
1. Harness Design for Long-Running Apps
2. Managed Agents: Decoupling the Brain from the Hands
3. Seeing Like an Agent
4. Multi-Agent Coordination Patterns

往期文章:
优化上下文:subAgents + Skills 为何是当前 AI 编程的黄金方案