Agent 研习舱

chapter 03 / 全景

Harness 是什么

围绕模型的编排框架:它编码了「模型独立完成不了什么」

上一章的循环解决了「Agent 怎么转起来」。这一章回答一个更大的问题:围着模型的那一整套东西,到底是什么?

定义:围绕模型的编排框架

Agent Harness(智能体挽具)是围绕 AI 模型构建的编排框架:它管理多轮交互、上下文、工具调用和状态传递,决定 Agent 如何分解任务、何时重置上下文、如何评估输出质量。

「Harness」原意是马具/挽具——马有力气,但要靠挽具才能拉车。模型有智能,但要靠 Harness 才能:

  • 记住这个任务已经进行到哪了(模型自己不记得);
  • 真正执行一个工具调用(模型只会「说」要调用什么);
  • 在跑偏时被拉住、在完成时停下来;
  • 中断之后还能接着干。

Anthropic 的经典论述也从这里出发——先区分 workflow(预定义编排)与 agent(模型自主决定过程),再给出核心设计原则:找到最简方案,仅在需要时增加复杂度

Anthropic2024-12-19

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 专门负责回答一个问题:这个外循环还要不要继续转?

  1. 1L2450构造:停止条件是一条评估器链
    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 思维:把「模型无法自己判断的事」显式做成组件。

  2. 2L111138should_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 为什么停了」。还有个防御细节:某个评估器自己抛异常时只记警告、不拖垮循环。判断停止的代码,自身绝不能成为崩溃源。

  3. 3L153199状态快照:停止条件也要可恢复
    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 注释已在节选中保留。

以上为 Apache-2.0 许可的 openJiuwen 源码节选,仅截取教学所需片段;完整实现见 GitHub(固定 commit)

内外双循环是值得记住的结构:内循环负责「把这一步做对」,外循环负责「这件事还要不要继续做」。停止条件评估器链(轮数、token 预算、超时、完成承诺)正是 Harness 替模型做出的、模型自己做不了的判断。

一个工业级案例:三 Agent Harness

Anthropic 在长时程应用开发场景给出过一个完整的 Harness 设计实录:受 GAN 启发的三 Agent 架构——

Planner(把需求扩展成规格)→ Generator(逐功能实现)→ Evaluator(用 Playwright 实际操作应用来验收)

两个设计细节比架构本身更有启发:Agent 之间通过文件通信(持久、可审计),且每个 sprint 有协商好的验收合同(Evaluator 不凭感觉验收)。

Anthropic Engineering2026-03-24

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 已答

  1. Q1对 Agent Harness 最准确的定义是?

  2. Q2「新模型发布时应重新审视 Harness」的原因是?

  3. Q3openJiuwen 的 LoopCoordinator 如何决定外循环是否继续?

  4. Q4Anthropic 的三 Agent Harness(Planner → Generator → Evaluator)中,Agent 之间如何通信?