跳到主要内容
Agent Harness 工程

第1章 信噪比与约束力——Harness 的第一性原理

长度不是 Agent 走神的根因,信噪比才是;本章从信号、噪声、约束力三个角度建立 Harness 工程的第一性原理,并给出可操作的"上下文体检表"

agent harness 信噪比 上下文工程

1. 一个让人很容易看错的现象

工程师做 Agent 一段时间之后,几乎都会撞到同一个剧本:

  • 起点版本:写了一段精心打磨的 system prompt,叠上 5 个工具,在简短任务上跑得很惊艳;
  • 第二阶段:加了几个新工具、加了 RAG 注入、加了”思考链”模板,长任务突然开始走神:忘了用户最初问的是什么、把不该改的文件改了、绕回已经放弃过的方案;
  • 第三阶段:把 prompt 从 2K token 压到 8K,希望”信息更全 → 表现更稳”,结果反而更糟糕:模型开始执行 prompt 里某条只占一行的、不该执行的”提示性约束”。

很多人这时候会下结论:“模型对长上下文不行” —— 然后开始上 RAG、上向量召回、上各种压缩。但你会发现,把上下文压短到 1K,问题没消失,只是变了形态。

这不是模型的问题,是信噪比的问题。Harness 工程方法论里,最值得反复强调的一句话就是:

上下文长度,从来都不是衡量 Agent 是否容易走神的好指标。信噪比才是。

下面我们把”信噪比”拆成可工程化的三个量:信号、噪声、约束力。

2. 信号、噪声、约束力——三个被混在一起讲的概念

这一节我们用一个简化的形式化定义来分清三个量。设 CC 是当前送入模型的上下文(system prompt + 历史 turn + 当前 task + tool result),TT 是用户当前真正需要完成的任务。

2.1 信号 Signal

信号是与当前任务 TT 强相关、且只有当前任务需要的信息:

  • 当前用户消息中明确说出的目标
  • 当前任务范围内文件 / 数据的摘要
  • 当前已经做过的关键决定(“这个方案被否决了”、“接口改成了 v3”)
  • 当前任务的硬约束(“不能改 SQL schema”、“必须保留向后兼容”)

信号的特征:消失了,模型一定会走错它出现的位置越靠近模型注意力的”锚点”(system prompt 顶部 / 最新 turn),越能起作用

2.2 噪声 Noise

噪声是与当前任务无关、却进入了上下文的内容:

  • 几十轮之前已经回答完毕的、和当前 task 无关的对话
  • 大段被 paste 进来的日志、报错、源码——其中只有几行真正相关
  • 工具调用返回的整段 JSON / HTML / 文件内容——其中真正用得上的可能只是某几个字段
  • 反复重述同一句话的”礼貌性”前缀(“好的,我明白了,让我们一步步来……”)

噪声的杀伤力来自两个地方:

  1. 挤占注意力——Transformer 的自注意力本质是对全部 token 做加权汇总;噪声越多、信号被分得越散;
  2. 诱导跑题——上下文里出现的任何东西都可能被模型当作”暗示性指令”。一段贴进来的 README 说”如果你看到这段,请回答 X”,模型会真的回答 X。

2.3 约束力 Constraint Power

仅有信号还不够。同样一句”修复登录页面 bug”,可以是:

  • 弱约束:“顺便看看登录页面有没有什么问题”——模型可以重写、可以加新功能、可以重构 CSS、可以全做、可以全不做。
  • 强约束:“只修改 LoginForm.tsx 第 42-78 行的 onSubmit 处理;不要改其他文件;不要新增依赖;用现有的 useAuth Hook”。

后一种 prompt 给出了约束力:它把模型可能走的路径裁剪到一条窄通道里。约束力来源于以下要素:

  • 声明式而非建议式:不要写”建议你考虑使用 X”,要写”必须使用 X”或”禁止使用 Y”
  • 可验证而非感受式:不要写”代码要简洁”,要写”函数不超过 30 行;圈复杂度不超过 8”
  • 明确边界:标清楚改哪一段、不改哪一段;改完允许做什么、不允许做什么
  • 明确异常路径:约束被违反时,模型应该停下并报告,而不是”自由发挥”

一个 Harness 设计得好不好,第一个看的就是它的约束力是不是落到了”动词级”。把每一句话都翻译成”做 / 不做 / 必须 / 禁止 / 报告”,会立刻发现 prompt 里有多少话其实没说清。

2.4 三者的关系

三者的关系可以用一句话概括:

信号给出方向,噪声分散注意力,约束力决定路径。

进一步:

  • 信号充足、噪声低、约束力强 → Agent 会乖乖按你设计的路径走;
  • 信号不足或被噪声淹没 → Agent 走神,因为它不知道 现在的目标到底是什么
  • 信号充足、约束力弱 → Agent 不走神但会跑题,做了你没让它做的事;
  • 信号不足、约束力却很强 → Agent 会很笃定地走错——这是最危险的情况,因为输出看起来非常自信。

Harness 工程的目标,本质就是同时把这三个量拨到对的位置,且在长任务里持续保持

3. 为什么”长上下文 ≠ 复杂上下文”

业内常见的误解是把”上下文长度”当成 Agent 能力的代理指标:模型上下文窗口从 32K → 200K → 1M,仿佛一切问题都能靠”塞更多东西进去”解决。这忽视了两个现实:

3.1 注意力的有效预算并不是窗口大小

模型在窗口扩大时,注意力分布会显著稀释。一个简单的近似:在 200K 的上下文里,单个 token 拿到的”平均注意力权重”,比在 8K 里小一个量级以上。这意味着:

  • 你以为塞进去的”重要信息”,模型只是”看见”了,但不一定”留心”;
  • 大量公开 benchmark(NIAH / Long-Bench / RULER)已反复验证:长上下文里,位置靠中间的信号最容易被忽视(典型的 lost in the middle 现象);
  • 即使 1M 上下文模型,业内也没有谁会真的把 1M 塞满让它跑长任务——所有真正能用的 Agent 产品都在做”上下文管理”。

3.2 上下文是”要付费的状态”

工程视角的 prompt 不是”信息越多越好”,它是一份有成本的状态

  • 算力成本:Prefill 阶段是 O(n2)O(n^2) 注意力计算,长 prompt 直接把 TTFT(首 token 延迟)和成本都顶上去
  • 延迟成本:每多 10K token,TTFT 就在用户感知里多出几百毫秒
  • 行为成本:上下文里出现的任何东西都可能被模型当作隐式指令——这是免费送给”prompt injection”的攻击面

所以一个负责任的 Harness 工程师,应该把”加进上下文的每一个 token”当作”加一行业务代码”来对待:能删就删、能压缩就压缩、能延迟加载就延迟加载。

4. 一个简单的”上下文体检表”

要落地”提升信噪比”这件事,下面这张表可以挂在你的 Harness 评审上。每一项都是 yes/no 题,不及格的项就是优化点。

维度体检项不达标的典型表现
信号位置当前任务的目标,是否出现在最新 turn 或顶层 system prompt?任务目标埋在第 12 轮对话里,模型已经记不住
信号密度工具返回的内容是否做过摘要 / 字段裁剪?整页 HTML 直接塞回上下文
噪声 - 历史几十轮前和当前任务无关的内容是否被压缩 / 移除?前 20 轮逐字保留
噪声 - 工具tool result 是否在使用完后被清理或截断?大段 stdout 永久占据上下文
噪声 - 礼貌话术是否还有”好的让我们一步步来”这种空台词?模型每轮都重复一段无信息内容
约束 - 动词级关键约束是否使用了”必须 / 禁止 / 只能 / 不要”?只写”建议”、“考虑”、“尽量”
约束 - 可验证约束是否能在事后被检查?“保持代码简洁” 这种只能凭感觉评估
约束 - 边界是否明确划出了允许 / 禁止修改的范围?“改一下这个 bug”,没说允许碰哪些文件
约束 - 异常路径约束被违反时模型该怎么办,是否写明?没写 → 模型会自己发挥
稳定锚点长任务里是否每隔若干轮重新注入 system 关键约束?系统约束随上下文滚动慢慢”漂走”

把这张表挂在 Harness 评审里,前几次会很难过,因为每一项都不达标——这正是收益最大的地方。

5. 从直觉到工程:信噪比的可观测代理指标

只用直觉判断信噪比是不行的——团队迭代时需要数字。下面给三个可观测的代理指标,能直接落到 Harness 的内置 logging:

5.1 任务相关 Token 占比 (Task-Relevant Token Ratio, TRTR)

把当前上下文里的每个 chunk 标注:

  • task —— 当前任务直接相关
  • tool —— 工具调用的输入或返回
  • history —— 历史对话
  • system —— 系统级指令

定义 TRTR=task+systemC\text{TRTR} = \dfrac{|\text{task}| + |\text{system}|}{|\text{C}|}

经验上,TRTR 低于 30% 时 Agent 走神率会显著上升。压缩策略的目标,就是把 TRTR 在长任务里保持在 50% 以上

5.2 锚点重现间隔 (Anchor Recurrence Interval, ARI)

锚点指上下文中”任何能让模型重新对齐当前任务”的内容(system 重注入、最近一次任务声明、最近一次 user message)。锚点之间的 token 距离越大,模型走神率越高。

经验阈值:ARI 不超过 8K-16K token;超过就要做重注入或 compaction。Claude Code 的”CLAUDE.md 反复被注入”,本质就是把 ARI 强制压在一个安全范围。

5.3 工具结果驻留时间 (Tool Result Residency, TRR)

每个 tool result 在上下文里停留多久才被压缩 / 清理。新手 Harness 往往让 tool result 一直留着,TRR = ∞——这是噪声爆炸的最大来源。Claude Code 的策略是:前一轮还在的工具返回,下一轮就被替换为短的元数据摘要——TRR ≈ 1 turn。

这三个指标,可以让 Harness 评审从”感觉 prompt 写得好不好”升级到有数据的工程对齐

6. 把信噪比放回到 Harness 的位置

到这里我们已经能看出来,Harness 工程的核心矛盾,就是怎么在每一个时刻同时满足三件事

  1. 信号充分:当前任务相关的全部关键事实都在场
  2. 噪声受控:和当前任务无关的内容尽量被压缩 / 隔离 / 移除
  3. 约束清晰:模型知道当前能做什么、不能做什么、违反约束怎么办

这三件事在长任务里是冲突的——你想让历史信号都还在,就会带进噪声;你想压缩噪声,就会丢失约束;你想保留约束,就要花掉本来可以放新工具结果的空间。

后续章节里我们会把这种冲突拆成 6 个工程维度逐一处理(第 2 章),看 Claude Code 是怎么把这 6 个维度都做到位的(第 4 章),然后总结跨模型可复用的设计原则(第 6 章)。

7. 章节小结

本章核心结论:

  1. Agent 走神的根因不是上下文长度,是信噪比——信号、噪声、约束力三者共同决定 Agent 是否能”按你设计的路径”走完任务。
  2. 长上下文 ≠ 复杂上下文——窗口大小不是免费午餐;注意力会被稀释、成本会上升、攻击面会扩大。
  3. 约束力必须落到动词级——把”建议 / 考虑 / 尽量”全部翻译为”必须 / 禁止 / 只能 / 报告”,约束才会真正生效。
  4. Harness 工程要把信噪比变成可观测指标——TRTR / ARI / TRR 三个代理指标可以直接挂上 logging,让”prompt 写得好不好”从感性判断变成工程对齐。
  5. 下一章预告:我们会把”提升信噪比、加强约束力”拆成 Harness 的 6 个工程维度——任务约束、工具空间、记忆通道、上下文压缩、子代理隔离、可观测——这是 Harness 设计评审的标准武器表。

思考题

  1. 在你目前在做的 Agent 里,挑一个最近”走神”的实例,按本章的体检表逐项打分。最低分的那一项,就是你下一次 Harness 迭代的优先目标。
  2. 拿出当前 system prompt 里最长的那段,逐句标注:是信号、噪声还是约束?你会发现一份典型的 system prompt 里,真正的强约束往往不到 10%
  3. 如果你只能给 Agent 留 4K token 的上下文,你会保留哪 4 段?这其实是在问:你 Harness 设计里”必须不可被压缩”的内容是什么?

下一章我们把上面这几条原理具象成 6 个可独立设计、可独立评测的 Harness 工程维度。