此前在讨论 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 需要将任务定义、执行、环境反馈、验证、归因和演进连接为可运行、可审计、可恢复且可持续改进的系统。
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 只描述一种拓扑,这一层还要定义这些角色如何调度。
当前覆盖:已有四种角色的分工描述。还缺调度规则:何时走代码写死的路径,何时开放循环;子任务回传什么;审查是否继承实现过程的对话;验证失败后重试几次、带什么证据;任务中断后从哪一步继续。
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 的职责不同。
⑧ 评测与演进控制面
离线或准在线评测跨任务、跨模型和跨版本进行:
- 通用 Benchmark
- 领域任务集
- 回归套件
- 多次 Trial、Pass@k
- 成功率、成本、延迟
- 安全违规率、人工接管率
- 长任务完成率、跨模型迁移效果
Agent 评测包含任务、环境、多轮执行和多个 Grader,不能只评最终文本。同一任务还需要多次 Trial 来对抗随机性(Anthropic: Demystifying evals for AI agents)。
AHE 如何使用 Eval 与 Trace
AHE(Agentic Harness Engineering)根据 Eval 和 Trace 的输出修改 Harness 组件:
2026 年提出的 Agentic Harness Engineering 要求三个可观测条件(arXiv 2604.25850):
- 组件可观测:所有可编辑 Harness 组件都有显式、可回滚的文件级表示
- 经验可观测:将海量轨迹压缩成可钻取的经验语料
- 决策可观测:每次修改先声明预期,再用下一轮结果验证
横切控制面:安全、权限与治理
数据面各层决定做什么。横切控制面决定哪些操作允许执行、用什么凭证、花多少预算、出事时影响范围有多大。它贯穿层①到层⑧,不进入数据面主路径。策略在这里定义,层②的 Gateway 和 Sandbox 负责落地。
当前覆盖:已有审批门、Sandbox 和 YOLO Classifier,主要处理单次操作是否允许。还缺身份、分面授权、密钥位置、注入防御、预算、干预记录和爆炸半径。YOLO Classifier 是一种权限决策机制,覆盖不了上述其余职责。
Anthropic 将风险写成失败概率 × 爆炸半径,防御分成环境、模型和外部内容三层。凭证放在沙箱外,提示注入即使影响模型,也无法通过沙箱读到 token。用户会批准约 93% 的权限请求,高频弹窗无法有效区分风险;中低风险交给分类器,高风险保留人工审查。权限还要看动作的实际影响,普通名称的脚本也可能删除仓库或改生产(Anthropic: How we contain Claude、Claude 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 执行策略,不编写策略。层③ 在策略拒绝或预算耗尽时停止。层④ 按脱敏和范围规则组装上下文。层⑥ 记录实际发生的操作;治理要求留下决策依据、策略版本和人工干预,失败归因才能回答「当时为什么允许」。层⑦ 判定任务是否做对,高风险动作即使测试通过仍要人工确认。
模型调整
早期的能力地图可用于对外介绍。用于指导平台建设、团队分工和技术规划时,需要进行四项调整:
- 新增任务定义与完成条件(层①)
- 将在线 Verification 与离线 Eval 分开(层⑦ vs 层⑧)
- 区分 State、Memory、Artifact、Skill(层⑤内部)
- 将 Governance、Observability、AHE 组织为横切控制面与反馈回路
Harness 应覆盖任务定义、执行、环境反馈、验证、归因和演进,并支持运行、审计、恢复与持续改进。
