Harness Engineering 完全指南

Harness Engineering 完全指南svg xmlns http www w3 org 2000 svg style display none svg

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



 
  
    
     
      
     

1.1 词源与比喻

"Harness"原意是马具——缰绳、鞍具、嚼子——用来驾驭一匹强大但不可预测的动物的完整装备。这个比喻是刻意的:

  • 马 = AI 模型:强大、快速,但自己不知道该往哪里走
  • 马具 = Harness:引导、约束、使力量变得可控且有方向

1.2 技术定义

Agent = Model + Harness

如果你不是模型,你就是 Harness 的一部分。 — Vivek Trivedy, 2025

Harness 是除模型本身以外的所有代码、配置和执行逻辑。一个裸模型不是 Agent。但当 Harness 赋予它状态、工具执行能力、反馈回路和可执行的约束时,它就成了 Agent。

以编程 Agent 为例:

coding agent = AI model + harness

其中 Harness 包括:

  • 系统提示(System Prompt / AGENTS.md)
  • 工具、Skills、MCP 及其描述
  • 捆绑基础设施(文件系统、沙箱、浏览器)
  • 编排逻辑(Sub-agent 生成、任务交接、模型路由)
  • Hooks / 中间件(上下文压缩、续行、lint 检查等确定性执行逻辑)

1.3 类比理解:Harness 就像操作系统

可以用计算机架构来类比:

模型(大体上)接受文本、图像等输入并输出文本,仅此而已。开箱即用,它们无法做到:

  • 跨交互维护持久状态
  • 执行代码
  • 访问实时知识
  • 搭建环境和安装依赖来完成工作

这些都是Harness 层面的特性。LLM 的结构决定了需要某种将其包裹起来的机制才能完成有用的工作。


2.1 定义

Harness Engineering 由 Vivek Trivedy(Viv)首创,描述了利用 Harness 的各个配置点来定制和提升编程 Agent 输出质量与可靠性的实践。

Mitchell Hashimoto(Terraform、Ghostty 等工具的创建者)在 2026 年 2 月正式命名了这一术语,他这样定义:

“每当你发现 Agent 犯了一个错误,你就花时间工程化一个解决方案,使 Agent 永远不再犯同样的错误。”

核心问题:不是"如何让模型更聪明",而是"如何从今天的模型中获得最大收益"。

2.2 与 Context Engineering 的关系

Harness Engineering 是 Context Engineering 的子集:

  • Context Engineering(由 Dex 在 12-factor agents 中首次提出)是 “prompt engineering” 及多种系统性提升 AI agent 可靠性技术的超集
  • Harness Engineering 是 context engineering 的子集,主要涉及利用 harness 配置点来精心管理编程 agent 的上下文窗口

它回答的问题包括:

  • 如何赋予编程 Agent 新能力?
  • 如何向它传授训练数据中没有的代码库知识?
  • 如何在 CRITICAL: 始终做 XYZ 之外增加确定性?
  • 如何防止上下文窗口膨胀或充斥无效上下文?

3.1 范式转移

LLM API(对话式端点) → Harness API(可定制的运行时)client.chat.completions.create() → client.responses.create() → agent.query() 

这一转变反映了三个趋势的汇聚:

趋势一:模型商品化。 Claude、GPT、Gemini 在标准基准测试上的表现已非常接近。竞争优势不再是模型本身,而是模型周围的系统。

趋势二:Agent 从 Demo 走向生产。 2025 年大多数 Agent 部署还是概念验证;2026 年组织已在部署处理客户交互、编写生产代码、管理基础设施的 Agent。可靠性标准从"令人印象深刻的 Demo"变成了"不能宕机"。

趋势三:基准测试不再衡量真正重要的东西。 标准基准衡量单轮任务完成率,但生产 Agent 运行数小时甚至数天。

3.2 从"祈祷更好的模型"到"工程化 Harness"

许多团队面对 Agent 失败时的第一反应是:

  • “等 GPT-6 就好了”
  • “等指令遵循能力更好就好了”
  • “等我用的小众库进了训练数据就好了”

但经历数十个项目和数百个 Agent 会话后,反复得出的结论是:这不是模型问题,而是配置问题。

模型会变得更聪明,某些失败模式会消失。但也正因为更聪明了,我们会赋予它们更大、更难的新问题,而它们将继续以意想不到的方式失败。意外失败模式是非确定性系统的根本性问题。

3.3 HaaS(Harness as a Service)的诞生

Viv 提出了 HaaS(Harness as a Service) 的概念——通过丰富的 Agent Harness 生态系统,快速构建、定制和共享 Agent。Claude Code SDK 是这一范式的典型代表:其现有 Harness 可通过用户自己的提示、工具、上下文和权限轻松扩展,用户获得了一个开箱即用、可定制的 Agent 运行时。


Viv 在第一篇文章中提出了四个核心定制杠杆,HumanLayer 团队在实战中补充了两个。

4.1 杠杆一:系统提示(System Prompt)

系统提示是最直接的配置点。以 AGENTS.md 或 CLAUDE.md 文件为载体,定义 Agent 的行为准则、编码规范、项目结构等。

关键洞见(来自 OpenAI):上下文是稀缺资源。一个巨大的指令文件会挤占任务、代码和相关文档的空间。不要把 AGENTS.md 当作百科全书,把它当作目录,真正的知识库放在结构化的 docs/ 目录中。

4.2 杠杆二:工具 / MCP

Agent 通过工具与外部世界交互。MCP(Model Context Protocol)提供了标准化的工具接口。

工具设计的三个关键问题:

  1. Agent 需要做什么才能实现目标?是否有对应的工具?
  2. Agent 是否清楚何时使用这些工具?
  3. 能否通过合并多个工具为更原子化的结果来减少出错面?

工具不仅扩展能力,更是反馈机制。自定义 linter 错误消息同时充当修复指令——工具在 Agent 工作时教育 Agent。

4.3 杠杆三:上下文(Context)

给 Agent 的上下文越好,表现越好。关键上下文类型包括:

  • 代码文档和片段:保存为文件系统中的 Markdown 文件,不要让 Agent 去网上搜索你已经知道它会需要的内容
  • 记忆 / 用户个性化:将相关信息注入记忆文件或使用记忆服务
  • 最新知识:通过 Web 搜索和 Context7 等 MCP 工具访问超出知识截止日期的信息

经验法则:将所有关键上下文放在系统提示中,将其他有用上下文放在 Markdown 文件中并告知 Agent 何时及如何使用。

4.4 杠杆四:Sub-agents

Sub-agents 是最被低估的杠杆之一。它们通过 YAML 在 .claude/agents/{name}.md 中定义,解决两个核心问题:

专业化——让不同的 Sub-agent 专注于特定任务(如视觉检查、代码评审、测试编写)。

并行化——在隔离的上下文窗口中并行执行多个任务。

核心价值:上下文防火墙。 Sub-agents 确保离散任务在隔离的上下文窗口中运行,中间噪声不会积累到负责编排的父线程中。

4.5 补充杠杆一:Hooks

Hooks 提供确定性控制流,用于自动化集成。典型用途包括:

  • Pre-commit hook:运行 linter、类型检查
  • Stop hook:覆盖率下降时提示 Agent 提升覆盖率
  • 成功时完全静默(不占用上下文),失败时只暴露错误信息

HumanLayer 的 pre-commit hook 示例

OUTPUT=$(bun run --parallel "biome check . --write --unsafe || biome check . --write --unsafe" "turbo run typecheck" 2>&1)if [ $? -ne 0 ]; then echo "$OUTPUT" >&2 exit 2 # 退出码 2 告知 harness 重新激活 agentfi 

4.6 补充杠杆二:Skills

Skills 解决了一个关键问题:Agent 启动时过多工具或 MCP server 被加载进上下文,导致上下文腐烂(context rot)。

Skills 通过渐进式披露(progressive disclosure) 解决这个问题——不在启动时加载所有指令,而是在 Agent 需要时才按需加载相关知识模块。


5.1 Stripe Minions:400+ 工具的一次性编程 Agent

背景:Stripe 的代码库包含数亿行代码,主要用 Ruby(配合 Sorbet 类型系统),每年处理超过 1 万亿美元支付。Minions 属于"无人值守 Agent",每周负责超过 1,300 个 PR 的合并。

5.1.1 反馈左移(Shift Feedback Left)——深度解读

"左移"借用的是软件开发流程从左(开发)到右(部署)的时间线比喻。越早发现问题,修复成本越低——bug 在本地开发阶段修复的成本,远低于在 CI 中或生产环境中修复的成本。Stripe 将这一原则极致化,构建了分层的反馈架构:

代码变更 ↓[层 1] Pre-push Hooks(预推送钩子) 基于启发式规则自动运行相关 linter 自动修复常见问题(autofix) 耗时 < 1 秒 ↓[层 2] 本地 Linting(后台守护进程) 预计算并缓存适用规则 耗时 < 5 秒 ↓[层 3] CI 选择性测试 从 3,000,000+ 个测试中智能选择子集运行 已知失败模式 → 自动修复器自动处理 ↓如果失败 → Agent 获得一次修复机会 ↓如果再次失败 → 分支交回人工工程师 

关键设计:最多两轮 CI(at most two CI rounds)。 这个上限是刻意为之的。LLM 在反复重试同一问题时收益递减——第一次重试可能解决 80% 的可修复问题,第二次也许再解决 10%,第三次可能只能再解决 2%,而每次重试的算力和时间成本是相同的。更多轮次消耗更多 token 和算力,改进却不成比例。知道何时停止与知道如何开始同样重要。

Pre-push hooks 的核心价值在于:它们在代码到达 CI 服务器之前就运行本地 linter 和自动修复,将问题消灭在最廉价的阶段(本地机器上,秒级完成),避免为失败的 CI 运行付出时间和算力成本。对 Agent 来说,这更加重要——每次 CI 失败不仅浪费计算资源,还会向 Agent 的上下文窗口中注入大量错误信息,加速上下文腐烂。

5.1.2 Blueprints(蓝图)——混合编排的核心机制

蓝图是 Stripe 最精妙的设计之一。它不是纯粹的工作流(固定步骤序列),也不是纯粹的 Agent 自由决策,而是将确定性代码节点与自由流动的 Agent 子任务混合在一起的混合工作流。

[确定性] 克隆仓库,设置环境 ↓[Agent 循环] 理解任务,规划实现方案 ↓[Agent 循环] 编写代码 ↓[确定性] 运行配置好的 linter(< 5 秒) ↓[确定性] 推送分支 ↓[Agent 循环] 修复 CI 失败(如有) ↓[确定性] 推送最终分支,遵循 PR 模板 ↓PR 准备就绪,等待人工审查 

上图中,方形节点为确定性节点,圆形节点为 Agent 循环节点。这种分离至关重要:某些任务永远不应该留给 Agent 的判断——linter 总是要运行的,分支总是要按照特定方式推送并遵循公司 PR 模板的。将这些步骤确定性化可以:

  1. 节省 token——确定性节点不消耗 LLM 推理 token
  2. 减少错误——不给非确定性系统犯可预防错误的机会
  3. 保证关键步骤每次都发生——不依赖 Agent"记住"要做某件事

Stripe 的核心观点:“把 LLM 放入有围墙的盒子里,积累起来就产生了系统级的可靠性收益。模型不运行系统,系统运行模型。”

团队还可以为专项需求构建自定义蓝图,例如大规模代码库迁移任务,其蓝图可能包含更多确定性节点(如批量文件变更、依赖版本锁定),或特殊领域任务(如不稳定测试修复),其蓝图可能包含额外的自动化诊断步骤。

5.1.3 Agent 需要与人类工程师相同的上下文和工具

这是 Stripe 最重要的设计哲学之一,值得展开理解。

工具层面:Minions 连接到 Toolshed——Stripe 的集中式 MCP 服务器,暴露了近 500 个工具,跨越内部系统(文档检索、工单系统、构建状态、代码搜索)和第三方 SaaS 平台。关键的是,这套工具并非为 Agent 专门设计——人类工程师通过 Claude Code、Cursor 等工具访问的是完全相同的 Toolshed。

┌──────────────────────────────────────────────────┐│ Toolshed 架构 ││ ││ 集中式 MCP 服务器(~500 个工具) ││ ├── 内部文档检索 ││ ├── 工单系统(获取 ticket 详情) ││ ├── 构建状态查询 ││ ├── 代码搜索(Sourcegraph 集成) ││ └── 第三方 SaaS 集成 ││ ││ 使用者(共享同一套工具): ││ ├── Minion(无人值守 Agent) ││ ├── Claude Code(有人值守工具) ││ └── Cursor(有人值守工具) ││ ││ 注意:每个 Minion 只获取任务相关的精选子集 ││ (过多工具会压垮上下文窗口、降低性能) │└──────────────────────────────────────────────────┘ 

上下文层面:Stripe 非常谨慎地使用全局规则。他们将规则限定在特定子目录和文件模式的范围内(目录范围的规则文件)。当 Agent 在文件系统中移动时,自动获取仅与当前工作位置相关的规则,而非在启动时一次性加载所有规则——后者会在 Agent 开始工作之前就填满上下文窗口。

更精妙的是,这些规则文件与人类使用的工具(Cursor、Claude Code)读取的完全相同——无需重复维护,也没有 Agent 专用的额外开销。Stripe 采用了 Cursor 的规则文件格式,并在三个 Agent 系统(Minions、Cursor、Claude Code)之间同步:为一个系统编写的指导文档,对其他两个同样有效。投入一份时间,获得三倍回报。

这个设计哲学的深层含义:不要为 Agent 构建一套独立的、事后拼凑的工具链。如果你的开发者平台已经出色(标准化环境、完善的测试套件、内部工具),Agent 就能直接利用这个优势。对人类好的东西,对 Agent 同样好。 反过来说,如果人类工程师在你的代码库中都举步维艰,Agent 只会更差。

5.1.4 执行沙箱(Devboxes)

每个 Minion 运行在一个 devbox——标准化的 AWS EC2 实例,预装完整代码库、预热的 Bazel 和类型检查缓存,10 秒内从热备池分配。遵循"牲畜而非宠物"原则:每个实例完全相同且可丢弃。由于运行在 QA 环境中,已与生产数据隔离,Agent 可以完整权限运行,无需确认提示——任何错误的影响半径都被限制在一台可丢弃的机器上。

重要的是:Stripe 构建 devbox 并不是为了 Agent,而是为了人类。 并行性、可预测性和隔离性,早在 LLM 出现之前就已经是工程师渴望拥有的属性。

5.1.5 Minions 五层核心组件全景

整个 Minions 架构是一条将聊天消息转化为生产就绪 PR 的五层流水线,每一层解决一个特定的工程问题:

层次 组件 解决的问题 核心技术 第一层 触发(Invocation) 工作入口在哪里? Slack、CLI、Web UI、工单系统、自动化系统 第二层 执行沙箱(Devboxes) Agent 在哪里安全运行? AWS EC2 预热池,10 秒启动,QA 隔离 第三层 Agent 核心(Goose Fork) 用什么 Agent 运行时? Block 开源 Goose 的深度定制 fork,剥离所有人类交互元素 第四层 蓝图编排(Blueprints) Agent 如何执行任务? 确定性节点 + Agent 循环节点的混合工作流 第五层 Toolshed(~500 MCP 工具) Agent 如何获取上下文和能力? 集中式 MCP 服务器,目录范围规则文件

第三层特别值得注意:Stripe 的 Agent harness 是 Block(原 Square)开源编程 Agent Goose 的一个深度定制 fork,专门针对完全无人值守的操作进行了改造。与 Cursor 或 Claude Code 这类面向交互式结对编程设计的工具不同,Minions 将所有面向人类的设计元素全部剥离——可打断性、确认对话框、人类触发的命令——并针对一次性任务完成进行优化。这是整个架构中最重要的设计决策之一:为无人值守的工作场景专门重新设计 Agent 运行时,而非在有人值守工具上打补丁。

系统关键指标:

指标 数值 Agent 框架 Block 的 Goose 的内部 fork 执行环境 AWS EC2 devboxes,10 秒分配 可用 MCP 工具数量 ~500(通过 Toolshed) CI 测试套件规模 3,000,000+ 个测试 最大 CI 重试轮次 2 轮 每周合并 PR 数量 1,300+ PR 中人工编写代码比例 0%

5.2 OpenAI:百万行代码零人工实验

实验概况:

  • 3 名工程师(后扩展到 7 人)驱动 Codex
  • 5 个月内产出约 100 万行代码(应用逻辑、基础设施、工具、文档、内部开发工具)
  • 约 1,500 个 PR 被开开并合并
  • 人均每天 3.5 个 PR,且吞吐量随团队增长而提升
  • 全程零人工编写代码——这成为团队的核心哲学

“软件工程团队的首要工作不再是编写代码,而是设计环境、明确意图、构建反馈回路,让 Agent 能够可靠地工作。” — OpenAI 团队

5.2.1 架构即护栏(Architecture as Guardrails)——深度解读

OpenAI 团队强制执行了一个严格的分层架构,其核心设计远非简单的"代码分层"。理解其精妙之处需要抓住三个关键要素:

(一)刚性架构模型:有限的层次 + 严格的依赖方向

每个业务领域被划分为固定的层次集合,依赖方向经过严格验证,允许的边数量有限。这意味着:

  • 表示层只能调用业务逻辑层,不能直接访问数据层
  • 跨领域调用只能通过定义好的接口进行
  • 任何超出架构范围的代码被机械性地禁止
    ┌─────────────────────────────────────────────────┐│ OpenAI 刚性架构模型示例 ││ ││ 领域 A 领域 B ││ ┌─────────────┐ ┌─────────────┐ ││ │ 表示层 │ │ 表示层 │ ││ │ (API/UI) │ │ (API/UI) │ ││ └──────┬──────┘ └──────┬──────┘ ││ ↓ (仅允许) ↓ (仅允许) ││ ┌─────────────┐ ┌─────────────┐ ││ │ 业务逻辑层 │ ←——————→ │ 业务逻辑层 │ ││ │ (Services) │ (通过接口) │ (Services) │ ││ └──────┬──────┘ └──────┬──────┘ ││ ↓ (仅允许) ↓ (仅允许) ││ ┌─────────────┐ ┌─────────────┐ ││ │ 数据层 │ │ 数据层 │ ││ │ (Repos) │ │ (Repos) │ ││ └─────────────┘ └─────────────┘ ││ ││ ✗ 表示层 → 数据层 (禁止跨层调用) ││ ✗ 数据层 → 业务逻辑层 (禁止反向依赖) ││ ✗ 领域 A 数据层 → 领域 B 数据层 (禁止跨域底层耦合)│└─────────────────────────────────────────────────┘ 

(二)通过自定义 Linter 和结构性测试以机械方式强制执行

这里的"机械方式"是关键。不是在文档里写着"请遵守分层架构"(Agent 会忽略),而是通过代码级别的自动检查来物理性地阻止违规。这些自定义 linter 本身也是由 Codex 生成的——体现了一种有趣的递归:Agent 编写约束自己行为的工具。

结构性测试(structural tests)则是另一种机械验证手段,类似 ArchUnit(Java 生态)或 dependency-cruiser(JavaScript 生态),在测试套件中用断言验证代码的结构性属性:模块依赖方向、包的命名规则、接口的存在性等。这些不是功能测试——它们测试的是代码本身的形状是否符合架构要求。

(三)为什么"迂腐的规则"对 Agent 是倍增器

“在以人类为主导的工作流中,这些规则可能感觉迂腐或令人掣肘。对 Agent 而言,它们变成了倍增器:一旦编码完成,便同时作用于所有地方。” — OpenAI 团队

人类开发者通常对过于严格的架构约束感到不适——它限制了灵活性和"先快速验证再清理"的工作方式。但 Agent 没有"审美偏好",没有"快速试验"的冲动,它只按照规则行事。严格的架构规则在 Agent 手中反而变成了巨大的优势:

  • Agent 不会"偷懒"绕过规则
  • 规则一次编写,永久生效,在所有 Agent 会话中同时作用
  • 每个违规都在本地被捕获,不需要人工审查才能发现

反直觉的洞见(来自 Birgitta Böckeler / Martin Fowler):提高对 AI 生成代码的信任和可靠性,需要缩小解决方案空间而非扩大它。我们未来可能会根据技术栈和代码库结构是否对 Harness 友好来做技术选型,而非单纯追求灵活性。

5.2.2 工具即反馈(Tools as Feedback)——深度解读

这是 OpenAI 文章中最精妙的想法:自定义 linter 错误消息同时充当修复指令。

传统 Linter 错误消息 vs. Agent 优化的 Linter 错误消息:

传统 linter 错误消息(面向人类):──────────────────────────────ERROR: Layer violation in module "payments" - payments/api/handler.go imports payments/db/repo.go - Expected: api layer should not import db layer directly↑ 人类看到这个消息后,凭经验知道该怎么修复。 Agent 看到这个消息后,可能尝试各种错误方向。Agent 优化的 linter 错误消息(面向 LLM):──────────────────────────────ERROR: Layer violation in module "payments" - payments/api/handler.go imports payments/db/repo.go - VIOLATION: api layer must not import db layer directly. - FIX: Create or use an existing service in payments/services/ that wraps the db access. The api handler should call the service, and the service should call the repo. - EXAMPLE: See payments/services/refund_service.go for the correct pattern. - REFERENCE: docs/architecture/layer-rules.md↑ Agent 看到这个消息后,有明确的修复路径: 1. 知道要在哪个目录创建什么文件 2. 有一个可参考的正确模式 3. 有详细的架构文档链接 

这创造了一个零人工干预的紧密反馈回路:

Agent 写代码 ↓自定义 Linter 运行 ↓发现架构违规 ↓错误消息 = 修复指令(注入 Agent 上下文) ↓Agent 按指令修复 ↓Linter 再次运行 ↓通过 ✓ 

整个过程没有人类参与。 工具在 Agent 工作时教育 Agent——这是一种积极意义上的"提示注入"。

这一设计的深层意义在于:传统的 linter 是为人类设计的,假设读者有经验、有上下文、能推断修复方式。为 Agent 设计的 linter 需要把修复步骤说清楚,就像写给一个聪明但缺乏代码库特定知识的新人看的一样。

5.2.3 文档即记录系统 + 垃圾回收

文档管理:AGENTS.md 作为目录而非百科全书。OpenAI 团队发现,巨大的指令文件会产生三个问题:

  1. 挤占任务、代码和相关文档的上下文空间——上下文是稀缺资源
  2. 当一切都"重要"时,什么都不重要——Agent 开始模式匹配而非有意识地导航
  3. 单体文档即刻腐烂——Agent 无法分辨哪些规则仍然有效,人类也停止维护

解决方案:AGENTS.md 只包含目录和核心原则,真正的知识库在结构化的 docs/ 目录中,通过引用按需加载。

垃圾回收:周期性机制扫描代码库中因 Agent 生成而累积的不一致性、冗余和架构漂移(“熵”),让 Agent 提出修复建议。这特别重要,因为 Agent 会复制已有的模式(包括不好的模式),且不带有人类工程师的审美判断和对技术债的主动感知。

“我们目前最艰难的挑战集中在设计环境、反馈回路和控制系统上。” — OpenAI 团队

5.3 两个案例的共同主题

维度 Stripe Minions OpenAI Codex Agent 类型 无人值守 无人值守 规模 数亿行代码库 从零到百万行 工具 400+ MCP 工具 自定义 linter + 结构性测试 核心洞见 Agent 需要和人类相同的工具 瓶颈是环境设计,不是代码编写 反馈机制 Blueprints + pre-push hooks 自定义 linter 充当修复指令

Charlie Guo 在《正在形成的 Harness Engineering 实践手册》中总结了跨组织的共同规律,Mitchell Hashimoto 的个人实践进一步验证了这些模式。

6.1 两部分工作

Harness Engineering 有两个互相交织的部分:

第一部分:构建环境。 瓶颈从来不是 Agent 编写代码的能力,而是周围缺乏结构、工具和反馈机制。当 Agent 卡住时,将其视为环境设计问题。

第二部分:管理工作。 在执行之前与 Agent 进行大量规划,担任架构的"仁慈独裁者",同时交付自己没有读过的代码。

这两部分不是顺序进行的。Agent 的失败告诉你环境缺少什么;更好的环境让管理摩擦更小。

6.2 四大反复出现的实践

实践一:架构即护栏(Architecture as Guardrails)

Agent 在拥有严格边界和可预测结构的环境中最为高效。在以人类为主导的工作流中,这些规则可能感觉迂腐;对 Agent 而言,它们是倍增器——一旦编码完成,便同时作用于所有地方。

反直觉的启示:提高对 AI 生成代码的信任和可靠性,需要缩小解决方案空间而非扩大它。

实践二:工具既是地基也是反馈(Tools as Foundation and Feedback)

维护团队依赖的工具列表,确保有人负责让这些工具对 Agent 可访问。工具不只扩展 Agent 能做的事,它们提升了 Agent 已在做的一切事情的可靠性。

实践三:文档即记录系统(Documentation as System of Record)

AGENTS.md 作为目录,docs/ 目录作为知识库。每个架构决策、每个模块边界、每个编码规范,都需要被写下来。

实践四:每个团队需要一个 Agent 负责人(Agents Captain)

Greg Brockman 的建议:指定一个负责思考 Agent 如何融入团队工作流的人。

6.3 实践中的 Do’s 和 Don’ts

有效的做法:

  • 偏向交付,只在 Agent 实际失败时才添加配置
  • 设计、测试、迭代——并丢弃无用的东西
  • 通过仓库级配置将经过实战检验的配置分发给整个团队
  • 优化迭代速度,而非"第一次尝试就一击即中的概率"
  • 给 Agent 一套能力后仔细削减暴露给模型的内容

无效的做法:

  • 在还没遇到真实失败之前就试图设计理想的 Harness 配置
  • 以"以防万一"的心态安装几十个 Skills 和 MCP Servers
  • 在每个 Agent 会话结束时运行完整的测试套件(超过 5 分钟)
  • 试图微观优化哪些 Sub-agents 可以访问哪些工具

Viv 在 LangChain Blog 上的第二篇文章从一个独特的角度出发:从模型原生无法做到的事情反推 Harness 每个组件存在的原因。

7.1 反推逻辑

核心方法论:

我们期望的 Agent 行为 → 帮助模型实现这一目标的 Harness 设计

期望行为 模型的原生局限 Harness 解决方案 持久存储与上下文管理 模型只能操作上下文窗口内的知识 文件系统抽象 + 文件操作工具 自主解决问题 Harness 只能执行预配置的工具 Bash + 代码执行(通用工具) 安全执行与核验 本地运行 Agent 代码有风险 沙箱 + 验证工具 记忆与搜索 模型除权重和当前上下文外无额外知识 AGENTS.md + Web 搜索 + MCP 对抗上下文腐烂 上下文填满后推理能力退化 压缩(Compaction)、输出卸载、Skills 渐进式披露 长周期自主执行 过早停止、跨窗口不连贯 Ralph Loop + 规划 + 自我验证

7.2 文件系统:最基础的 Harness 原语

文件系统是最基础的 Harness 原语,因为它解锁了:

  • Agent 获得了读取数据、代码和文档的工作空间
  • 工作可以增量添加和卸载,不必把一切保存在上下文中
  • 文件系统是天然的协作界面,多个 Agent 和人类可以通过共享文件协调

7.3 上下文腐烂的三重防线

上下文压缩(Compaction):智能卸载并总结现有的上下文窗口,使 Agent 能够继续工作。

工具调用输出卸载:保留超出 token 阈值的工具输出的头尾,将完整输出卸载到文件系统。

Skills 渐进式披露:避免启动时将过多工具描述加载进上下文,保护模型免受上下文腐烂侵害。

7.4 模型训练与 Harness 设计的耦合

前沿编程模型是在其 Harness 上进行后训练的(例如 Claude 在 Claude Code 上,GPT-5 Codex 在 Codex 上)。这创造了反馈循环:有用的原语(primitives) 被发现、添加到 Harness、然后在训练下一代模型时被使用。

什么是"原语"? 在 Harness Engineering 语境中,原语指的是 Harness 中最基础、不可再分的功能构建块——它们是其他更复杂能力得以构建的基石。每一种原语对应模型的一种原生局限,为模型提供了一种原本不具备的基础能力。

原语之所以重要,是因为它们构成了一个协同演化的循环:开发者在实践中发现某种 Harness 原语特别有用(如文件系统操作)→ 原语被添加到 Harness 中 → 模型在包含这些原语的 Harness 上被后训练 → 模型在使用这些原语时变得更擅长 → 新的原语需求被发现 → 循环继续。

例如,Codex 模型与 Codex harness 的 apply_patch 工具耦合如此之紧密,以至于 OpenCode(Claude Code 的开源替代品)不得不专门添加 apply_patch 工具来模拟 Codex harness,以提升 Codex 模型在 OpenCode 中的性能。这就是原语与模型协同演化的一个具体例子。

但最适合你任务的 Harness 不一定是模型后训练时所用的那个。 Terminal Bench 2.0 排行榜显示,Opus 4.6 在 Claude Code 中排名第 33,但在不同 Harness 中跃升至第 5。这说明模型可能对其训练时的 Harness 存在过拟合——仅通过更换 Harness,就能带来巨大的性能提升。


HumanLayer 团队(Kyle)的文章提供了面向编程 Agent 构建者的战术工具箱。

8.1 Harness 组件全景

编程 Agent 的 Harness 包含以下可配置层次:

  • Agentfile(AGENTS.md / CLAUDE.md):行为准则和编码规范
  • MCP Servers:外部工具集成
  • Skills:渐进式知识披露模块
  • Sub-agents:专业化和并行化的上下文防火墙
  • Hooks:确定性控制流(pre-commit、stop 等)
  • 反压机制(Backpressure):验证 Agent 工作的反馈回路

8.2 反压机制(Backpressure)提升成功率

什么是"反压机制"? “反压”(Backpressure)原本是流体力学和分布式系统中的概念,指下游系统对上游系统施加的"回推力"——当下游处理不过来时,它会向上游发出信号要求减速或修正。在 Harness Engineering 中,反压机制指的是让 Agent 在完成工作后能自动检验其产出质量、并在不合格时被迫回头修正的反馈回路。

没有反压的 Agent 就像一个不检查自己作业的学生——交上去的东西可能全对,也可能全错,但它自己不知道。有了反压,Agent 在"交卷"之前会被强制要求"验算",不合格就打回重做。

用编程 Agent 成功解决问题的概率,与 Agent 验证自身工作的能力高度相关。关键的验证机制(即反压来源)包括:

  • 类型检查和构建步骤(强类型语言效果更好——类型系统本身就是一种反压,它会拒绝不合规的代码)
  • 单元测试和/或集成测试(测试失败 = 反压信号,告知 Agent “你写的代码不对”)
  • 代码覆盖率报告(HumanLayer 有一个 Stop hook,在覆盖率下降时提示 Agent 提升覆盖率)
  • UI 交互和测试集成(Playwright、agent-browser 等——让 Agent 像用户一样操作界面来验证行为)

反压机制的设计核心:上下文效率。 这是 HumanLayer 团队吃过苦头后学到的关键教训:

早期做法(失败的):───────────────────Agent 变更代码 → 运行完整测试套件 → 4000 行"✓ PASS"输出 淹没上下文窗口 ↓ Agent 失去对任务的追踪 开始对刚读过的测试文件产生幻觉改进后的做法(成功的):───────────────────Agent 变更代码 → 运行测试 → 全部通过?→ 静默(零上下文开销) ↓ 有失败?→ 只暴露失败信息(精准反压) Agent 定向修复 

好的反压机制遵循三条原则:

  1. 成功时静默——通过的测试、成功的构建不应向上下文注入任何信息。沉默就是最好的信号。
  2. 失败时精准——只暴露错误信息,且尽可能包含修复指引(参见 OpenAI 的"linter 错误即修复指令")。
  3. 运行要快——反压太慢(如完整测试套件跑 5 分钟以上)就失去了在 Agent 循环中嵌入的价值。HumanLayer 建议运行子集而非全量。

这三条原则可以总结为一个公式:好的反压 = 快速 + 静默成功 + 精准失败。

8.3 构建者的核心原则

“下次你的编程 Agent 表现不如预期时,在责怪模型之前,先检查一下 Harness。模型可能没问题,只是技能问题(It’s just a skill issue)。” — HumanLayer


Birgitta Böckeler(Thoughtworks 杰出工程师)在 Martin Fowler 网站上发表的文章,将控制论(Cybernetics)框架引入 Harness Engineering,建立了最完整的理论体系。

9.1 三层同心圆

"Harness"一词在不同限界上下文中含义各异:

  • 最内层:模型——被套上 Harness 的终极对象
  • 中间层:构建者 Harness——编程 Agent 产品内置的系统提示、编排、检索机制等
  • 最外层:用户 Harness——我们(使用者)针对自身用例和系统构建的外部 Harness

9.2 前馈(指引)与反馈(传感器)

为编程 Agent 套上 Harness 的核心机制:

指引(前馈控制,Feedforward)——预测 Agent 的行为,力求在其行动之前加以引导。提高 Agent 首次创建良好结果的概率。

传感器(反馈控制,Feedback)——在 Agent 行动之后进行观察,帮助其自我纠正。当传感器产生针对 LLM 消费优化的信号时尤其强大——例如包含自我纠错指令的自定义 linter 消息。

单独使用其中一种会产生问题:仅有反馈则 Agent 会不断重蹈覆辙;仅有前馈则 Agent 编码了规则却永远无从验证它们是否生效。

9.3 计算型 vs. 推断型

指引和传感器各有两种执行类型:

类型 计算型(Computational) 推断型(Inferential) 执行主体 CPU GPU/NPU(LLM) 特点 确定性、快速 语义分析、更慢更贵 示例 Linter、类型检查、测试 AI 代码评审、LLM-as-judge 可靠性 结果可靠 具有非确定性

组合示例:

方向 类型 示例实现 前馈 推断型 AGENTS.md、Skills 前馈 计算型 LSP、CLI、代码迁移工具 反馈 计算型 ESLint、类型检查、测试覆盖率 反馈 推断型 AI 代码评审 Agent 反馈 混合型 变异测试 + 质量评审

9.4 时序:保持质量左移

关键问题是将检查分布在开发时间线的不同节点:

  • 集成前:速度足够快的操作(linter、快速测试套件、基础代码评审 Agent)
  • 集成后流水线:更昂贵的操作(变异测试、全面代码评审、架构审查)
  • 持续监控:代码库漂移检测(死代码检测、依赖扫描器)和运行时反馈(SLO 退化、日志异常)

9.5 三种监管类别

可维护性 Harness——调节内部代码质量。目前最容易实现,因为有大量既有工具可用。计算型传感器可靠地捕捉结构性问题(重复代码、圈复杂度、架构漂移),LLM 能部分解决需要语义判断的问题但成本高昂。

架构适应性 Harness——定义和检查应用架构特性,本质上是适应性函数(Fitness Functions)。包括性能需求的 Skills、可观测性编码规范等。

行为 Harness——确保应用按需运作。目前最具挑战性,大多数人依赖 AI 生成的测试套件 + 手工测试,但这还不够好。

9.6 可 Harness 性与 Harness 模板

并非每个代码库都同等地适合被套上 Harness。 强类型语言天然拥有类型检查作为传感器;清晰可定义的模块边界允许构建架构约束规则。

Harness 模板的概念正在浮现:一套将编程 Agent 约束到某种拓扑结构、规范和技术栈上的指引与传感器集合。

Ashby 的必要多样性定律提供了理论支撑:调节器必须具有至少与其所治理的系统同等的多样性。定义拓扑是一种多样性缩减动作——承诺一种拓扑就缩窄了输出空间,使构建全面的 Harness 变得可行。

9.7 人类的角色

“一个好的 Harness 不一定要完全消除人类的介入,而是要将介入引导到我们的输入最重要的地方。” — Birgitta Böckeler

人类开发者将自身的技能与经验作为隐式 Harness 带入每个代码库。编程 Agent 不具备社会责任感,对 300 行函数没有审美厌恶感,没有"我们在这里不这么做"的直觉,也没有组织记忆。Harness 是将人类经验外化和显式化的一种尝试,但它只能做到这么多。

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

在这里插入图片描述

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

小讯
上一篇 2026-04-21 13:25
下一篇 2026-04-21 13:23

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/261881.html