Harness Agent 的组成要素分析

📅
3 分钟阅读
·

此前在讨论 AI 友好型架构时,我们已经梳理过 Harness 需要覆盖的上下文、受控执行和反馈回路。本篇结合一段时间的实践,并对照 LangChain 的 Agent Harness 拆解、Anthropic 的 Building Effective Agents 方法论、Martin Fowler 的 Harness Engineering 框架和 2026 年提出的 AI Harness Engineering(AHE)研究,给出一份更细的组成模型。

本文给出完整模型,并逐层说明各层的职责、当前覆盖和缺失,以及三个不同性质能力的边界。本套架构正在 v2r-Agent 中落地,这是一个自适应、自成长、自迭代的 Vue 2.x → React 全自动迁移 Agent,用来将公司内的陈年Vue项目整体迁移到React上。

完整模型

Harness Agent 组成要素完整架构

Harness 需要将任务定义、执行、环境反馈、验证、归因和演进连接为可运行、可审计、可恢复且可持续改进的系统。

2026 年提出的一套 AI Harness Engineering 框架将 Harness 责任拆成 11 项:任务规格、上下文选择、工具访问、项目记忆、任务状态、可观测性、失败归因、验证、权限、熵审计和人工干预记录。当前模型明确覆盖其中约 8 项(arXiv 2605.13357)。

三种性质的能力

早期的能力拆分将这些内容放在同一层级,难以区分它们的职责。按能力性质,可分为三个面:

三种性质的能力

数据面(层①~⑤)构成 Agent 执行任务的主路径:数据从任务定义流向最终产物。

控制面(层⑥ + 治理)横切各层。治理规定每层允许执行的操作,可观测性记录各层实际执行的操作。

演进面(层⑦⑧)使用运行结果改进 Harness。它消费控制面的数据,通过失败归因提出修改假设,再通过验证判断修改是否带来收益。


① 任务定义与完成条件

当前模型缺少独立的任务定义层。该层需要定义 Agent 的任务目标、完成条件和停止条件。

任务定义与完成条件

当前覆盖:不完整。Claude Code 的 CLAUDE.md 和 Agent Skills 提供部分前馈指导,但缺少结构化的任务定义。缺少这一层时,Planner 缺少正确分解任务的依据,Validator 缺少验证目标,Agent 也缺少停止条件。

建议包含

  • 用户意图澄清
  • Task Spec:目标、范围、非目标
  • 约束条件(允许修改路径、禁止修改路径)
  • 需求分解
  • Acceptance Criteria
  • Definition of Done(可执行验证器)
  • 输出 Schema
  • 风险等级
  • 完成证据要求

任务定义可以将「修复订单页面卡顿」定义为以下内容:

goal: 修复订单页面首次渲染卡顿
scope:
  allowed_paths: [app/order/**]
  forbidden_paths: [infrastructure/**]
acceptance:
  - 首屏 P95 < 1200ms
  - 所有现有测试通过
  - 不改变接口 Schema
evidence:
  - benchmark-before.json
  - benchmark-after.json
  - test-report.xml

② 执行环境与工具

模型输出的是文本。这一层把文本变成对仓库的修改、命令和浏览器操作,并把环境里发生的事情变成下一轮可消费的观察。层①规定允许改哪些路径、怎样算完成;这一层准备对应的工作区,隔离副作用,并执行被允许的动作。

执行环境与工具

当前覆盖:已有 Tool Registry 和 Sandbox。Registry 登记函数名和参数 Schema,Sandbox 把单次命令关进隔离环境。还缺三类能力:按任务准备和回收工作区;对每次调用做超时、重试、幂等和结果裁剪;管理开发服务、浏览器和磁盘快照的生命周期。Agent Loop 决定何时调用工具、何时停止,属于层③。

LangChain 将文件系统、沙箱、bash、浏览器视为 Harness 的执行基础设施,编排、压缩和记忆另行处理(LangChain: The Anatomy of an Agent Harness)。这一层只覆盖前一类。

工作区没有按仓库准备时,Agent 会在错误的运行时或未安装依赖的目录里继续改代码。调用没有闸门时,重复的 npm run serve 会占死端口,一次卡住的 npm ci 会拖住整个任务。工具输出不裁剪时,安装日志会把任务目标和约束挤出上下文。

建议包含

  • Workspace:按任务检出指定 commit,创建 worktree 或分支,安装与仓库匹配的运行时和依赖,写入 before 基线,结束后回收进程和磁盘。v2r-Agent 迁移 Vue 2 仓库时,镜像需要对应的 Node、包管理器和可启动的原应用。
  • Isolation:文件系统范围、进程隔离、网络白名单、CPU / 内存 / 磁盘上限。凭证留在沙箱外,按调用注入。层①的 allowed_paths / forbidden_paths 在这里强制执行。
  • Tool Surface:读文件、写补丁、bash、搜索等基础动作,加上任务需要的专用动作,例如启动 dev server、截图、视觉对比、跑指定测试。MCP 和 CLI 用于注册工具,与内置函数走同一条 Gateway。工具名称、Schema、描述和错误格式会影响能否被正确调用(Anthropic: Writing effective tools for agents)。按当前步骤暴露最小工具集,或提供工具搜索,避免一次载入全部 MCP 工具。
  • Tool Gateway:参数校验、超时、重试、并发上限、幂等键、限流。同一条「启动订单页」不能因模型重复调用而开出多个抢同一端口的进程。Gateway 执行治理策略,策略定义在横切控制面。
  • Hook:项目可注入的调用前后拦截,用于附加工作目录、拦截危险命令、写文件后跑 formatter。上下文压缩、自动续跑、完成判定不要放进 Hook。
  • Observation:返回 exit code、截断后的 stdout / stderr、结构化错误、截图路径和产物引用。完整日志留在工作区,模型默认读摘要。
  • Process / Service:启动、健康检查、端口占用处理、终止残留进程。前端迁移通常要同时跑原 Vue 应用和迁移后的 React 应用,再在浏览器里对照。
  • Workspace Snapshot:用 git commit 或文件系统快照保存可恢复的磁盘状态。会话从哪条消息继续,由层③和层⑤处理;这一层保证恢复时文件和依赖还在。

同一条订单页任务若由 v2r-Agent 做 Vue 2 到 React 的迁移,环境可以定义成:

environment:
  image: v2r-workspace:vue2
  workspace:
    repo: git@internal/order-app.git
    ref: abc123
    worktree: /work/order-app
    branch: v2r/order-page
  provision:
    - npm ci
  network:
    allow: [registry.npmjs.org]
    deny: ["*.prod.internal"]
  resources:
    command_timeout: 120s
    task_deadline: 4h

tools:
  - apply_patch:
      allowed_paths: [src/views/order/**, src/components/order/**]
      forbidden_paths: [infrastructure/**]
  - bash:
      cwd: /work/order-app
  - dev_server:
      command: npm run serve
      healthcheck: http://localhost:8080
  - browser_screenshot:
      url: http://localhost:8080/#/order
  - visual_diff:
      baseline: artifacts/before/order.png

测试和 lint 在这个环境里运行,是否构成完成由层⑦判定。工具结果如何进入模型上下文由层④组装。产物的命名、版本、来源和权限由层⑤管理。一次调用是否允许、预算是否超限,由治理层决定。


③ Agent 运行时与编排

层①规定目标和完成条件,层②执行单次动作。这一层决定由谁行动、按什么顺序、用哪套工具和哪个模型、失败后怎么回流、何时停止。Planner / Coder / Validator / Refiner 只描述一种拓扑,这一层还要定义这些角色如何调度。

Agent 运行时与编排

当前覆盖:已有四种角色的分工描述。还缺调度规则:何时走代码写死的路径,何时开放循环;子任务回传什么;审查是否继承实现过程的对话;验证失败后重试几次、带什么证据;任务中断后从哪一步继续。

Anthropic 把 agentic system 分成两类:Workflow 由代码预先编排路径,Agent 由模型动态选择步骤和工具。常用组合包括单 Agent 循环、固定工作流、Orchestrator-Workers 和 Evaluator-Optimizer。多 Agent 只适用于其中部分模式(Anthropic: Building Effective Agents)。

只有角色名时,系统无法决定何时走固定路径、何时开放循环。子 Agent 把完整对话交回时,父上下文会被探索过程占满,审查也会读到实现过程中的判断。没有停止条件时,验证失败会一直重试,或在未满足层①完成条件时自行结束。

建议包含

  • Agent Loop:一次角色运行是 think → 选工具 → 观察 → 再 think,直到命中停止条件。这是编排的基本单元。类型检查失败后把错误交给修复节点再跑检查,就是一个 Loop。
  • Topology:声明有哪些角色、各角色可见的上下文、可调用的工具和默认模型。v2r-Agent 的 Planner 只读仓库并拆页面,Coder 可写补丁和启动 dev server,Validator 只跑检查和截图,不改业务代码。
  • Workflow / Agent 选用:路径事先确定时由代码编排节点,例如「先列迁移单元,再逐页进入循环」。步骤数量和分支事先不确定时用 Agent Loop,由模型选下一步。先用 Workflow 能覆盖的部分,再把判断节点交给 Loop。
  • Sub-agent:为探索、检索或并行子任务开隔离循环。子任务只继承任务说明和必要文件,不继承父对话;结束时回传结论、产物路径和状态,完整过程留在子记录里。
  • Handoff:角色或会话交接时传递任务定义、已确认约束、产物引用和未完成项,丢弃草稿推理。研究会话的探索过程不应进入实现会话。
  • Scheduling:串行、并行、汇合、投票。只在节点之间没有输入输出依赖时并行。v2r-Agent 在 Planner 拆完互相独立的页面后可以并行迁移;共享组件要先串行完成,再让依赖它的页面开工。
  • Model routing:按角色和步骤选模型。拆计划和做审查可以用更强的模型,单页改写可以用更便宜的模型。路由规则写在编排里,不要让每个角色自己挑。
  • Stop / Retry / Resume:停止条件包括层①的 Definition of Done、最大步数、预算和必须转人工的失败类型。重试要把验证证据交给下一轮,不要只说「再试一次」。续跑读取层⑤的任务状态和层②的工作区快照,从中断的步骤继续,不重新开一轮对话。

同一条订单页迁移可以编成:

runtime:
  topology: evaluator-optimizer
  roles:
    planner:
      model: opus
      tools: [read_file, grep]
    coder:
      model: sonnet
      tools: [apply_patch, bash, dev_server]
    validator:
      model: sonnet
      tools: [bash, browser_screenshot, visual_diff]
  schedule:
    - planner
    - foreach page in plan:
        loop: [coder, validator]
        max_retries: 3
  stop:
    on: [definition_of_done, max_steps, budget_exceeded]
    max_steps_per_page: 40
  handoff:
    pass: [task_spec, page_list, constraints, artifacts]
    drop: [planner_scratch, coder_rationale]

工具怎么执行由层②负责。每次模型调用带哪些上下文由层④组装。当前计划、已完成步骤和子 Agent 状态写在层⑤。编译、测试和视觉对比是否通过由层⑦判定,编排只根据判定结果决定回流或停止。并发上限、预算和是否允许生成子 Agent,由治理层限制。


④ 上下文、知识与技能

层③决定这次由谁调用模型。这一层决定这次调用实际带上哪些材料:任务定义、仓库规则、检索到的文件、Skill、工具定义,以及层②刚返回的观察。Token 预算和压缩是容量约束。还要按角色和步骤选择材料,并记录来源与过期状态。

上下文、知识与技能

当前覆盖:已有 Token 预算、压缩和 AGENTS.md 注入,主要处理装载和容量。还缺按步骤选择、检索、溯源和范围控制。全部 MCP 工具定义和整份仓库说明一旦在会话开始时注入,窗口在动手之前就被占满。

Martin Fowler 把前馈 Guide 和反馈 Sensor 分开:AGENTS.md、目录规则和 Skill 在行动前提供约束;测试、Lint、日志和截图在行动后进入下一轮上下文(Harness engineering for coding agent users)。Anthropic 的原则是为当前任务选择能提高成功率的最小高信号集合。窗口变大之后,塞入无关资料仍会降低当前步骤的信号密度(Anthropic: Effective context engineering for AI agents)。

全量装载时,订单页迁移会带上无关模块和过期约定,模型难以稳定关注当前页面的完成条件。压缩只砍 token、不保留决策和未解决问题时,续跑会重复已经做过的探索。工具定义和 Skill 正文全部前置时,Validator 也会读到只给 Coder 用的迁移手册。

建议包含

  • Context Selection:按当前角色和步骤挑选材料。Planner 需要路由和页面清单,不需要组件实现细节;Coder 需要当前页及其 import;Validator 需要验收条件和 before 基线。会话常驻只放项目概览、运行命令和安全约束。
  • Retrieval:代码搜索、符号检索、文档检索、历史任务召回。检索范围受层① allowed_paths 限制。v2r-Agent 迁订单页时,应检索 src/views/order 和它引用的组件,而不是把整个 src/store 塞进窗口。
  • Context Assembly:按稳定前缀组装,便于缓存命中。常见顺序是系统提示、工具 Schema、AGENTS.md、任务定义、本步文件、本步 Skill、最近观察。目录级规则在进入对应目录时加载;专项知识在调用对应能力时加载。
  • Provenance:每条注入材料带上来源、版本和过期状态。Vue 2.5 仓库不应直接采用针对 2.6 的经验条目。已废弃的 ADR 和与实现不一致的规则会变成错误上下文。
  • Scope Control:禁止 .env、密钥、forbidden_paths 和任务范围外的目录进入上下文。层②的 Isolation 限制写入;这一层限制模型看见什么。
  • JIT / Progressive disclosure:Skill 先注入名称和触发条件,正文在命中时再加载。工具定义按当前角色暴露最小集合,或提供工具搜索。层⑤定义 Skill 对象;这一层决定何时把哪一份 Skill 放进窗口。
  • Compression:接近窗口上限时,保留决策、进度、未解决问题和验证方法,把原始工具输出外置到工作区。层②已经裁剪单次观察;这一层处理跨多轮的历史。
  • Context Cache:把不随步骤变化的前缀固定下来,减少重复构建。角色切换、工具集变化或 AGENTS.md 改写会打断缓存,应显式记录。

同一条订单页迁移的上下文可以定义成:

context:
  always:
    - AGENTS.md
    - task_spec
  by_role:
    planner:
      retrieve: [src/router, src/views]
      skills: []
    coder:
      retrieve: [current_page, imported_components]
      skills: [vue2-to-react]
    validator:
      retrieve: [acceptance, artifacts/before/order.png]
      skills: []
  exclude:
    - "**/.env*"
    - "infrastructure/**"
  compaction:
    keep: [decisions, progress, open_issues, verification]
    offload: [raw_tool_stdout]
  cache:
    stable_prefix: [system, tool_schemas, AGENTS.md]

工具结果如何产生由层②负责。谁在调用、子 Agent 回传什么由层③决定。Task State、Memory、Artifact、Skill 的对象模型在层⑤。层⑥需要保存本轮上下文快照,失败归因才能回答「当时模型看见了什么」。


⑤ 状态、记忆、产物与技能的职责

早期的能力拆分将「会话状态 / 项目记忆 / 技能系统」归为同一层,但这些概念记录的信息和使用方式不同。

四种不同概念

Task State 任务状态

记录当前任务的执行位置:

  • 当前计划、已完成步骤、Pending TODO
  • 当前分支、已执行测试
  • 子 Agent 状态、失败次数
  • Lease、锁和任务心跳

用于断点续跑、并发协作和流程一致性,不记录长期 Memory。

Memory 长期记忆

记录可跨任务复用的信息:

  • 用户偏好、项目约定
  • 历史失败经验、某类任务的最佳策略
  • 模块负责人、架构知识
  • 已验证的经验规律

用于跨任务复用经验,不记录当前任务的进度。

Artifact 产物

记录本次任务产生的内容:

  • 代码 Diff、计划文档、测试报告
  • 构建产物、截图、失败日志
  • 验证报告、Episode Package

Artifact 应有命名、版本、来源、生命周期和权限。Google ADK 将 Artifact 与 Session、State 和 Memory 分别管理(Google ADK Artifacts)。

Skill 技能

定义 Agent 可执行的操作及其执行方式:

  • 操作指南、Prompt、脚本
  • 工具组合、触发条件
  • 输入输出 Schema、验证方法

AHE 研究发现,工具、Middleware 和长期记忆对性能提升的贡献超过 System Prompt。这些组件需要能够分别表达、修改、评测和回滚(arXiv 2604.25850)。

建议:概念模型应将这四类对象分开,物理实现可以共用文件系统或数据库。


⑥ 可观测性与失败归因

当前覆盖:已有轨迹、事件图和 Token 追踪。这些信息记录执行过程,但不足以定位失败原因。

完整可观测性还应包括

  • Prompt / Context 快照(每次 Agent 调用时的完整上下文)
  • Tool 输入输出
  • Agent 与子 Agent 调度关系
  • 模型、工具、Skill、配置版本
  • 延迟、Token、费用
  • 重试、超时、取消
  • 环境状态变化
  • 文件与 Artifact 变化
  • 用户审批与人工干预

失败归因需要建立因果链:

失败归因因果链

缺少这条归因链时,失败后可能直接修改 Prompt 并再次执行,无法确定修改是否针对实际原因。

AI Harness Engineering 框架将 failure attribution、entropy auditing 和 intervention recording 列为独立责任,而不只是 Trace(arXiv 2605.13357)。


⑦ 验证与质量闭环

在线验证在 Agent 执行过程中持续进行:

  • 编译是否通过
  • 单测是否通过
  • 功能是否满足需求
  • 是否引入回归
  • 是否符合架构规范
  • 是否满足 Definition of Done
  • 是否可以结束 Agent Loop

Martin Fowler 的 Harness 模型强调,Agent 需要同时具备前馈 Guide 和反馈 Sensor。测试、静态分析、日志和审查 Agent 属于反馈控制,用于在结果交给人类前修正执行结果。

Verification 与 Evaluation 的职责不同。

Verification vs Evaluation

⑧ 评测与演进控制面

离线或准在线评测跨任务、跨模型和跨版本进行:

  • 通用 Benchmark
  • 领域任务集
  • 回归套件
  • 多次 Trial、Pass@k
  • 成功率、成本、延迟
  • 安全违规率、人工接管率
  • 长任务完成率、跨模型迁移效果

Agent 评测包含任务、环境、多轮执行和多个 Grader,不能只评最终文本。同一任务还需要多次 Trial 来对抗随机性(Anthropic: Demystifying evals for AI agents)。

AHE 如何使用 Eval 与 Trace

AHE(Agentic Harness Engineering)根据 Eval 和 Trace 的输出修改 Harness 组件:

AHE 元闭环

2026 年提出的 Agentic Harness Engineering 要求三个可观测条件(arXiv 2604.25850):

  1. 组件可观测:所有可编辑 Harness 组件都有显式、可回滚的文件级表示
  2. 经验可观测:将海量轨迹压缩成可钻取的经验语料
  3. 决策可观测:每次修改先声明预期,再用下一轮结果验证

横切控制面:安全、权限与治理

数据面各层决定做什么。横切控制面决定哪些操作允许执行、用什么凭证、花多少预算、出事时影响范围有多大。它贯穿层①到层⑧,不进入数据面主路径。策略在这里定义,层②的 Gateway 和 Sandbox 负责落地。

安全、权限与治理

当前覆盖:已有审批门、Sandbox 和 YOLO Classifier,主要处理单次操作是否允许。还缺身份、分面授权、密钥位置、注入防御、预算、干预记录和爆炸半径。YOLO Classifier 是一种权限决策机制,覆盖不了上述其余职责。

Anthropic 将风险写成失败概率 × 爆炸半径,防御分成环境、模型和外部内容三层。凭证放在沙箱外,提示注入即使影响模型,也无法通过沙箱读到 token。用户会批准约 93% 的权限请求,高频弹窗无法有效区分风险;中低风险交给分类器,高风险保留人工审查。权限还要看动作的实际影响,普通名称的脚本也可能删除仓库或改生产(Anthropic: How we contain ClaudeClaude Code auto mode)。AHE 把权限、熵审计和人工干预记录列为独立责任。只记工具调用不足以回答当时为什么允许(arXiv 2605.13357)。

只按工具名允许或拒绝时,bash 无法区分 npm test 和删除仓库。弹窗过密时,合并主干和改一个 Vue 文件会被连点通过。凭证进入沙箱后,仓库注释或 MCP 返回里的注入指令可以读到 token。v2r-Agent 若能访问 infrastructure/** 或生产网段,一次跑偏会超出单个页面迁移的范围。

建议包含

  • Identity:每个 Agent 有身份和租户。v2r-Agent 迁订单页时,身份绑定 order-app 租户和对应仓库,不能看到其他项目的密钥和工作区。
  • Policy Engine:集中计算允许、拒绝或升级。输入包括身份、任务风险等级、目标路径、工具名、参数和当前预算。层①的 allowed_paths / forbidden_paths 和风险等级在这里变成可执行规则。层② Gateway 只执行判定结果。
  • 分面授权:文件、命令、网络、MCP 分开授权。允许在 src/views/order/** 写补丁,不等于允许访问 *.prod.internal,也不等于允许调用未审计的 MCP。审计过的连接器不代表它处理的数据已经审计。
  • Secrets:凭证留在沙箱外,按调用注入。模型上下文和沙箱文件系统默认看不到 NPM_TOKEN 或内网证书。数据分类和脱敏规则同时约束层④:密钥文件不得进入窗口。
  • Prompt Injection 防御:仓库注释、网页、MCP 返回和工具输出都是不可信内容。环境层用沙箱限制爆炸半径,模型层用分类器和探针处理中低风险越权,高风险操作不因分类器放行而跳过人工。
  • 分层决策:低风险、可回滚的操作可自动放行,例如允许路径内的 apply_patch。中低风险命令走分类器,例如 bash。合并主干、部署、删除、生产变更走人工接管。不要把所有操作都变成弹窗。
  • Budget:Token、步数、费用和调用次数的配额写在治理层。层③在配额耗尽时停止,不自行提高限额。
  • Audit / Blast Radius:记录策略版本、判定、执行者和人工干预。限制工作区、分支和网络出口,使一次失败停在 v2r/order-page 这条分支上。回滚使用 git revert 或工作区快照,并写入干预记录。

同一条订单页迁移的治理可以定义成:

governance:
  identity: v2r-agent
  tenant: order-app
  policy:
    files:
      allow: [src/views/order/**, src/components/order/**]
      deny: [infrastructure/**, "**/.env*"]
    network:
      allow: [registry.npmjs.org]
      deny: ["*.prod.internal"]
    commands:
      auto: [apply_patch]
      classifier: [bash]
      human: [git push origin main, deploy, delete]
  secrets:
    location: outside_sandbox
    inject: [NPM_TOKEN]
  budget:
    tokens: 2000000
    max_steps_per_page: 40
  blast_radius:
    worktree: /work/order-app
    branch: v2r/order-page
    rollback: git revert
  audit:
    record: [policy_id, decision, actor, intervention]

层② 的 Isolation 和 Gateway 执行策略,不编写策略。层③ 在策略拒绝或预算耗尽时停止。层④ 按脱敏和范围规则组装上下文。层⑥ 记录实际发生的操作;治理要求留下决策依据、策略版本和人工干预,失败归因才能回答「当时为什么允许」。层⑦ 判定任务是否做对,高风险动作即使测试通过仍要人工确认。


模型调整

早期的能力地图可用于对外介绍。用于指导平台建设、团队分工和技术规划时,需要进行四项调整:

  1. 新增任务定义与完成条件(层①)
  2. 将在线 Verification 与离线 Eval 分开(层⑦ vs 层⑧)
  3. 区分 State、Memory、Artifact、Skill(层⑤内部)
  4. 将 Governance、Observability、AHE 组织为横切控制面与反馈回路

Harness 应覆盖任务定义、执行、环境反馈、验证、归因和演进,并支持运行、审计、恢复与持续改进。


1216 字 · 178 段落
ximing

Follow onGitHub

相关文章