chapter 03 / 全景
Harness 是什么
围绕模型的编排框架:它编码了「模型独立完成不了什么」
上一章的循环解决了「Agent 怎么转起来」。这一章回答一个更大的问题:围着模型的那一整套东西,到底是什么?
定义:围绕模型的编排框架
Agent Harness(智能体挽具)是围绕 AI 模型构建的编排框架:它管理多轮交互、上下文、工具调用和状态传递,决定 Agent 如何分解任务、何时重置上下文、如何评估输出质量。
「Harness」原意是马具/挽具——马有力气,但要靠挽具才能拉车。模型有智能,但要靠 Harness 才能:
- 记住这个任务已经进行到哪了(模型自己不记得);
- 真正执行一个工具调用(模型只会「说」要调用什么);
- 在跑偏时被拉住、在完成时停下来;
- 中断之后还能接着干。
Anthropic 的经典论述也从这里出发——先区分 workflow(预定义编排)与 agent(模型自主决定过程),再给出核心设计原则:找到最简方案,仅在需要时增加复杂度。
Building Effective AI Agents ↗
最成功的 Agent 实现用的是简单、可组合的模式而非复杂框架——「找到最简方案,仅在需要时增加复杂度」。区分了 workflow(预定义编排)与 agent(模型自主决定过程)。
解剖一台真实的 Harness
openJiuwen 的 agent-core 里恰好有一个显式命名的 harness/ 模块。把它和 core/ 的支撑模块放在一起,可以解剖出七层结构。点击下图各层,看每层的职责、相关概念和对应源码:
harness anatomy
点击各层查看职责与 openJiuwen 对应源码(agent-core @ 1e3a5c7a)
循环驱动层
驱动「收集上下文→行动→检查→重复」,并决定何时停
内循环(ReActAgent:模型调用→工具执行→检查中断)套在外循环(harness/task_loop:LoopCoordinator + 可插拔停止条件)里。第 2、3 章的两个源码走读正是这两层。
相关概念
openJiuwen 对应模块
值得注意的是:Harness 不是一个单一对象,而是一组性质各异的接口的集合(概念卡片:Harness 嵌合体性)——循环驱动是控制流接口,工具暴露是能力接口,上下文管理是资源接口,rails 是治理接口。谈「换一个 Harness」时,实际是在谈换掉其中某几类接口。
外循环:把「什么时候停」做成组件
第 2 章走读了 ReActAgent 的内循环。而 harness 模块里还有一个包在外面的任务外循环——DeepAgent 的 task loop。它把一个关键决策抽成了独立组件:
source walkthrough
LoopCoordinator:Harness 把「什么时候停」做成了可插拔组件
openJiuwen-ai/agent-core @ 1e3a5c7a3d · openjiuwen/harness/task_loop/loop_coordinator.py:24-210 · 提取于 2026-07-18
第 2 章的 ReAct 循环是 Agent 的内循环;而在 openJiuwen 的 harness 模块里,还有一个包在外面的任务循环(DeepAgent outer task loop)。LoopCoordinator 专门负责回答一个问题:这个外循环还要不要继续转?
- 段 1L24–50构造:停止条件是一条评估器链
class LoopCoordinator: """Coordinates the outer task-loop lifecycle. Attributes: current_iteration: Number of completed rounds (read-only). is_aborted: Whether abort was requested (read-only). stop_reason: Name of the evaluator that triggered the stop, or None if still running (read-only). """ def __init__( self, evaluators: Optional[ List[StopConditionEvaluator] ] = None, ) -> None: self._evaluators: List[StopConditionEvaluator] = ( evaluators or [] ) self._iteration: int = 0 self._token_usage: int = 0 self._aborted: bool = False self._start_time: float = 0.0 self._stop_reason: Optional[str] = None self._last_result: Optional[Dict[str, Any]] = None停止条件没有写死在循环里,而是抽象成 StopConditionEvaluator 列表注入进来——轮数上限、token 预算、超时、完成承诺……每种停止逻辑一个类。协调器自己只跟踪四个量:轮数、token 消耗、起始时间、上一轮结果。这就是 Harness 思维:把「模型无法自己判断的事」显式做成组件。
- 段 2L111–138should_continue:OR 语义 + 记录停止原因
def should_continue(self) -> bool: """Return True if the loop may proceed. Evaluates all evaluators with OR semantics — the first evaluator that returns True from ``should_stop()`` terminates the loop and records the stop reason. """ if self._aborted: self._stop_reason = "Aborted" return False ctx = self._build_eval_context() for ev in self._evaluators: try: if ev.should_stop(ctx): self._stop_reason = ev.name logger.info( "Stop condition met: %s", ev.name, ) return False except Exception: logger.warning( "Evaluator %s raised an error", ev.name, exc_info=True, ) return True任意一个评估器说停就停(OR 语义),并且记下是谁喊停的——stop_reason 之后会出现在日志和产出里,让人能回答「Agent 为什么停了」。还有个防御细节:某个评估器自己抛异常时只记警告、不拖垮循环。判断停止的代码,自身绝不能成为崩溃源。
- 段 3L153–199状态快照:停止条件也要可恢复
def get_state(self) -> Dict[str, Any]: """Export a JSON-safe snapshot for checkpointing.""" ev_states: Dict[str, Any] = {} for ev in self._evaluators: s = ev.get_state() if s is not None: ev_states[ev.name] = s return { "iteration": self._iteration, "token_usage": self._token_usage, "stop_reason": self._stop_reason, "evaluator_states": ev_states, } def load_state( self, data: Optional[Dict[str, Any]], ) -> None: """Restore state from a persisted snapshot. ``start_time`` is reset to now so that ``TimeoutEvaluator`` measures from the resume point. """ if not data: return self._iteration = int( data.get("iteration", 0) or 0 ) self._token_usage = int( data.get("token_usage", 0) or 0 ) self._stop_reason = data.get("stop_reason") self._start_time = time.monotonic() ev_states: Dict[str, Any] = data.get( "evaluator_states", {} ) for ev in self._evaluators: if ev.name in ev_states: ev.load_state(ev_states[ev.name])长任务 Agent 随时可能被打断,所以连「已经跑了几轮、花了多少 token」这样的循环状态也要能存档再读档(Checkpoint)。一个讲究的细节:恢复时 start_time 重置为当下——超时评估器从恢复点重新计时,而不是把停机时间也算进去。docstring 注释已在节选中保留。
内外双循环是值得记住的结构:内循环负责「把这一步做对」,外循环负责「这件事还要不要继续做」。停止条件评估器链(轮数、token 预算、超时、完成承诺)正是 Harness 替模型做出的、模型自己做不了的判断。
一个工业级案例:三 Agent Harness
Anthropic 在长时程应用开发场景给出过一个完整的 Harness 设计实录:受 GAN 启发的三 Agent 架构——
Planner(把需求扩展成规格)→ Generator(逐功能实现)→ Evaluator(用 Playwright 实际操作应用来验收)
两个设计细节比架构本身更有启发:Agent 之间通过文件通信(持久、可审计),且每个 sprint 有协商好的验收合同(Evaluator 不凭感觉验收)。
Harness design for long-running application development ↗
长时程应用开发的 Harness 设计实录:受 GAN 启发的多 Agent 架构(Planner → Generator → Evaluator),Agent 间通过文件通信,每个 sprint 有协商好的验收合同。
几种 Harness 形态
- Coding Harness:面向编码任务的特化形态(Claude Code、Codex CLI 都是),核心是文件系统 + 终端 + 测试反馈回路;
- Vertical Harness:面向具体行业/领域垂直定制的 Harness;
- Fat Skills Thin Harness:一种架构主张——Harness 保持薄,领域知识沉淀进可迁移的 Skills;
- Brain-Hands 解耦:模型(脑)与执行环境(手)分离,Harness 就是中间的神经系统。
本章能力在 Harness 中处于什么位置?
harness positioning
本章能力在 Harness 中处于什么位置?
本章是全景视角:七层各就各位。接下来的章节将逐层深入——第 4 章上下文管理层,第 5 章工具暴露层,第 6 章评估与进化层,第 7 章多 Agent 编排层,第 8 章运行时支撑。每一章都会回到这张图,标出自己的位置。
本章概念清单 / 点击进入概念卡片
章末测验
chapter quiz
0/4 已答
Q1对 Agent Harness 最准确的定义是?
Q2「新模型发布时应重新审视 Harness」的原因是?
Q3openJiuwen 的 LoopCoordinator 如何决定外循环是否继续?
Q4Anthropic 的三 Agent Harness(Planner → Generator → Evaluator)中,Agent 之间如何通信?