返回博客列表
最佳实践2026-07-0224 分钟阅读

总结与展望:Harness工程的迭代哲学与被否决的方案

迭代哲学 · 三轮评审 · 被否决方案 · Reasoning Sandwich · 双路径对称 · 未来路线

WeClaw_69_总结与展望:Harness工程的迭代哲学与被否决的方案

第四季系列文章第 8 篇(总第 69 篇) - 迭代哲学 · 三轮评审 · 被否决方案 · Reasoning Sandwich · 双路径对称 · 未来路线


📚 专栏信息

《从零到一构建跨平台 AI 助手:WeClaw 实战指南》专栏 · 第四季

专栏定位:面向开发者和技术决策者的实战专栏,用真实案例和完整代码带你理解如何构建生产级 AI 应用

本文是第四季的收官之作,回顾整个 Harness Engineering 对齐迭代的历程——从初始评估到 V3 最终方案,总结三轮评审的淬炼过程,深入分析被否决的方案(特别是 Reasoning Sandwich 的降级),提炼工程思考,并展望未来路线。


👨‍💻 作者与项目

作者简介:翁勇刚 WENG YONGGANG 新概念龙虾-WeClaw 开发团队负责人,一群专注于跨平台 AI 应用的实践者 理念:"再复杂的技术,也能用代码讲清楚"


📝 摘要

本文结构概览: 回顾 WeClaw Harness Engineering 对齐迭代的完整历程——从 4.3/5.0 的初始评估,到 V1 方案的 6 个 Critical Issues,到 V2 的 3 个阻塞项,再到 V3 的可编码实施。重点分析三轮评审中暴露的深层问题:双路径不对称、流式不可逆性、API 契约假设错误。以 Reasoning Sandwich 的降级为案例,讲解"何时放弃一个设计"的工程判断。最后展望未来路线——从"增强型单 Agent"到"多 Agent 编排 + 确定性约束"的范式演进。

核心问题: 一个方案从"看起来完美"到"可以编码实施",中间需要经历什么?为什么有些设计在文档层面成立,在代码层面却崩溃?

关键成果

  • 提炼了三轮评审中的核心工程教训
  • 完整的 7 差距对齐路线图和状态总览
  • Reasoning Sandwich 降级的深度反思
  • 未来 3-6 个月的技术演进方向

适合读者:关注 AI Agent 工程化的开发者、架构师、技术决策者

阅读时长:约 20 分钟

关键词迭代哲学三轮评审被否决方案Reasoning Sandwich双路径对称未来路线


一、回顾:从 4.3 分到 V3 方案

1.1 评估结论

在系列开篇(#62),我们对 WeClaw 进行了六层 Harness 成熟度评估:

Prompt Layer          ████░░  4.0
Context Layer         █████░  5.0  ← 最强层
Tools Layer           ████░░  4.0
Orchestration Layer   █████░  4.5
Multi-Agent Layer     ████░░  4.0
Safety & Observability█████░  4.5

综合 Harness 成熟度    ████░░  4.3 / 5.0

4.3 分——一个不错的起点,但远非终点。7 个差距领域(G1-G7)构成了迭代方向。

1.2 V1 → V2 → V3 的淬炼历程

V1 方案(初始规划)
  ↓ 三视角评审 → 6 Critical + 6 Warning + 4 Suggestion
V2 方案(修订版)
  ↓ 代码级深度评审 → 3 阻塞项 + 5 风险项
V3 方案(最终版)→ 可编码实施

每一轮评审都发现了上一轮无法发现的问题。这不是因为前面的评审不够认真,而是因为修复了表层问题后,更深层的问题才会浮出水面。就像一个洋葱:你剥掉外面那层皮,才能看到里面那层。


二、三轮评审的核心发现

2.1 V1 → V2:架构级修正

V1 方案最大的问题是"只考虑了非流式路径"。6 个 Critical Issues 中有 3 个与此相关:

编号问题根因
C1chat_stream 全面遗漏方案只描述了 _chat_impl 的注入点
C2Checklist continue 时序错误没有考虑 add_assistant_message 的执行顺序
C5Reasoning Sandwich 不可行没有考虑 reasoning 模型不支持 function calling

V2 修复:确立了"双路径对称覆盖"原则——所有 Hook 注入必须同时覆盖 _chat_impl(非流式)和 chat_stream(流式)两条 ReAct 路径。

2.2 V2 → V3:代码级验证

V2 方案在文档层面看起来完美,但代码级评审发现了"文档说有、代码说没有"的问题:

编号问题发现方式
B1ExecutionTracker.get_recent_calls() 不存在读 agent.py L77-178,发现只有字段,无方法
B2chat_stream 缺少 _validate_tool_relevance读 L2488-2530,发现流式路径遗漏此校验
B3Reasoning Sandwich has_tool_calls=False 逻辑矛盾分析模型调用时序,发现无法在调用前预知结果

B1 的教训:方案中写 self._execution_tracker.get_recent_calls(3),看起来合理。但如果去读代码,这个方法根本不存在——recent_success_calls 是一个字段,没有公开的访问方法。文档层面的合理性 ≠ 代码层面的可行性。

B2 的教训:这是一个潜伏的现有系统 Bug——非流式路径有 _validate_tool_relevance 校验,流式路径没有。这意味着流式模式下模型可以调用任何工具而不被拦截。新功能注入前,先修复现有路径的不对称。

B3 的教训:Reasoning Sandwich 希望在"最终回复阶段"切换到 reasoning 模型。但"最终回复"的标志是 has_tool_calls = False——这个值在模型调用返回后才知道。你无法在调用前就知道返回不会有工具调用。时序矛盾是最难发现的设计缺陷——它在逻辑上自洽,但在时序上不可能。

2.3 5 个实施风险项

编号风险V3 修复
R1流式 Checklist 用 continue 导致 UX 混乱改为后置告知模式
R2依赖注入入口是 gui_app.py 而非 assistant.py修正引用
R3EventBus 不支持子实例为角色 Agent 创建独立 EventBus() 实例
R4AgentPool 向后兼容风险GENERAL 角色不传额外参数
R5default.toml 有编码乱码区域配置添加在 [agent.trace] 之后

三、流式不可逆性 —— 最重要的工程发现

3.1 问题的本质

WeClaw 的流式路径通过 yield delta_content 实时将文本发送给用户。这意味着:

模型生成 "好的,我已经完成了修改。"
  → yield "好的,"          → 用户看到了 ✅
  → yield "我已经完成了"     → 用户看到了 ✅
  → yield "修改。"           → 用户看到了 ✅
  → 此时检查 Checklist → 发现问题!
  → 但文本已经全部发给用户了,无法回收 ❌

这就像脱口而出了一句话——说出去的话泼出去的水,你只能补充,不能撤回。

3.2 影响范围

这个发现影响了两个关键设计决策:

CompletionChecklist 的流式策略(#67):

  • 非流式路径:文本未发送,可以 continue 重入循环 → 静默修正
  • 流式路径:文本已发送,只能 yield 追加告知提示 → 后置告知

Reasoning Sandwich 的降级(见第四节):

  • 原计划在"最终回复阶段"切换到 reasoning 模型
  • 但流式路径下,"最终回复"的文本已经在逐步 yield
  • 无法在 yield 开始前切换模型

3.3 通用工程教训

流式架构的不可逆性是一个通用约束——不仅影响 WeClaw,也影响所有使用流式 LLM API 的应用:

操作流式下可行性替代方案
拦截并重入❌ 文本已 yield后置告知
撤回已发送文本❌ 单向流不可能
切换模型(中途)❌ 已开始生成在下一步切换
追加提示✅ 新的 yield后置告知模式

四、被否决的方案 —— Reasoning Sandwich 降级全记录

4.1 原始设想

在 ReAct 循环中,不同阶段使用不同"推理强度"的模型:

Step 1-5(规划阶段)  → DeepSeek-Reasoner(高推理,深度思考)
Step 6-20(执行阶段) → DeepSeek-V3(中推理,快速执行)
Step 21-25(验证阶段)→ DeepSeek-Reasoner(高推理,严格审查)

"三明治"模型:强-弱-强,规划和验证用强推理,执行用普通推理。

4.2 第一轮评审(V1→V2)发现的问题

问题1:reasoning 模型不支持 function calling

DeepSeek-Reasoner 是一个"推理专用"模型——它可以生成深思熟虑的文本,但不能调用工具。这意味着它无法在"规划阶段"调用工具(因为规划也需要调用搜索工具等)。

V2 的修复:将 Reasoning Sandwich 限制在"最终回复阶段"——此时 Agent 已经完成了所有工具调用,只需要生成最终文本回复。

4.3 第二轮评审(V2→V3)发现的矛盾

问题2:时序矛盾

即使限制在"最终回复阶段",仍然有时序问题:

# ReAct 循环中的关键代码(简化)
response = await self.model_registry.call_model(messages, tools=tools)
# 调用完成后,才知道 response 是否有 tool_calls
has_tool_calls = len(response.tool_calls) > 0

# 如果 has_tool_calls = False → 这是最终回复
# 但模型切换需要在 call_model 之前决定!
# → 你不知道这次调用会不会有 tool_calls

这是一个因果倒置:你无法在调用前预知调用结果。

4.4 降级决策

V3 将 Reasoning Sandwich 降级为实验性骨架

class ReasoningScheduler:
    """阶段感知模型选择器(实验性)。
    
    设计约束:
    - Reasoning 模型不支持 function calling,仅用于纯文本生成
    - 仅在 CompletionChecklist 触发的额外步骤中生效
      (此时明确无工具调用,是 checklist 重入步骤)
    """
    
    def should_switch(self, is_checklist_retry: bool, step_idx: int) -> str | None:
        """仅当明确为 Checklist 重入步骤时,才返回 reasoning model_key。"""
        if not is_checklist_retry:
            return None
        if self._verification_model:
            return self._verification_model
        return None

关键设计is_checklist_retry = True 是一个已知的确定性信号——当 Checklist 拦截并重入循环时,这一步明确是"自检修正步骤",不需要工具调用。此时可以安全切换到 reasoning 模型。

4.5 联合启用条件

V3 为 Reasoning Sandwich 设定了严格的启用条件(非本方案范围):

  1. CompletionChecklist 已稳定运行 2 周无误报
  2. _chat_impl 的 Checklist continue 分支内添加模型切换逻辑
  3. 调用时不传 tools 参数(确保 reasoning 模型不需要 function calling)

4.6 教训总结

教训说明
文档 ≠ 实现方案文档上完美的设计,可能在代码层面有根本性矛盾
时序矛盾最隐蔽逻辑自洽不代表时序可行——"先有鸡还是先有蛋"在工程中也存在
降级 ≠ 失败将设计降级为骨架不是失败,而是更诚实的工程判断
确定性信号最可靠不确定的信号(如 has_tool_calls)不如确定性信号(如 is_checklist_retry

五、其他被否决的方案

5.1 否决清单

方案为什么否决我们选择了什么
重构 _chat_impl 为 Pipeline侵入性太高,agent.py 3296行运行稳定Hook 注入(侵入性最小)
LangGraph/AutoGen 替换编排外部依赖,与 EventBus/AgentPool 架构不兼容自建 RoleOrchestrator
ToolRegistry 层面做角色限制影响所有 Agent 实例,无法会话级隔离AgentPool 层面过滤
独立进程实现熵管理过度设计,asyncio.Task 已足够后台 Task
Checklist 用 LLM 判断token 成本高,延迟不可控纯规则检查
流式 Checklist 用 continue 重入文本已 yield 给用户,continue 导致重复后置告知模式

5.2 否决方案的共同特征

被否决的方案都有一个共同特征:它们看起来更"优雅"或更"强大",但实际风险不可控

  • Pipeline 重构更优雅——但回归风险大
  • LangGraph 更强大——但与现有架构不兼容
  • LLM Checklist 更智能——但成本和延迟不可控

我们的选择标准是:风险可控 > 架构优雅 > 功能强大


六、7 差距对齐状态总览

6.1 路线图

M0(Day 1-2): 前置基础设施修复
  → Task 0.1: ExecutionTracker.get_recent_calls()(3行)    ✅ 可立即实施
  → Task 0.2: chat_stream 补全 _validate_tool_relevance(10行)✅ 可立即实施

M1(Week 1-2): 确定性约束 + Pre-completion Checklist
  → Task 1: ConstraintEngine(~200行)     ✅ 依赖 M0
  → Task 2: CompletionChecklist(~200行)   ✅ 无依赖,可与 Task 1 并行

M2(Week 3-4): Loop Detection + 熵管理
  → Task 3: LoopDetector(~180行)         ✅ 无依赖
  → Task 4: EntropyManager(~250行)       ✅ 无依赖

M3(Week 5-7): 角色化多 Agent + 自适应 Harness
  → Task 5: RoleOrchestrator(~300行)+ AgentRoles(~150行)+ TokenBudget(~150行)
  → Task 6: AdaptiveHarness(~250行)      ⏳ 需 TaskTrace 数据积累 1-2 周

M4(Week 8): Reasoning Sandwich 骨架
  → Task 7: ReasoningScheduler(~150行)   ⏳ 实验性,仅骨架不注入

6.2 代码量汇总

里程碑新模块新增行数agent.py 改动
M0--13行
M12~400~28行
M22~430~10行
M34~850~10行
M41~150不注入
合计9~1830~61行

6.3 配置汇总

# config/default.toml — 新增 7 个配置节

[agent.constraint_engine]      # G1
enabled = false

[agent.completion_checklist]   # G5
enabled = false

[agent.loop_detection]         # G6
enabled = false

[agent.entropy_manager]        # G3
enabled = false

[agent.roles]                  # G2
enabled = false

[agent.adaptive_harness]       # G4
enabled = false

[agent.reasoning_sandwich]     # G7(实验性)
enabled = false

所有功能默认关闭——逐项开启,灰度上线。


七、提炼:六个工程原则

从整个迭代过程中,我们提炼出六个可复用的工程原则:

原则1:双路径对称覆盖

如果系统有两条执行路径(如流式/非流式),所有新功能必须同时覆盖两条路径。

验证方法:每次新增 Hook 注入点时,在两条路径的代码中搜索同一方法名。

原则2:代码级验证优先

方案文档的合理性不等于代码层面的可行性。每个设计决策都必须对照源码验证。

验证方法:对每个方案中的代码引用,实际读取对应源文件确认方法/字段/签名存在。

原则3:Hook 注入优于架构重构

在稳定系统中新增功能时,侵入性最小的方案优先于最优雅的方案。

验证方法:评估方案时,将"改动范围"和"回归风险"作为一级评估维度。

原则4:流式不可逆性

流式输出的内容不可回收。所有在"最终回复前"的拦截逻辑,在流式路径上需要替代方案。

验证方法:每个在 _chat_impl 中使用 continue 的逻辑,检查 chat_stream 中是否可行。

原则5:降级优于崩溃

当设计存在根本性矛盾时,降级为骨架或实验性功能,比强行实施更好。

验证方法:每个新功能都有明确的"启用条件"和"降级策略"。

原则6:配置驱动灰度

所有新功能默认关闭,逐项开启。每个功能有独立的配置节。

验证方法:检查每个新功能的配置项是否有 enabled = false 默认值。


八、未来路线

8.1 短期(1-3 个月)

M0-M2 实施:完成前置修复、确定性约束、Checklist、Loop Detection、熵管理。

  • 预期收益:Agent 执行可靠性提升 30-50%
  • 验证指标:循环检测命中率、Checklist 触发率、约束引擎拦截率

8.2 中期(3-6 个月)

M3 实施:角色化多 Agent + 自适应 Harness。

  • 预期收益:复杂任务成功率提升 40-60%
  • 验证指标:角色化任务的 token 消耗 vs 单 Agent、任务完成率

Reasoning Sandwich 联合启用:在 Checklist 稳定后,尝试在自检步骤中使用 reasoning 模型。

  • 前提:Checklist 误报率 <10%

8.3 长期(6-12 个月)

Harness-Bench 对标:在 Harness-Bench 的五大失败模式上,将 WeClaw 的防护覆盖率从平均 3.8 星提升到 4.5 星以上。

社区反馈循环:收集使用 WeClaw 的开发者反馈,持续优化自适应 Harness 的模式挖掘算法。

学术发表:将 WeClaw 的 Harness 工程实践整理为案例研究论文——"From Prompt Engineering to Harness Engineering: An Iterative Approach to Agent System Alignment"。

8.4 成熟度目标

当前状态(4.3/5.0)               目标状态(4.8/5.0)

Prompt Layer          4.0  →     4.5(+自适应 Prompt)
Context Layer         5.0  →     5.0(维持领先)
Tools Layer           4.0  →     4.5(+ConstraintEngine)
Orchestration Layer   4.5  →     5.0(+Checklist + LoopDetection)
Multi-Agent Layer     4.0  →     5.0(+RoleOrchestrator)
Safety & Observability 4.5 →     5.0(+EntropyManager)

综合成熟度             4.3  →     4.8

九、给同行的建议

如果你也在构建 Agent 系统并考虑 Harness Engineering 对齐,以下是我们的建议:

9.1 先评估,再规划,后实施

不要跳过评估直接做方案。WeClaw 的评估发现了 7 个差距——如果你不做评估,可能只关注了 2-3 个,遗漏了关键的差距。

9.2 多轮评审,逐层深入

第一轮评审关注架构("方向对不对"),第二轮评审关注代码("实现可不可行"),第三轮评审关注细节("边界情况有没有处理")。

9.3 尊重流式架构的约束

如果你的系统有流式输出,记住:流式是不可逆的。所有在"最终回复前"的拦截逻辑都需要流式路径的替代方案。

9.4 降级不是失败

将功能降级为"实验性骨架"是一种成熟的工程判断。它意味着你承认了当前设计的局限性,同时保留了未来改进的空间。

9.5 配置驱动灰度

永远不要一次开启所有新功能。每个功能有独立的 enabled = false 配置,逐项开启,观察效果,再决定下一个。


十、系列总结

第四季共 8 篇文章,覆盖了 WeClaw Harness Engineering 对齐的完整旅程:

编号主题核心贡献
#62总体技术分析六层模型评估框架 + 7 差距识别
#63确定性约束引擎ConstraintEngine 设计 + 三层校验链
#64角色化多 Agent 协作RoleOrchestrator + EventBus 隔离 + Token 预算
#65熵管理EntropyManager + 四类清理任务 + 空闲调度
#66自适应 HarnessAdaptiveHarness + 模式挖掘 + 安全边界
#67Pre-completion Checklist双路径差异策略 + 流式不可逆性
#68Loop Detection三级检测 + 渐进响应 + 锚定消息注入
#69(本文)总结与展望迭代哲学 + 被否决方案 + 未来路线

核心信息

Agent = Model + Harness。 当所有人都在追逐更强的模型时,真正决定 Agent 表现的,是它运行的"线束"架构。Harness Engineering 不是一次性工程,而是一个持续迭代的过程——从评估到规划,从实施到评审,从 V1 到 V3,每一步都在收敛到更好的方案。

感谢阅读第四季系列。如果你在实践中也遇到了 Harness 工程相关的挑战,欢迎在 GitHub 上讨论。


📖 相关文章

第四季全系列

前三季精选


本文是 WeClaw 专栏第四季的收官之作(总第 69 篇)。如果这个系列对你有帮助,欢迎给项目点个 Star ⭐