Agent 执行策略拆分与继承:同类任务失败时如何按场景切换 Harness

作者:carzy2026.11.04 09:21浏览量:0

简介:当 Agent 在同一类任务上反复失败时,问题往往不在模型本身,而在它外层的执行策略没有被单独设计和切换。本文从“生成文档但格式错误”“更新系统但未真正写入”两类典型问题出发,对比统一策略、独立策略与继承式策略三种 Harness 组织方式,重点分析它们在代码复用、任务适配、维护成本和效果评估上的差异,帮助开发者判断何时应拆分执行规则、如何复用已有逻辑,以及依据什么标准切换策略。

agent-harness">Agent 执行策略拆分与继承:同类任务失败时如何按场景切换 Harness

一、问题背景:模型没变,执行方式却反复出错

在 Agent 应用开发中,一个常见现象是:模型能力看起来足够,但在某一类任务上却持续失败。例如,让它生成一个 Word 文档,它最终只把纯文本保存成了 .docx 后缀;让它更新业务系统,它完成了一轮查询后便结束流程,没有真正执行写入操作。

这两种失败都不属于“模型不知道答案”,而属于“模型外层执行程序没有做对事情”。前者的本质是文件后端选择错误,后者的本质是缺少对写操作是否真正发生的验证。更值得关注的是,这类问题往往不是随机出现,而是集中在某一类任务上重复出现。

因此,问题可以转化为:能否把某类任务需要的执行规则单独抽出来,并在合适的场景下自动启用?

这引出了 Agent 开发中一个关键但容易被忽视的对象——Harness。


二、对比对象定义:什么是 Harness 与三种组织方式

2.1 Harness 的基本含义

Harness 可以理解为包裹在大模型外部的执行控制程序。它并不改变模型权重,而是参与决定以下事项:

  • 给模型什么样的提示词和上下文;
  • 开放哪些工具或接口;
  • 如何处理中间输出与长上下文;
  • 何时继续执行、何时停止;
  • 在关键步骤之后是否增加检查;
  • 遇到异常时如何重试或降级。

换句话说,模型负责“理解和生成”,而 Harness 负责“执行和管理”。在很多 Agent 失败案例中,模型输出并没有问题,问题出在 Harness 没有针对任务特点做相应控制。

2.2 三种 Harness 组织方式

为了处理“同类任务反复失败”,通常有三种做法:

  1. 统一策略:所有任务共用同一套 Harness,逻辑简单,但难以针对特定任务优化。
  2. 独立策略:为不同任务分别维护完整的 Harness 实现,灵活但重复代码多,维护成本高。
  3. 继承式策略:保留一个基础 Harness,将专项修复写入子类,由路由逻辑选择适合当前任务的子类。

三者的关系可以用下图式的结构表示:

  1. 统一策略:
  2. 所有任务 -> 同一个 Harness
  3. 独立策略:
  4. 任务A -> Harness A
  5. 任务B -> Harness B
  6. 任务C -> Harness C
  7. 继承式策略:
  8. 基础 Harness
  9. ├── 子类 Harness A:覆盖写入检查
  10. ├── 子类 Harness B:覆盖文件后端
  11. └── 子类 Harness C:增加预算耗尽前保存产物

继承式策略的核心思想与经典面向对象设计相似:父类提供默认行为,子类只覆盖需要调整的部分,必要时通过类似 super() 的机制复用父类逻辑后再补充新检查。


三、三种策略的相同点

无论采用哪种组织方式,它们都有一些共同基础:

  1. 模型权重保持不变:三种方式都只修改执行控制逻辑,不重新训练或微调模型。
  2. 目标一致:都是为了让 Agent 在特定任务上执行更可靠,减少重复性失败。
  3. 都需要任务反馈:都需要通过执行记录、评分或成功/失败信号来判断策略是否有效。
  4. 都面向同一类问题:即“模型有能力,但执行过程存在缺陷”的场景。

这些共同点说明,Harness 的改进不是模型层的优化,而是工程控制层的优化。它更接近“流程修复”,而不是“能力提升”。


四、核心差异分析

4.1 代码复用程度

统一策略的复用程度最高,因为只有一套代码。但它无法表达“不同任务需要不同规则”的差异,所有调整都只能全局生效。

独立策略几乎没有复用。每个 Harness 各自维护完整流程,一旦公共逻辑发生变化,例如提示词模板调整或上下文管理方式改变,需要同步修改所有副本。

继承式策略在复用与差异之间取得平衡。基础逻辑保留在父类,子类只覆盖差异部分。例如:

  1. class BaseHarness:
  2. def execute(self, task):
  3. result = self.run_agent(task)
  4. return result
  5. class WriteCheckHarness(BaseHarness):
  6. def execute(self, task):
  7. result = super().execute(task)
  8. self.verify_write_occurred(task)
  9. return result

上述示意代码中,WriteCheckHarness 复用了父类的主执行逻辑,只额外增加了写入验证。它不会重复实现整套 Agent 流程。

4.2 任务适配能力

统一策略难以适应差异明显的任务。例如“生成文档”和“更新业务系统”对工具调用、中间检查、结束条件的要求差异很大,如果共用一套逻辑,很容易顾此失彼。

独立策略可以为每个任务精细调整,但任务数量增加后,维护成本迅速上升。当两个任务只需要细微差异时,维护两套几乎相同的完整 Harness 很不经济。

继承式策略允许按需覆盖。两个业务领域完全不同的任务,如果都卡在“查到了信息但没有写入”,可以复用同一个写入检查子类;两个应用场景不同的任务,如果都需要在资源耗尽前保存中间产物,也可以继承同一个保存逻辑。分组依据不是业务领域,而是失败机制。

4.3 维护成本与演进方式

统一策略维护成本最低,但任何改动都可能影响所有任务,风险集中。

独立策略维护成本最高。随着任务类型增加,重复代码不断膨胀,公共缺陷的修复需要多处同步。

继承式策略的维护成本介于两者之间。公共逻辑的修改只需在父类完成,专项逻辑的调整只影响对应子类。不过,继承层级过深也可能带来理解成本,需要合理控制继承关系。

4.4 效果评估的可靠性

这是一个容易被忽视但非常关键的差异。

如果同一批任务既用来反复修改 Harness,又用来证明修改有效,就很容易出现“过拟合”:策略只是记住了特定题目的答案,而不是真正获得了通用执行能力。

更可靠的做法是把任务分成两个不重叠的集合:

  • 发现集:用于发现失败模式、生成候选改进策略、进行迭代优化;
  • 验证集:在改进结束后才用于评估,任务内容与发现集不重叠。

三种组织方式都需要这种评估分离,但统一策略和独立策略由于结构简单,开发者更容易忽略这一点。继承式策略在实现时通常需要更明确地记录“某个子类是为哪类失败机制设计”,这反过来也促使评估过程更规范。


五、对比表格

维度 统一策略 独立策略 继承式策略
代码复用 最高,但无法表达差异 最低,大量重复 较高,公共逻辑在父类共享
任务适配 弱,只能全局调整 强,但每个任务需完整实现 较强,按需覆盖差异部分
维护成本 低,但改动风险集中 高,多处同步成本大 中等,公共改动集中,专项改动局部
扩展方式 修改唯一 Harness 新增一套完整 Harness 新增子类或覆盖方法
失败机制分组能力 弱,难以区分不同失败原因 可以实现,但结构不清晰 清晰,可按失败机制归类
评估规范性 容易混用任务集 容易混用任务集 更易区分发现集与验证集
适用团队规模 小规模、任务差异小的场景 任务类型少且差异很大的场景 任务类型多、需要持续演进的场景

六、典型场景选择

6.1 统一策略适用场景

当任务类型比较接近、执行流程高度一致时,统一策略足够。例如,一组主要做文本摘要和分类的 Agent,工具集相似,结束条件相同,失败模式也趋同。此时引入复杂继承结构反而增加不必要成本。

6.2 独立策略适用场景

当任务类型很少但差异极大,且每个任务都需要完全不同的执行流程时,独立策略更直观。例如一个任务是文件格式转换,另一个任务是长流程业务审批,两者的 Harness 几乎无法共享任何逻辑,强行抽象反而僵硬。

6.3 继承式策略适用场景

当任务类型较多,但失败机制可以归纳成少数几类时,继承式策略优势最大。例如:

  • 需要在写入后验证是否真正落库;
  • 需要根据任务类型选择不同的文件后端;
  • 需要在长任务中定期保存中间结果;
  • 需要在调用外部接口后检查返回码并重试。

这些专项规则可以分别写成子类,由路由逻辑根据任务特征选择启用。改进过的规则可以继续继承,暂时用不上的规则不必强加给所有任务。


七、选型建议

选型时不应抽象地追求“哪种更好”,而应结合以下条件判断:

  1. 如果任务差异小、流程稳定,优先选择统一策略,降低系统复杂度。
  2. 如果任务数量少且彼此几乎无重叠逻辑,可以接受独立策略,但要控制规模,一旦任务数量增长则需要重新评估。
  3. 如果任务类型多、失败模式可归纳、团队希望持续积累执行经验,继承式策略更值得采用。
  4. 无论选择哪种策略,都建议严格区分发现集与验证集,避免把“对题目的适配”误判为“通用执行能力”。

一个容易忽略的点是:选择继承式策略并不意味着要启动多个 Agent 实例。被选中的子类本身就是一个完整的 Harness,父类只提供代码复用。 在一次任务执行中,只有被选中的子类实例运行,继承树上的节点不会各自跑一轮任务。


八、迁移与使用注意事项

如果从统一策略或独立策略迁移到继承式策略,需要关注以下几点:

  1. 先梳理失败记录:把历史执行日志中的失败原因归类,找出是否存在可复用的失败机制。分组应基于“哪里出错”,而不是基于“哪个业务”。
  2. 保持父类稳定:父类应只包含真正通用的逻辑,例如基本上下文管理、默认工具加载、通用结束条件。不应为了让某个任务通过而频繁修改父类。
  3. 子类保持单一职责:每个子类最好只处理一种执行问题,例如“验证写入”或“选择文件后端”。多个问题可以组合多个子类,但要避免一个子类塞入过多无关修复。
  4. 评估任务必须隔离:用于优化子类的发现集任务,不应再出现在最终效果评估中。否则难以判断改进是否具有通用性。
  5. 留意继承深度:继承层级过深会让执行流程难以追踪。建议控制在浅层继承,必要时通过组合方式代替深继承。
  6. 记录切换依据:路由逻辑凭什么选择某个子类,应当有明确依据,例如任务特征、工具需求或历史失败类型。依据模糊会导致策略切换不稳定。

九、总结

Agent 在同类任务上反复失败,往往不是模型能力不足,而是外层执行策略没有针对任务特点进行区分。统一策略、独立策略和继承式策略分别代表了“不加区分”“完全区分”和“有继承地按需区分”三种路线。

三者的核心差异不在于模型层,而在于执行规则的复用方式、适配粒度、维护成本和评估可靠性。统一策略简单但容易全局受限;独立策略灵活但重复成本高;继承式策略在复用和差异之间取得平衡,更适合任务类型多、失败机制可归纳、需要长期演进的 Agent 工作流。

选型的关键不是追求结构上的“先进”,而是回答三个问题:要改什么、能否复用、凭什么切换。 只有把失败机制拆解清楚,才能把 Harness 改进从“打补丁”变成一套可持续积累的执行策略体系。