Harness Engineering(驾驭工程)
驾驭工程(Harness Engineering) 是将包裹 LLM 的 基础设施层(agent harness / execution harness) 视为独立工程面的系统方法论。名称源自 “harness” 的驾驭含义:不是限制模型能力,而是把能力引导到正确方向。
区别于Prompt Engineering(提示工程)(优化模型输入)和Context Engineering(上下文工程)(优化模型每步看到什么),驾驭工程优化的是模型如何运行——执行环境、工具接口、上下文管理、生命周期编排、可观测性、验证与治理等基础设施层的总体质量。
OpenAI 对 Codex CLI harness 的拆解给出了一个具体例子:Codex harness 负责构造包含指令、工具 schema、权限说明、项目文档、技能元数据和环境上下文的输入,通过 Responses API(响应 API)驱动 Agent Loop(智能体循环),再执行工具调用、转发流式事件、管理上下文窗口和缓存命中。
OpenAI 2025 年 3 月发布的 Agent 工具栈展示了另一种平台化方向:Responses API(响应 API)提供内置 Web search、File search 和 Computer use 工具,OpenAI Agents SDK提供 Agent、handoff、guardrail 和 tracing 原语。也就是说,一部分 harness 能力正在从应用代码下沉到平台层,但业务权限、风险分级、验证标准和人工确认仍然必须由应用侧定义。
OpenAI 2026 年 4 月 15 日对 Agents SDK 的更新把这个平台化方向推进到执行层:SDK harness 不只管理 Agent、handoff 和 trace,还开始标准化文件检查、命令执行、代码编辑、沙箱运行、工作区 Manifest、snapshot 与 rehydration。它说明“harness”正在从应用内部的手写循环,演化成模型提供商和沙箱生态共同提供的一层标准基础设施。
这里要区分对象和方法论:agent harness 指那套非模型基础设施本身;harness engineering 指设计、评估和演进这套基础设施的方法论。为了避免词条碎片化,本库不单独拆出 “Agent Harness” 词条,而是在本页统一讨论。
Viv Trivedy 在《The Anatomy of an Agent Harness》中把这条边界压缩成一个便于检查的公式:Agent = Model + Harness。模型负责推理与决策;除此之外,系统提示、工具与 Skill(技能)、文件系统、Agent Sandbox(Agent 沙箱)、浏览器、子 Agent 编排、上下文压缩、继续执行 hook 和 lint 检查,都属于 harness。这个定义不是说模型不重要,而是提醒工程师:凡是模型原生做不到、但产品又要求 Agent 稳定做到的行为,都必须在模型外找到可执行的实现位置。
文章的第一张架构图把 harness 归纳为围绕模型的五类接口:
flowchart TB
C["上下文注入\nprompt / memory / skills / conversation"] --> M["模型\n推理与决策"]
K["控制\ncompaction / orchestration / Ralph loop"] --> M
M --> A["行动\nbash / tools / MCP"]
A -.->|"结果回到上下文"| M
M --> P["持久化\nfilesystem / git / progress files"]
P -.->|"读取状态"| M
M --> V["观察与验证\nbrowser / screenshots / tests / logs"]
V -.->|"反馈"| M
这五类接口对应的不是一张静态组件清单,而是一组从期望行为反推外部机制的设计关系:
| 期望 Agent 做到什么 | Harness 增加什么 |
|---|---|
| 持久处理真实数据 | 文件系统 + Git |
| 自主编写并执行代码 | Bash + 代码执行 |
| 在安全且开箱可用的环境工作 | 沙箱 + 默认工具链 |
| 记住旧信息并访问新知识 | Memory 文件 + Web 搜索 + MCP |
| 长上下文中维持性能 | 压缩 + 工具结果清除 + Skill 渐进披露 |
| 完成长时任务 | Ralph Loop + 规划 + 验证 |
这里最值得保留的设计方法是:先写清楚模型缺失的行为,再决定 harness 原语;不要先堆工具,再期待模型自己发现这些工具为何存在。
这里的 工具结果清除(Tool Result Clearing,原文也称 Tool Call Offloading) 不是停止工具,也不是销毁结果,而是把大体积工具输出移出模型的活跃上下文视图。关键实现是把“完整事件存储”与“下一次请求发给模型的消息列表”分开:Harness 可以永久保存原始结果,但每次调用模型前重新投影一份精简消息列表。保存到磁盘本身不会省 token;只有下一次请求不再携带原文,卸载才真正发生。
常见实现有两个时间点:
- 模型读取前截断:测试命令产生 20,000 行日志后,Harness 立即把完整结果写入
/tmp/test.log,只把头尾片段、错误摘要和路径作为tool消息发给模型。模型从未一次性看到全部日志,需要细节时再调用grep、tail或分段读取工具。 - 模型读取后清除:如果某次模型调用确实读过完整日志,那么这一次调用的 token 成本已经发生,无法追回。但在再下一次调用前,Harness 可以把历史中的那条巨大
tool消息替换成“日志路径 + 已确认结论 + 关键错误”,不再原样重放 20,000 行。
还有一种相邻但更彻底的方案是 Subagent(子智能体)上下文隔离:主 Agent 不读取完整日志,只把“分析 /tmp/test.log,返回失败用例、根因、证据行号和建议动作”委派给独立上下文的子 Agent。搜索、分段读取和推理轨迹都留在子线程,主线程只接收结构化结论。它减少的是主 Agent 的上下文污染,但不会让成本凭空消失——子 Agent 仍要消耗 token;如果它也一次性吞入 20,000 行,同样可能发生 Context Rot。更好的组合是让子 Agent 通过 grep、sed、tail 等工具按需读取,再返回带文件路径和行号的短报告。
第二种方式之所以可行,是因为多数 Agent Loop 并不是让模型自己保存对话,而是由 Harness 组装每次 API 请求。概念上,它维护两份表示:
完整存储:tool_call_17 -> 20,000 行原始日志或文件引用
模型视图:tool_call_17 -> 失败用例 A/B/C;完整日志见 /tmp/test.log如果使用的服务端会话 API 会自动、不可变地续接全部历史,仅把日志另存到文件并不能卸载;Harness 还必须使用该平台的 tool-result clearing、compaction,或从精简状态开启新的分支/会话。它与上下文压缩的区别在于:工具结果清除针对单个工具输出持续、局部地替换;上下文压缩通常对整段历史做全局摘要。两者都通过减少实际发送给模型的 token 来缓解 Context Rot(上下文腐烂)。
文章的第三张图还提出一个重要的模型—Harness 共同演化回路:工程团队先发现有效原语,把它标准化进产品 harness,再让下一代模型在这套 harness 中接受后训练;模型因此更擅长使用这些原语,而新的使用经验又会催生下一轮 harness 设计。
flowchart LR
D["发现有效原语\nskills / compaction / Ralph loops"] --> H["加入 Harness\n标准化进产品"]
H --> T["训练下一代模型\n将 Harness 放进训练回路"]
T --> I["模型更擅长使用 Harness"]
I --> D
共同演化同时会带来接口耦合:模型可能对训练时见过的工具名称、参数形状或编辑协议形成偏好,替换一个语义相近的工具仍可能使表现下降。因此不能把 harness 当成对模型透明的包装层;工具接口变更需要像模型升级一样经过 Evals(评估)和回归测试。另一方面,“原厂 harness”也不必然对所有任务最优,特定任务仍可能从有针对性的工具、上下文和验证设计中获得更大收益。
绑定约束论题(Binding Constraint Thesis)
驾驭工程的核心主张:真实世界 Agent 可靠性的绑定约束是 harness,而非模型本身。
三个近期实证印证(均来自 2025–2026 年):
- 仅修改工具格式与 harness 配置,无需改动模型权重,在 15 个模型的编程 benchmark 上提升高达 10×
- 通过系统 prompt 重构、中间件上下文注入、自验证 hook,在 Terminal-Bench 2.0 从 52.8% 提升至 66.5%(+13.7pp),完全来自基础设施变更
- 自动化 harness 优化(Meta-Harness)在 Terminal-Bench-2 达到 76.4%,超越所有手工调优方案且未修改模型权重
这些增益超过同一 benchmark 上模型升级通常带来的 2–4pp 改进。OpenAI 在 2026 年 2 月明确将 harness engineering 定义为一门独立学科;Anthropic 的工程博客从多个方向得出相同结论;Martin Fowler 网站将其描述为围绕 LLM 形成 控制论调速器(cybernetic governors) 的工程方法。
三阶段工程演进
工程杠杆点随 Agent 能力成熟而上移:
| 阶段 | 时期 | 核心问题 | 工程范围 |
|---|---|---|---|
| Prompt Engineering(提示工程) | 2022–2024 | 如何有效地问 AI | 优化单次文本输入 |
| Context Engineering(上下文工程) | 2025 | 模型每步应看到什么 | 多步上下文管理 |
| 驾驭工程 | 2026 | 整个系统如何可靠运行 | 七层基础设施全栈 |
三阶段是包含关系,不是替代关系:驾驭工程包含上下文工程,上下文工程包含提示工程。Loop 里的每次 Agent 调用仍然需要好的 Prompt、充足的 Context;驾驭工程只是把杠杆点向上移动了一层,优化模型运行所在的系统,而非模型本身的输入。
生产 Harness 的组成
从 Anthropic、OpenAI、LangChain 等实践中可以把生产 Agent harness 归纳为一组相互耦合的部件:
- 编排循环:组装输入、调用模型、解析输出、执行工具、把观察结果追加回上下文,再重复直到停止;这是 Agent Loop(智能体循环)的运行核心。
- 工具层:管理工具 schema、注册、参数校验、权限检查、沙箱执行、结果捕获和错误包装;工具越多,能力越大,选择错误率和上下文成本也越高。
- 记忆与状态:把短期会话历史、长期 Agent Memory(Agent 记忆)、checkpoint、progress file、数据库记录或 git commit 组合起来,使任务可恢复、可审计、可续接。
- 上下文管理:通过压缩、观察遮蔽、按需检索和子 Agent 摘要控制 Context Rot(上下文腐烂),只把当前步骤最需要的高信号 token 放进窗口。
- Prompt 构造与输出解析:按优先级组织系统指令、开发者指令、项目规则、工具定义和用户请求;用原生 tool calling 或结构化输出区分最终回答、工具调用、handoff 与格式错误。
- 错误处理:把瞬时错误、模型可恢复错误、用户可修复错误和意外异常分开处理;可恢复错误应作为结构化观察返回给模型,而不是静默吞掉。
- 护栏、权限与沙箱:把“模型想做什么”和“系统允许做什么”分开,由工具层、权限系统、Agent Guardrails(Agent 护栏)和 Agent Sandbox(Agent 沙箱)决定动作是否能执行。
- 验证与终止:用测试、lint、类型检查、截图、独立 reviewer 或 Evals(评估)判断进展,并设置最大 turn、token、成本、连续失败次数、人工审批和安全拒绝等停止条件。
- 子 Agent 编排:在工具集过载、任务域分离或需要独立审查时,把子任务交给专门 Agent;多 Agent 并行通常需要 Agent Worktree(Agent 工作树)隔离状态。
这组部件说明:harness 的复杂性不在”写一个 while 循环”,而在循环周围如何管理上下文、权限、错误、状态、成本和验证信号。
Deep Agents把这组部件产品化为四个控制面:执行环境(工具、虚拟文件系统、权限、sandbox / interpreter)、上下文管理(Skill、memory、摘要、卸载、prompt caching)、委派(todo 规划与 subagent)和 steering(人工中断)。这个例子进一步说明 agent framework 与 agent harness 的差别:前者可以只提供模型—工具循环,后者还要为真实长任务提供状态、隔离和控制。
OpenAI 的 Codex Prompting Guide 进一步说明,coding-agent harness 的效果会被很多“看似实现细节”的接口形状影响:shell 工具是否强制 workdir、文件修改是否有 apply_patch、计划工具是否有稳定状态枚举、并行工具调用是否被显式鼓励、工具输出是否按固定规则截断、assistant preamble 是否带 phase 元数据。这些都不是模型之外的杂务,而是模型实际工作的操作界面。
数据研发实践中的三层六支柱
曹亚龙在阿里云开发者文章《数据研发 Multi-Agent 架构的 Harness 工程实践》中,按一次任务的生命周期把 harness 归纳成身份层、执行层、进化层。这是作者基于数仓研发系统总结的落地框架,并非行业统一标准;它的价值在于把上面的组件清单重新组织成“执行前定边界、执行中保可靠、执行后把错误工程化”的闭环。
flowchart TB
I["身份层:Identity\n角色 / 工具能力 / 行为约束"] --> X["执行层\nOrchestration / Context / Gate / Recovery"]
X --> E["进化层:Evolution\n违规记录 / 经验加载 / 约束迭代"]
E -->|"更精确的身份与约束"| I
X -->|"质量结果与失败样本"| E
六个支柱分别消除一类系统性失效:
| 支柱 | 要回答的问题 | 数据研发案例中的实现 |
|---|---|---|
| Identity | 谁负责什么,什么绝对不能做? | 协调者只调度、审查和汇报;需求、方案、SQL、测试由 specialist 分工;约束分为红线、错误记录、操作规则 |
| Orchestration | 按什么路径和顺序执行? | 全链路、快案、快码与单点模式共用同一能力;有依赖串行、无依赖并行;修改按轻量、中等、重大匹配不同流程 |
| Context | 每一步能看到什么? | 按阶段加载指令;阶段结束生成 checkpoint 摘要;规范渐进加载;Agent 之间通过结构化 Spec 文件而非完整对话交接 |
| Gate | 产出是否达标? | 工具可用性、上游产物、SQL 语法和阶段切换均设检查点;强制检查不能由 Agent 自行豁免;生成者与评估者分离 |
| Recovery | 当前在哪,失败后从哪继续? | 状态机和中间文件持久化;失败分为自动重试、回退到稳定点、停止并请求人工介入 |
| Evolution | 一次错误怎样减少再次发生? | 错误实时结构化记录并在后续任务中加载;反复出现的错误升级为红线、自动检查或流程门禁 |
这套划分也揭示了两个容易混淆的边界。Identity 的约束属于前馈控制,Gate 的验收属于反馈控制,两者不能互相替代;Evolution 也不等于让模型“记住教训”,而是把教训转成下一轮可执行的规则、检查或编排变化。后者与Agent Memory(Agent 记忆)有关,但最终落点仍是可版本化、可评估的 harness 机制。
Evaluation Harness 与 Agent Harness
Anthropic 在 Agent eval 实践里明确区分两类 harness:
- Agent harness / scaffold:让模型作为 Agent 行动的执行系统,负责输入组织、工具调用、状态更新和终止。
- Evaluation harness:运行评估的外部系统,负责分发 task、创建干净环境、并发运行 trial、记录 trajectory、调用 grader、聚合指标。
这一区分很关键:评估一个 Agent 时,被测对象不是模型本身,而是模型 + agent harness + 工具 + 环境 的组合。Evaluation harness 则是测量系统,必须尽量避免把自身噪声混进结果。
一个可靠 evaluation harness 至少要满足四点:
- 环境隔离:每个 trial 从干净状态启动,避免文件残留、缓存、git history 或共享数据库让后续 trial 获得不公平优势。
- 轨迹完整:记录消息、工具调用、推理摘要、工具输出、环境更新、token、延迟和错误,方便人工读 transcript 判断 grader 是否公平。
- 结果优先:优先检查最终环境状态和产物,而不是强制 Agent 走某条工具调用路径;路径检查只用于必要约束。
- 可复跑基线:同一 suite 能在模型升级、prompt 改动、工具接口变化和 harness 改动后重复运行,形成 baseline 与 regression gate。
这也解释了为什么 Agent Sandbox(Agent 沙箱)不仅是安全组件,也是评估组件:没有可重置、可隔离、可观测的执行环境,Agent eval 的 trial 之间就不是独立样本。
长时 Agent Harness
Anthropic 的 Long-running Agent Harness 案例展示了 harness 在跨多个上下文窗口时的另一条边界:compaction 不等于连续性。即使模型能自动压缩上下文,后一轮 Agent 仍可能拿不到足够清楚的交接信息,结果要么在半成品上猜测,要么看到部分进展后过早宣布完成。
可工作的长时 harness 需要把连续性外化到环境里:第一次运行由 initializer agent 生成 feature_list.json、init.sh、claude-progress.txt 和初始 git commit;后续 coding agent 每轮只做一个功能,启动时读进度和 git log,先跑基础端到端测试,结束时提交增量并更新进度。这里的 git、progress file、feature list 共同构成 Agent Memory(Agent 记忆),浏览器自动化和 passes 字段则构成 Evals(评估)。
这个模式把 harness 从“一次执行的工具壳”扩展为“跨班次工作的接力制度”。它不替代 Durable Execution(持久执行):前者让新上下文窗口知道任务状态,后者让运行时在崩溃后从正确步骤恢复。
Harness 与 compute 分离
OpenAI 的 Agents SDK 更新明确提出一个生产边界:把可信 harness 与不可信 compute 分开。Harness 保留 agent loop、工具编排、memory、凭证与状态;sandbox/compute 只执行模型生成的文件操作、shell 命令、代码运行和依赖安装。这样设计的直接收益有三类:
- 安全:凭证和内部 API 不进入模型生成代码所在的沙箱,prompt injection 即使影响了执行命令,也更难直接读到密钥。
- 持久性:Agent 状态外置到 harness,沙箱容器失败或过期后,可以用 snapshot 和 rehydration 在新容器中恢复运行。
- 扩展性:一个 run 可以按需调用一个或多个沙箱,也可以把 Subagent(子智能体)路由到隔离环境,并行处理文件、测试或数据任务。
flowchart LR
H["可信 harness\nagent loop / memory / secrets / tools"] -->|"受控命令与文件操作"| C["非可信 sandbox / compute\nshell / code / filesystem"]
H -->|"直接访问"| D["数据库 / API / Web"]
C -->|"产物与日志"| H
H -->|"snapshot / rehydrate"| R["恢复后的新 sandbox"]
这个分离强化了 harness engineering 的核心观点:可靠 Agent 系统不是“模型 + 容器”就够了。真正的控制面在 harness:它决定哪些状态被保存、哪些动作进入沙箱、哪些凭证永不下放、失败后从哪里恢复。
Anthropic 的 Claude Managed Agents 把同一条边界推进成托管平台抽象:session、orchestration、harness、sandbox、resources、tools 都有稳定接口,具体实现可以替换。session 是 append-only 事件日志,harness 通过 getEvents() 选择性读取并用 emitEvent() 追加进展;sandbox 只通过 provision({resources}) 和 execute(name, input) -> String 被调用。这样容器失败只是一次工具错误,而不是整个 Agent 失联。
flowchart LR
S["Session\nappend-only log"] <--> H["Harness\nClaude + loop"]
H <--> B["Sandbox\nexecute / provision"]
H <--> T["Tools / MCP"]
O["Orchestration\nwake(session_id)"] <--> H
这也是 meta-harness 的设计方式:对接口有强约束,对接口背后的 harness、sandbox、调度器和工具实现保持可替换。它解决的不是“今天这个模型需要什么脚手架”,而是“模型能力继续变化时,哪些边界不该跟着重写”。
Claude Managed Agents 的早期反例是把 session、harness 和 sandbox 都放进同一个容器:文件编辑可以直接走 syscall,服务边界也少,但容器会变成不可丢失的状态实体。容器崩溃会丢 session,容器卡死时只剩 WebSocket 事件流可观察;客户接入自有 VPC 时,还会迫使 harness 跟执行环境同处一地。拆开之后,“脑”可以留在托管控制面,“手”可以是云 sandbox、自托管 sandbox、MCP 工具或其他执行环境。
工具不是越多越好
Harness 的工具层容易被误解成"能力越多越强"。实际设计里,工具数量增加会同时增加三种成本:工具说明占用上下文、模型选择动作的分支数变多、错误路径更难诊断。
Vercel 的 text-to-SQL 案例提供了一个反例:起初为 Agent 配置大量专用工具,后来删掉大部分专用工具,只保留 grep、cat、find、ls 等基础文件工具,让模型直接读取 schema 文件再生成 SQL,成功率和效率反而提升。它说明好的 harness 不是把所有 API 都暴露给模型,而是给模型一组足够稳定、可组合、低歧义的操作原语。
工具层的目标是降低不确定性,而不是展示能力清单。每新增一个工具,都应该回答:它是否显著减少任务步骤?是否比基础工具更不容易误用?失败时是否容易被 Evals(评估)捕捉?如果答案不清楚,少工具往往更稳。
Writer-Checker 子 Agent 分离
多 Agent 场景下最有价值的结构是写作者(Writer)与检查者(Checker)分离:主 Agent 生成输出,独立的 Reviewer 子 Agent 用干净的上下文窗口校验。同一模型审查自己的输出,天然宽松——它太了解自己的”意图”了;独立 Reviewer 才能抓住写作者说服自己接受的错误。这正是让 Loop Engineering(循环工程)在无人值守时依然可信的技术基础。规则:生成者不宣布完成。
Dynamic Workflows(动态工作流)把这些部件集中暴露为 Workflow Runtime:模型负责按目标生成编排脚本,Runtime 负责调度 subagent、管理中间状态、控制并发、记录日志、处理失败并触发验证节点。没有这层 Runtime,所谓“动态编排”很容易只是一个更长的 prompt,而不是可审计、可恢复、可复跑的执行系统。
Claude Code Harness 目录布局
以 Claude Code 为参照,整个 harness 住在一个目录里——.claude/。理解这套布局可以在几秒内读懂任何人的 harness 配置:
.claude/
├─ CLAUDE.md # 常驻事实——每次会话都读
├─ settings.json # 权限、模型选择、hooks
├─ .mcp.json # 外部工具连接(MCP 服务器)
├─ rules/ # 路径范围限定的行为规则
│ ├─ tests.md
│ └─ python-types.md
├─ agents/ # 子 Agent 定义(每个约 30 行)
│ ├─ reviewer.md
│ └─ eval-runner.md
├─ skills/ # 可复用工作流
│ └─ pr-checklist/
│ └─ SKILL.md
└─ agent-memory/ # 在会话间存活的状态
└─ STATE.md这套结构体现了 harness 的四件事分工:常驻事实(CLAUDE.md)、权限与约束(settings.json + hooks)、工具接入(.mcp.json)、可复用知识(rules/ + skills/ + agents/)、跨轮状态(agent-memory/)。
判断 harness 是否健康的粗略规则:能不能用一句话解释这个目录下每个文件存在的理由?解释不了的,删掉。
Settings.json:权限一次设好
默认 harness 对每个有风险的操作都弹出确认。settings.json 是把安全操作预批准、危险操作永久拒绝的地方——避免循环在无人值守时卡在权限弹窗上:
{
"model": "claude-sonnet-4-6",
"permissions": {
"autoApprove": [
"Read(*)", "Grep(*)",
"Bash(npm test)", "Bash(git status)"
],
"deny": [
"Bash(rm -rf*)", "Bash(git push*)",
"Edit(.env*)", "Edit(secrets/*)"
]
}
}判断原则:这个操作出错后撤销成本低吗?低 → 预批准;高(强推、删文件、改密钥)→ 永久拒绝或弹窗确认。
Hooks:不依赖模型理解的确定性约束
Hook 是在 Agent 生命周期固定时间点执行的 shell 命令,退出码可以阻断动作——H1-H4 护栏是判断,Hook 是确定性执行,模型无法绕过。
几乎每个 harness 都值得配的两个 hook:
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"command": "./.claude/hooks/block-dangerous.sh"
}],
"PostToolUse": [{
"matcher": "Edit|Write",
"command": "prettier --write \"$CLAUDE_FILE_PATH\""
}]
}- PreToolUse:在危险命令执行前拦截,
exit 2即阻断。模型说不上话。 - PostToolUse:每次文件修改后自动格式化,Agent 永远不会提交未格式化代码。
Hook 用于必须发生或绝不能发生的事——安全、格式化、审计日志。判断、权衡是模型的工作,不是 hook 的工作。好的 harness 有一两个锋利的 hook,不是二十个没人能解释的 hook。
打包与复用
一个在一个项目上有效的 harness 是资产。把 skills、agents、rules 打包成插件(Plugin),团队一步安装,获得相同的约定、相同的安全 hook、相同的 Reviewer。Harness 从个人配置变成共享基础设施。
打包前要扫描:泄露的密钥和过宽的权限会随插件传播给所有安装者。deny 规则尤其要在打包前仔细确认。
ETCLOVG:七层结构
ETCLOVG Taxonomy(ETCLOVG 分类法) 将 Agent harness 分为七层(170+ 开源项目的实证映射):
结构核心
- E — 执行环境与沙箱:Agent Sandbox(Agent 沙箱)在隔离、可复现、活性三个维度服务 Agent 运行
- T — 工具接口与协议:Model Context Protocol(模型上下文协议)、A2A、Function Calling(函数调用)定义能力如何被描述和调用
- C — 上下文与记忆管理:短期(活跃窗口)、中期(会话状态)、长期(持久记忆)三层架构
- L — 生命周期与编排:单 Agent 内循环 → 多 Agent 协调 → 完整任务 pipeline;多 Agent 并行时通常需要Agent Worktree(Agent 工作树)隔离工作区
控制平面
- O — 可观测性与运维:trace 收集、成本追踪、故障诊断(Langfuse、OpenTelemetry)
- V — 验证与评估:五阶段任务到反馈生命周期;评估分数是模型-harness 对的属性
- G — 治理与安全:权限模型、生命周期 hook、组件加固、声明式宪法、审计基础设施
V 层里的 Evals(评估)不是一个附属报表,而是控制循环的判定器:它决定改动是否保留、循环是否继续、是否需要回滚或升级给人类。没有 Evals,harness 只能执行 Agent 动作;有 Evals,harness 才能把动作变成可改进、可停止、可审计的反馈系统。
Harness 作为控制系统
Harness 的实质是把 Agent 从"随机输出机器"变成可控反馈系统。G 层的四个 hook 点形成围绕 LLM 的控制环路:
flowchart LR
I["输入"] --> H1["H1 输入护栏"] --> LLM["LLM"] --> H2["H2 动作护栏"] --> T["工具执行"]
T --> H3["H3 信息流控制"] --> R["结果返回"] --> LLM
H2 -.->|"关键动作"| H4["H4 人工审批"]
H4 --> T
- H1 输入护栏:检测 prompt injection(PromptShield、DataSentinel)
- H2 动作护栏:在工具执行前验证 LLM 提出的动作(ShieldAgent、ControlValve)
- H3 信息流控制:工具结果返回上下文前的污点追踪(CaMeL:每个数据值携带溯源元数据标签)
- H4 人工审批:Codex、Gemini CLI、OpenHands 对破坏性或超出范围的动作要求人工确认
OpenAI 的 Agent guide 给这套控制系统补了一个实用清单:相关性分类器、安全分类器、PII 过滤、Moderation、工具风险分级、规则型保护和输出校验。它们可以由模型、分类器、确定性规则和人工审批共同组成,不要求全部塞进同一个 prompt。
同一种闭环,三次上移
George 在《Harness Engineering Is Cybernetics》中把驾驭工程放进一条更长的控制论演进线:18 世纪的离心调速器把蒸汽机转速闭环,2010 年代的 Kubernetes controller 把集群状态闭环,编码 Agent 则尝试把代码质量闭环。三者都把人的工作从直接操作对象,推向定义目标、设计控制器和校准反馈。
制造业,1780s
flowchart LR
MS["目标转速"] --> MG["离心调速器"] --> ME["蒸汽机"] --> MO["实际转速"]
MO -->|"反馈"| MG
基础设施,2010s
flowchart LR
KS["期望状态"] --> KC["Kubernetes controller"] --> KL["集群"] --> KO["实际状态"]
KO -->|"协调反馈"| KC
代码库,Agent 时代
flowchart LR
CS["约定 / 架构约束"] --> CL["LLM + 工具"] --> CB["代码库"] --> CQ["质量信号"]
CQ -->|"验证反馈"| CL
这张类比的关键不是“LLM 就是 Kubernetes controller”,而是反馈回路闭合的层级上移了。编译器早已能检查语法,测试能检查部分行为,linter 能检查风格;但“改动是否符合架构”“抽象是否会随规模增长而恶化”过去缺少同时具备语义感知与修改能力的传感器和执行器。LLM 让这类高层闭环第一次部分可行。
但“能感知、能修改”只是必要条件,不是充分条件。转速是相对清晰的标量,集群也有明确的期望状态;代码质量却是多维、含语境且经常互相冲突的目标。因此 Agent 闭环更依赖校准:把真实分层和依赖方向写进架构文档,把修复建议写进自定义 linter,把团队判断沉淀为黄金原则,并让测试、CI 和错误输出对 Agent 可运行、可解析、可行动。否则,Agent 不会从重复运行中自动“耳濡目染”,只会以更高速度重复同一种架构漂移。
这也解释了工程师角色为何从“亲手修每个结果”转向“让判断可机器执行”:定义什么叫正确、识别偏离、决定方向,比逐行实现更稀缺。原文借生成—验证不对称说明这一点;它适合作为工程直觉,而不是把软件质量验证简单等同于复杂度理论里的 P vs NP。
编码 Agent 的质量调控(前馈与反馈)
Birgitta Böckeler(Thoughtworks)将编码 Agent 的 Harness 框架为围绕 LLM 形成的控制论调速器(cybernetic governors),并提出两种互补的控制机制:
- Guides(引导)/ 前馈控制(feedforward):在 Agent 行动前介入,提高初始输出正确的概率。典型形式:CLAUDE.md 架构文档、技能规范、测试要求、性能指标,以及技术栈约定。
- Sensors(传感)/ 反馈控制(feedback):在 Agent 行动后观察结果,触发自我修正。典型形式:测试运行器、lint 工具、类型检查器、架构合规检查器、独立 Review Agent。反馈控制在优化为 LLM 解读时最有效(清晰的错误信息 > 模糊的退出码)。
传感器按执行方式分为两类:
| 类型 | 执行方式 | 速度 | 可靠性 | 适合捕捉 |
|---|---|---|---|---|
| 计算型(Computational) | 确定性,CPU | 毫秒~秒 | 极高 | 结构性问题(重复、复杂度、覆盖率、风格) |
| 推理型(Inferential) | AI 语义分析,GPU/NPU | 秒~分钟 | 中等 | 语义性问题(冗余逻辑、过度设计、意图偏差) |
三类质量调控维度
编码 Agent 的 Harness 可按质量维度分为三个相互独立的调控域:
可维护性(Maintainability):目前最成熟。现有工具链可直接复用——计算型传感器可靠捕捉重复代码、圈复杂度、覆盖率缺口、风格违规;推理型传感器可部分识别冗余逻辑和过度设计。剩余盲区:诊断错误、不必要功能、指令理解偏差,依然需要人类判断。
架构合规(Architecture Fitness):将「架构适应性函数(Fitness Functions)」编码为可测量约束——前馈侧把性能要求和可观测性标准(日志格式、trace 规范)写进 Skill;反馈侧用性能测试和调试指令让 Agent 自行反思架构问题。
行为验证(Behaviour):目前最不成熟。多数团队仅靠功能规格(前馈)+ AI 生成测试套件 + 人工测试(反馈),提供的信心不足以支持自主部署。新兴模式是「批准夹具(approved fixtures)」——预置经人工验证的场景集,用于自动化行为验收。
Keep Quality Left(质量左移)
质量检查的时序原则:越快、越轻量的检查越靠前,越重的检查异步或延后。
| 阶段 | 检查内容 |
|---|---|
| 集成前 | Language Server、架构文档引导、快速 lint、基础 Review Agent |
| 集成后 Pipeline | 变异测试、完整代码 Review Agent、更广泛架构分析 |
| 持续监控 | 漂移检测(死代码、覆盖质量、依赖演化)、运行时反馈(SLO 降级、输出质量采样) |
Agent 生成代码的速度远超人工审查能力,及早捕获问题使修复成本接近零。这与 Harness 的绑定约束论题一致:将更多约束力前置到引导层,而非依赖事后修复。
Harnessability(可驾驭性)
可驾驭性(Harnessability) 是代码库的一种结构属性,描述它对 Agent 控制的天然友好程度——“环境本身使 Agent 能够读懂、能够导航、能够有效处理的结构性前提”。
高可驾驭性代码库的典型特征:强类型系统(减少 Agent 猜测空间)、明确的模块边界(变更影响可推断)、确立的框架约定(减少设计决策负担)。Greenfield 项目可在早期嵌入可驾驭性;遗留代码库的改造成本更高,引入 Agent 前先提升可驾驭性是合理投资。
与 Ashby 必要变种定律的关系:将 Agent 限定在固定服务拓扑(CRUD 服务、事件处理器、仪表盘)会收缩 Agent 的输出变种空间,使全面调控变得可行。拓扑定义是一种"变种收缩动作(variety-reduction move)"。
Harness 模板
一个新兴模式是将常见服务拓扑的 Guides 和 Sensors 捆绑为可实例化的 Harness 模板——类似于服务模板,团队可版本化、复用、治理。Harness 本身成为可管理的资产,而非散落在各处的配置脚本。
常见约束形式(G 层实践)
行为护栏(Behavioral Rails)
明确规定 Agent 不能做什么:
- 不能删除测试
- 不能修改 public API
- 不能直接向 main 分支提交
- 不能在未审查情况下执行数据库迁移
权限边界(Permission Scope)
最小权限原则:Agent 只获得完成当前任务的最小权限集。生产环境、账单系统、用户数据相关操作必须人工审批。
工具权限还应按风险分级:只读、可逆、局部影响的工具可以自动执行;不可逆、涉及资金、隐私或生产系统的工具应触发 Agent Guardrails(Agent 护栏)中的额外检查或人工审批。这个分级比简单的 allow/deny 更贴近生产场景。
声明式宪法(Declarative Constitutions)
将治理规则外化到声明式配置文件(YAML、DSL)而非硬编码到应用逻辑:
- 训练时宪法(Anthropic Constitutional AI):四层优先级——安全 > 伦理 > 合规 > 有用性
- 部署时 YAML(AutoHarness):pipeline 模式、风险分类、allowed/denied tool 模式、token 预算、审计日志目标
- 编程策略 DSL(Progent):布尔谓词+量词,运行时最小权限策略
停止条件(Stop Conditions)
- 连续失败 N 次后停止,而非无限重试
- 检测到高风险操作时暂停等待人工确认
- 上下文窗口接近上限时主动压缩或归档状态
跨层工程挑战
Harness 的层不是独立的——三个跨层问题无法在单层内解决:
成本-质量-速度三元悖论:更强沙箱 + 更深评估 + 更严治理增加延迟和成本。生产系统必须显式决定哪些检查同步、哪些异步、哪些放入回归套件。
能力-控制权衡:每次扩展工具菜单或放宽沙箱权限都增大控制问题。这是设计轴而非独立变量——工具菜单扩大 = 选择错误率上升 + prompt injection 攻击面扩大。
Harness 耦合问题:本地优化可能产生全局回退。Prompt 改动影响 token 消耗和 cache 命中率;工具描述变更既消耗上下文预算又改变模型行为;评估分数因此无法干净地归因于模型——harness 变更(tool schema、verifier、recovery loop)同样会改变测量到的行为。
Codex 的工程实践也说明,harness 变更会直接影响成本:工具列表顺序、模型特定 instructions、沙箱配置、审批模式和当前工作目录都会改变 prompt 前缀,进而影响Prompt Caching(提示缓存)命中率。性能优化因此不是 API 调用层的小细节,而是 harness 结构设计的一部分。
Harness 假设原则
每个 harness 组件都编码了一条关于模型不能自主完成什么的假设;随着模型改进,这些假设会变得陈旧。(Anthropic, 2026c)
Anthropic 在实践中验证了这一点:为 Opus 4.5 设计的上下文重置在 Opus 4.6 上变得多余,移除后在维持输出质量的同时将成本从 $200 削减至 $125。这意味着 harness 本身需要随模型能力改进而持续简化,而不是单调地增加脚手架。
Agent-First 开发的实证
OpenAI 于 2025 年 8 月启动了一项"零手写代码"实验:用 Codex 完整构建一个内部产品,任何应用代码、测试、CI 配置、文档均由 Agent 生成,人类只负责方向和验收。五个月后的结果:
- 仓库规模约 100 万行代码(含应用逻辑、基础设施、文档)
- 约 1,500 个 PR 合并,团队规模从 3 人扩展到 7 人
- 平均吞吐 3.5 PR/工程师/天,且随团队增长吞吐持续提升
- 估计约为手写代码速度的 10 倍
这个实验给 harness engineering 带来几个关键洞见:
三层控制面
把这套实践压缩来看,支撑 Agent-first 代码库的 Harness 可以归纳为三个相互咬合的控制面:
| 控制面 | 要解决的问题 | 典型实现 |
|---|---|---|
| 上下文工程 | Agent 此刻是否看见正确的信息 | 仓库内文档、按需检索、上下文压缩、文件系统与 Git 持久状态 |
| 架构约束 | Agent 是否沿着团队认可的结构扩展系统 | 固定分层、依赖方向、自定义 linter、测试与可行动的错误信息 |
| 熵控制 | 大量生成之后,局部妥协是否持续污染代码库 | 黄金原则、定期扫描、文档园丁与清理 Agent、小步偿还技术债 |
三层缺一不可:只给上下文,Agent 能找到代码却仍可能复制坏模式;只有架构规则,没有反馈检查,规则只是愿望;只做事后清理,则会把高吞吐变成更快积累技术债。真正的 Harness 是把信息供给、行动约束、偏差纠正闭合成持续运转的回路。
这也解释了许多 Agent 失败为什么不是“模型不够聪明”:所谓“好代码是什么样”“哪些依赖方向值得奖励”“何时算真正完成”,往往仍锁在工程师脑中。Agent 不会仅凭长期待在仓库里就自动吸收这些判断;若它们没有被外部化为文档、linter、测试、日志和停止条件,第 100 次运行仍可能重复第 1 次的错误。
工程师角色重新定义。当代码由 Agent 生成,工程师不再主要写代码,而是设计环境(design environments)、规定意图(specify intent)、构建反馈循环(build feedback loops)。核心范式:"人类掌舵,Agent 执行(Humans steer, agents execute)"。
当遇到失败时,正确反应几乎从不是"更努力地提示",而是定位缺失的能力并问:“这个能力如何对 Agent 变得可读、可执行?”
吞吐量改变合并哲学。当 Agent 产出速度远超人工 Review 能力,纠错很便宜、等待却很昂贵。与低吞吐环境相反,许多常规工程规范(强阻塞合并门禁、等待 flaky 测试稳定)反而成为瓶颈。短生命周期 PR + 跟进修复 + Agent-to-Agent Review 替代了人工强 Review 流程。
架构约束是速度的前提。刚性分层架构(每个业务域有固定的 Types → Config → Repo → Service → Runtime → UI 依赖方向)通常被推迟到有数百名工程师时才实施。但在 Agent-first 仓库里,这些约束必须尽早建立——约束是不让速度衰减的机制。自动 linter 强制执行这些规则,且 linter 错误信息本身被设计成注入 Agent 上下文的修复指令。
知识可读性与熵控制
Agent 可读性原则
Harness 的知识层遵循一个核心原则——Agent 可读性(Agent Legibility):Agent 在运行时无法访问的任何信息,对它等同于不存在。
Slack 讨论、Google Docs、口头决策、人的记忆——这些都在 Agent 的可见范围之外。每一条重要决策和约定,都必须以版本化 Markdown 的形式落入仓库,才能对 Agent 产生效果。这要求把 AGENTS.md 设计为"目录"而非"百科全书"(约 100 行,指向 docs/ 各专题文档),并用 linter + CI 机械验证知识库的新鲜度。
黄金原则与熵控制
Agent 会复制仓库中已有的模式——包括不完善的模式。随时间积累,这会产生漂移(drift),早期团队称之为"AI slop",每周需花费 20% 时间手工清理。
这不可持续。解决方案是"黄金原则(golden principles)"+ 递归清理:
- 将质量标准和设计偏好编码为仓库内的可机械检查规则(“优先用共享 utility 包而非自造 helpers”、“在边界解析数据 shape 而非假设类型”)
- 定期运行"文档园丁(doc-gardening)“Agent:扫描过期文档、违反黄金原则的代码,开修复 PR(大多数不到一分钟就能 review 并自动合并)
- “技术债是高息贷款"——持续小步偿还远优于让其复利后集中处理
结果:人的判断和品味被捕获一次,然后持续作用在每一行 Agent 生成的代码上。这是 harness 把技术债纳入可控反馈系统的机制。
跨会话任务连续性(Multi-Session Continuity)
长时间编码任务的一个特有挑战:任务所需工作量远超单个上下文窗口。每个新会话的 Agent 和换班工程师一样,对上一班发生了什么一无所知。
Anthropic 在用 Claude Opus 4.5 构建 claude.ai 克隆的实验中给出了一套具体模式:初始化者-执行者分工(Initializer-Coder Split)。
初始化者 Agent(Initializer Agent)
第一个会话不做功能开发,只建立后续所有会话共享的基础设施:
init.sh:可重现的环境启动脚本,后续每个会话开始时运行,确保一致的起始状态claude-progress.txt:工作历史文档,记录已完成内容、已知问题、下一步入口;每次会话结束后更新- 功能列表 JSON:200+ 条粒度化需求,每条包含
category、description、操作步骤和passes布尔字段
功能列表是防止"提前完成"失效的核心机制——让后续任何 Agent 会话都能精确知道哪些功能通过、哪些未完成,不会因为看到"进展不错"就宣布完工。关键约束:不允许删除或修改测试——这会导致功能遗漏或 bug 被掩盖。
执行者 Agent(Coding Agent)的标准化启动流程
1. 验证工作目录(pwd)
2. 读取 git 日志与 claude-progress.txt
3. 从功能列表选出最高优先级的未完成项
4. 执行 init.sh,恢复运行环境
5. 运行基础端到端测试
6. 专注开发单个功能直至完成每次会话结束时:把代码置于"merge-ready"状态、提交含描述的 commit、更新 claude-progress.txt。
四类失效与对应方案
| 失效模式 | 表现 | Harness 应对 |
|---|---|---|
| 过度野心(Over-Ambition) | 试图一次会话完成整个应用,上下文中途耗尽 | 强制单次会话只做一个功能 |
| 提前完成(Premature Completion) | 后续 Agent 看到进展后宣布项目完成 | 详细功能列表防止误判完成状态 |
| 测试不充分 | Agent 改了代码但没做端到端验证 | 集成 Puppeteer MCP,进行浏览器自动化测试 |
| 文档缺口 | Agent 离开时环境残缺或无文档 | 强制 git commit + 进度摘要 + 会话开始时健康检查 |
浏览器自动化作为 Harness 组件
传统单元测试无法捕捉完整用户路径的问题;本模式把浏览器自动化作为 harness 的标准组件:通过 Puppeteer MCP 在真实浏览器环境执行测试,与人工测试等价。Anthropic 观察到:一旦明确提示 Agent 使用浏览器自动化工具,端到端验证质量显著提升。这与"传感器(Sensors)“的前馈/反馈思路一致——不靠 Agent 自我判断,而是给它确定性的验证工具。
当前局限:模型视觉能力尚不能识别某些 UI bug(如浏览器原生 modal alert);单 Agent 与专职多 Agent 团队(测试 Agent、QA Agent、清理 Agent)的最优架构仍是开放问题。
常见 Harness 错误
以下是让每个 Loop 都变差的 harness 反模式:
| 错误 | 症状 | 纠正方式 |
|---|---|---|
| 跑在默认 harness 上 | Agent 每次重新推断项目、重复问相同权限 | 写 CLAUDE.md + settings.json |
| CLAUDE.md 膨胀 | 常驻上下文里塞满流程,真正的规则被挤走 | 流程移入 Skills,路径规则移入 rules/ |
| 约束写进 CLAUDE.md 而不是 hooks | Agent 偶尔忽略规则 | 把必须/绝不能发生的事写进 PreToolUse hook |
| 写作者自我评分 | Agent 审查自己的输出,天然宽松 | 加独立 Reviewer 子 Agent(Writer-Checker 分离) |
| 没有状态文件 | 每次循环重新理解世界,无法续接 | 建 agent-memory/STATE.md |
| 把循环套在烂 harness 上 | 循环加速产出垃圾 | 先让单次执行可靠,再加循环 |
| 二十个 hooks | 没人能解释每个 hook 的作用 | 一两个锋利的 hook,其余删掉 |
| 打包前不扫描 | 泄露密钥和过宽权限随插件传播 | 发布前审查 deny 规则和 secrets |
口诀:先让一次执行可靠,再加循环;先有约束,再给自由。
Harness 持续改进循环
Harness 不是"设计一次、永久运行"的静态配置——它需要随运行证据持续演进。OpenAI 的 Agent Improvement Loop Cookbook 展示了一套具体的改进飞轮:先用 OpenAI Agents SDK 跑出真实 trace,再让人类和模型解释这些 trace,把反馈转成可复跑的 Evals(评估),用 Promptfoo 作为 gate 验证当前行为,最后交给 HALO(层次化 Agent 循环优化) 排序改进建议,并生成 Codex 可执行的 handoff。
它不是一个新的基础模型能力,而是 Harness Engineering 的闭环操作化:把一次运行中学到的东西沉淀为下一轮 harness 修改、回归测试和自动化交接,而不是停留在零散评论里。
flowchart LR
T["SDK traces\n观察到的真实行为"] --> F["Human + LLM feedback\n解释 trace 中什么重要"]
F --> E["Promptfoo evals\n生成并验证回归条件"]
E --> H["HALO diagnosis\n诊断并排序 harness 改动"]
H --> C["Codex handoff\n把证据交给代码实现"]
C --> U["Harness update\nPR + validation"]
U --> T
A["Automation + heartbeat\n发现新 handoff 并触发 Codex"] -.-> C
这张飞轮图的关键信息是:人类判断不是只在最后审批一次,而是先通过 feedback 进入系统,之后每一轮都会通过 eval、HALO 建议和 handoff 继续复利化。自动化的 heartbeat 可以观察新 handoff 并触发 Codex,但是否全自动合并取决于 gate 可信度和团队策略。
飞轮的五个阶段:
1. Traces — 收集真实执行记录。 Agent 每次运行产生 OpenTelemetry 格式 JSONL,记录模型调用、工具使用、输出产物和 token 消耗。这是改进的原始证据,不是假想的失败场景。
2. Feedback — 人工与 LLM 双轨批注。 领域专家读 trace,指出哪些失败真正重要(“不应把未验证的 NRR 当官方指标”)、哪些正确行为应固化(required observations)、哪些表述需要禁止(prohibited claims)。同一批 trace 再通过模型批注补充人工遗漏的模式。两者分开保存——人工判断是第一性证据,模型洞察是覆盖扩展。
3. Evals — 把反馈固化为可复跑测试。 LLM 将 trace + feedback 转为 Evals(评估)定义(本例中用 Promptfoo),每条测试包含:期望行为描述(rubric)、确定性断言(contains/not-contains)和 llm-rubric judge(阈值 0.8)。这一步使"本次发现的问题"变成"所有未来版本都要跑的回归门”。
4. HALO — 分析全部信号,生成排名建议。 HALO(层次化 Agent 循环优化) 接收 traces + feedback + evals + gate 结果 + 当前 harness config,将故障分类为三类(规则缺失 / 规则存在但未可靠执行 / 实现缺陷),并按影响力排序输出 codex_handoff.md,包含 Executive Summary、Top 3 改动、证据、分章节详细建议和机器可读的 top_priorities JSON。
5. Codex — 实施改进,重启飞轮。 开发者(或 Codex 自动化)依据 handoff 文档实施变更,跑 eval gate 验证通过后合并,产生新版 harness;新版 harness 再运行 → 新 trace → 下一轮。
HALO 输入上下文
Cookbook 把不同来源统一包装成 HALO 可分析的上下文,而不是让优化器只看失败文本:
| 输入信号 | 数量 | 作用 |
|---|---|---|
| 当前 harness config | 1 | 系统 prompt、模型设置、工具策略和 eval 元数据 |
| SDK execution traces | 5 | Agent 步骤、工具调用和最终输出 |
| Human feedback | 5 | 专家认为必须出现或不得出现的观测 |
| LLM feedback | 5 | 模型补充的失败模式和 caveat |
| Generated eval definitions | 5 | 从反馈生成的期望行为、rubric、正反例 |
| Promptfoo row results | 5 | 每条 eval 的通过/失败和解释 |
| Promptfoo gate summary | 1 | 整个 suite 的总览结果 |
这种做法的价值在于让 HALO 同时看到“发生了什么”“为什么重要”“哪些要求已经被固化成 gate”“当前 gate 是否通过”。如果只给它 trace,它容易把个别失败当成全部问题;如果只给它 eval 结果,它又看不到行为路径和上下文。
飞轮的工程意义
飞轮的价值在于把"单次观察"转为"持久改进路径”:没有飞轮时,trace 是孤立日志、feedback 是一次性评论,改进靠工程师的个人判断拼接;有飞轮时,每次发现的问题直接进入 eval suite,每次 eval 失败直接进入 HALO 排序,每次 HALO 建议直接对应可实施的 diff。信号不再消失在对话记录里。
从 Harness Engineering 的"绑定约束论题"看,这个飞轮的假设前提也相同:改进 harness 基础设施比调整模型权重带来更大、更可控的实际提升,因为改进对象明确(具体 policy 规则、工具校验脚本、输出合约),改进结果可验证(eval gate),改进路径可复跑(codex_handoff.md 是可版本化的文档)。
Feedback-derived Evals(反馈驱动的测试生成)
这套流程里最值得关注的工程环节是 Feedback → Evals 转换:
- 人工 feedback 格式:
{ summary, required_observations: [...], prohibited_claims: [...] } - LLM feedback 格式:
{ observations: [...] } - 转换后的 eval 包含:rubric(llm-rubric judge 用)+ deterministic_assertions(
contains/not-contains)+ pass/fail 示例
这种结构使 eval 既能捕捉字面要求(确定性断言),又能检查语义质量(rubric judge),而且由 trace 中的真实失败案例生成,不是凭空构想的假设场景。
与 Evaluator-Optimizer(评估器-优化器)的区别在于时态:Evaluator-Optimizer 是运行时在线评估(边执行边判断);Feedback-derived Evals 是离线生成可复跑测试(把观察固化成未来的判断标准)。
示例中的 generated evals 不只是“让 LLM 再评价一次”。每条 eval 都来自 trace 和 feedback,包含 rubric、确定性断言、建议通过样例和失败样例。Promptfoo 再用自定义 provider 重放 trace 输出,检查当前 harness 是否满足这些条件。
这个结构适合把专家反馈转成长期回归:例如财务尽调场景里,人工反馈指出 ARR 必须使用 finance-controlled source of truth、客户集中度必须 roll up 到 parent account、SOC 2 Type I 和 Type II 不能混淆、没有支撑的 NRR 和 CAC payback 必须拒答。生成 eval 后,这些要求不再只是一次 review 里的评论,而会在未来 harness 修改后继续运行。
风险也很明确:generated eval 首轮仍需要人类审查。模型可以把反馈翻译得太宽、太窄,或只检查表面词句。Cookbook 的第二张图把“Eval review”列为可插入的人类 gate,原因正是 eval gate 一旦变成自动合并依据,错误的 gate 会长期塑造系统行为。
人类 gate 的放置点
Cookbook 的 human-gates 图强调,同一个 loop 支持不同自动化程度:可以全自动,也可以在若干关键点人工卡口。
flowchart LR
R["Trace review\n补充领域反馈"] --> E["Eval review\n收紧 gate"]
E --> P["PR review\n检查 Codex diff"]
P --> M["Merge approval\n按策略部署"]
M --> A["Autonomous path\n高置信时由策略驱动"]
这比“human-in-the-loop”更具体:人类可以在 trace review 阶段定义什么算错,在 eval review 阶段校准自动验收标准,在 PR review 阶段检查实现,在 merge approval 阶段控制发布风险。随着 eval suite 和 harness 变可信,某些 gate 可以从人工批准变成策略驱动。
与 Loop Engineering 的关系
Loop Engineering(循环工程) 关心的是长期系统如何触发、验证、记录状态并决定下一步。Agent improvement loop 是其中一种更窄的模式:它不直接处理“明天要做什么任务”,而处理“这个 Agent harness 如何从真实运行中持续变好”。
可以把它看成三层反馈的中间层:
| 层级 | 反馈对象 | 周期 |
|---|---|---|
| Agent run | 单次回答、工具调用和 artifact | 分钟级 |
| Agent improvement loop | prompt、工具策略、验证器、输出契约和 trace 采集 | 小时到天 |
| 产品/组织 loop | 任务定义、业务指标、风险政策和发布节奏 | 周到月 |
这个分层避免把所有问题都塞给单次 Agent run。单次 run 应该尽力完成任务;改进 loop 负责把 run 中暴露的问题变成 harness 修改;产品 loop 决定哪些行为值得优化、哪些风险必须保留人工判断。
与相邻概念的关系
- Pi — 用统一模型 API、Agent runtime、树形会话、TUI 与深扩展点实现“极简核心 + 可组合工作流”的 harness 案例;其默认无内置权限系统也清楚展示了扩展性与治理的边界
- Agent Engineering Roadmap — 从最小 loop、工具协议、上下文和技能,到长任务 harness、eval 与安全的学习导航
- HALO(层次化 Agent 循环优化) — Harness 改进飞轮中的分析层:从 trace + feedback + evals 生成排序改进建议
- ETCLOVG Taxonomy(ETCLOVG 分类法) — Harness 七层结构的系统化定义与 170+ 项目映射
- Agent Loop(智能体循环) — Harness 在单个 Agent 内部编排推理、工具调用和终止状态
- Loop Engineering(循环工程) — 解决的问题域不同:Harness 优化单次执行的可靠性;Loop 在此基础上解决跨轮次持续运行——状态如何跨轮续接、QA 结果如何驱动"继续/修复/挂起/停机"的分支决策、目标如何随反馈动态调整。Harness 是 Loop 的安全边界(Loop 是驱动力,Harness 是约束力)
- Dynamic Workflows(动态工作流) — 将 workflow script、Runtime 调度和多 Agent 验证收敛结合起来的产品化编排能力
- Evals(评估) — V 层的核心反馈机制
- Agent Worktree(Agent 工作树) — 多 Agent 并行执行时的工作区隔离约束
- Context Engineering(上下文工程) — C 层(上下文与记忆管理)是 harness 的子层
- Agent Sandbox(Agent 沙箱) — E 层,harness 的物理执行基底
- Model Context Protocol(模型上下文协议) — T 层核心标准
- Context Rot(上下文腐烂) — C 层和 O 层共同面对的长视野可靠性问题
- Goodhart’s Law(古德哈特定律) — G 层和 V 层防范的核心陷阱
- Closed vs Open Tasks(封闭性任务与开放性任务) — Harness 的核心工程价值之一:把开放性任务拆解为封闭性子任务
- Hallucination(幻觉) — Harness 通过验证循环和护栏控制幻觉传播
- Agent Guardrails(Agent 护栏) — Harness G 层中输入、动作、输出和人工审批的分层控制机制
- Claude Code — 最完整的公开 harness 参照实现,
.claude/目录布局体现七层分工