> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# Agent 老是散架？该修的是 harness，不是提示词
- URL: https://www.hubwiz.com/blog/harness-engineering-agent-guide-lunar/
- Published: 2026-11-02T05:23:32.000Z
- Updated: 2026-11-02T05:24:53.000Z
- Description: 大多数 agent 失败不是推理失败，是环境失败。提示词改变一次尝试，harness 改变每一次尝试。19 节清单：从任务契约到变更回执，从工具网关到"构建是为了删除"。
- Author: admin
- Tags: AI Agent, 软件工程, 代码评审, 验证

**大多数人在改错的那一层。**

agent 失败的时候，他们重写提示词。再失败，就加更多指令。然后换模型、加工具、把上下文窗口调大，希望下一次跑出来不一样。

但很多 agent 失败不是推理失败，是**环境失败**：

- 它不知道该看哪些文件；
- 它在对的地方用了错的工具；
- 它把上一轮会话里做的决定丢了；
- 它没跑检查就宣称成功；
- 它在一次部分失败之后重复了同一个动作；
- 它拿到了本该需要审批的权限。

模型未必是问题所在；**模型周围的系统不完整**。这个系统叫 harness，而设计它正在变成一门自己的工程学科。

> **提示词改变一次尝试，harness 改变每一次尝试。**

下面这份指南来自英文长文《Harness Engineering: The Complete Guide to Building AI Agents That Don't Fall Apart》（Lunar，2026-09-06）。原文 19 节，本文完整编译全部要点，并在最后加上我们的对照整理与边界说明。

---

## 一、模型不是 agent

模型能推理、生成、比较、选择。但 agent 还必须与真实环境交互：理解任务、找到相关上下文、选择并使用工具、保持状态、遵守权限、检查结果、从失败中恢复、**证明工作确实完成了**。

模型是这套系统里的推理引擎，harness 是让推理变得可运行的一切。

```text
user request
     |
     v
+-----------------------------+
|           HARNESS           |
| contract | context | policy |
| tools    | state   | checks |
| traces   | recovery          |
+-----------------------------+
     |
     v
    model
     |
     v
real environment

```

**一个强模型装在弱 harness 里，仍然是弱 agent。** 它可能偶尔给出惊艳的单项回答，但在长任务、变化的环境与部分失败面前，表现会不稳定。

harness 工程的目标不是消除模型的不确定性，而是**把不确定性关进一个能观察、能验证、能恢复的系统里**。

## 二、从一份任务契约开始

大多数 agent 任务从一句模糊的意图开始："优化一下注册流程。" 这句话够对话用，不够自主执行用。

在 agent 动手之前，harness 应该把它变成一份**任务契约**，回答五个问题：

1. 必须存在的结果是什么？
2. 范围之内包含什么？
3. 什么不能变？
4. 什么证据能证明完成？
5. 哪些动作需要人批准？

```yaml
objective: reduce onboarding drop-off

scope:
  - signup flow
  - onboarding analytics

constraints:
  - do not change authentication
  - preserve existing mobile behavior

acceptance:
  - tests pass
  - analytics event is emitted
  - screenshots cover desktop and mobile

approval_required:
  - production deployment
  - database migration

```

这件事改变的是 agent 的问题：从"我下一步该做什么？"变成"**哪个动作让环境朝契约里的结果前进？**"

没有契约，agent 会为"看起来在做事"优化；有契约，它才能为"被验证的完成"优化。

## 三、给地图，不给手册

把整个仓库、整套文档、整段历史都塞进上下文，不叫上下文工程，叫**上下文洪水**。

harness 应该先给一张小地图，等细节相关时再让它去取。

```text
PROJECT MAP

product rules     -> docs/product/
architecture      -> docs/architecture.md
frontend          -> apps/web/
backend           -> services/api/
tests             -> tests/
commands          -> docs/commands.md
release rules     -> docs/release.md

```

这就是**渐进披露**：任务 → 项目地图 → 相关子系统 → 具体文件 → 局部说明。上下文该因为任务需要而展开，而不是因为信息存在而展开。

一个合格的"上下文编译器"要决定四件事：

- 什么永远需要；
- 什么可以稍后检索；
- 什么已经过期；
- 什么可以摘要，什么必须逐字保留。

**目标不是最大上下文，而是每个 token 的最大信号。**

## 四、造工具网关，不要堆工具

给 agent 二十个工具，不会让它变强，只会给它二十种犯错的方式。

每个工具都该有清晰的契约：

```text
TOOL: edit_file

inputs:
  path
  patch

preconditions:
  path exists
  path is inside allowed workspace

success evidence:
  patch applied
  resulting diff returned

failure behavior:
  no partial overwrite
  structured error returned

risk class:
  reversible

```

harness 要控制工具**怎么被暴露、怎么被使用**：隐藏无关工具、校验参数、限制路径与域名、挂超时、让重试幂等、归一化输出、对高风险动作要求确认、**返回证据而不是一句 success**。

由此产生一条重要的分离：

```text
model    decides intent
gateway  validates action
tool     changes environment
sensor   observes result

```

模型可以提议一个动作；**由网关决定这个动作是否足够合法、可以执行**。

## 五、把脑、手、历史分开

很多脆弱的 agent 把所有东西都塞进一段越来越长的转录里：推理、工具调用、文件、决定、错误、旧观察，全都在抢同一个上下文窗口。

更强的系统把三种职责分开：

| 部分              | 职责             | 它不需要什么     |
| --------------- | -------------- | ---------- |
| **脑（Brain）**    | 规划、推理、选择       | 不需要每一段原始事件 |
| **手（Hands）**    | 在受控环境里执行工具     | 不需要理解整个目标  |
| **历史（History）** | 保存持久事实、决定与运行状态 | 不需要会推理     |

模型需要的是**正确的当前状态**，不是全部事件；沙箱需要的是**安全执行一个有界的动作**，不是全盘理解；会话日志需要的是**在当前上下文消失之后仍然留住发生了什么**。

这种分离让长跑 agent 更容易恢复、检查和修复，也让你能替换其中一块而不用重建全部。

## 六、记忆必须变成持久状态

对话历史不是可靠记忆，它只是一个事件流。有用的记忆应该被转换成**显式状态**，至少保留四类：

| 类别            | 内容                  |
| ------------- | ------------------- |
| **FACTS**     | 关于环境的稳定信息           |
| **DECISIONS** | 做过的选择**以及理由**       |
| **PROGRESS**  | 已完成 / 进行中 / 阻塞 / 剩余 |
| **LESSONS**   | 应当改变未来行为的失败         |

```yaml
facts:
  - checkout validation lives in services/orders

decisions:
  - reuse the existing validation pipeline
  - reason: avoids a second source of truth

progress:
  completed:
    - added server-side rule
  remaining:
    - update integration test

lessons:
  - local test command requires TEST_DB_URL

```

这比"回放五十页转录、指望模型注意到那一行"有用得多。**原始历史存起来做审计，持久状态编译出来做执行。**

## 七、完成需要证据

agent 说"done"不是任务完成的证据，那只是又一个模型输出。完成必须由**环境里可观察的变化**来判定。

| 主张        | 证据             |
| --------- | -------------- |
| "bug 修好了" | 之前失败的测试现在通过    |
| "页面能用了"   | 浏览器流程走通        |
| "迁移是安全的"  | dry run 与回滚都通过 |
| "报告是对的"   | 数值与源数据一致       |
| "任务完成了"   | 每一条验收检查都通过     |

harness 应该**先跑最便宜的确定性检查**：

```text
syntax
  -> types
      -> focused tests
          -> integration tests
              -> visual or semantic review
                  -> human approval

```

**不要用另一个模型去回答编译器、schema、校验和、查询或测试能回答的问题。用模型处理歧义，用代码处理管道。**

模型可以提议"任务完成了"，只有环境能证明它。

## 八、验证应该攻击结果

Worker 和 evaluator 不该共享同一个目标：worker 努力做出最强的解法，**evaluator 努力找出它该被拒绝的理由**。

```text
worker
  -> produces candidate

verifier
  -> checks contract
  -> searches for missing cases
  -> tests unsupported claims
  -> attempts to break result

survives -> accept
fails    -> return targeted evidence

```

这种不对称很重要。**如果你让同一个 agent、在同一个上下文里"复查一下自己的活"，它通常会保住那个制造了错误的假设。**

有用的验证环节应该具备：明确的拒绝标准；能拿到产物；能拿到验收契约；需要时能换工具或换新上下文；**以及"只拒绝、不负责修"的权限**。

> 验证不是第二意见，是一次未遂的反证（attempted disproof）。

## 九、模型提议，策略授权

有些规则永远不该依赖"模型是否记得住"：没批准不发布、不暴露密钥、不在工作区之外写、不超预算、没跑过的测试不许标通过。

这些不是提示词里的建议，它们是**策略**。最安全的设计把策略放在推理回路之外：

| 风险档      | 动作            | 门          |
| -------- | ------------- | ---------- |
| 低风险      | 读文件、搜索、查看     | 自动         |
| 可逆变更     | 改工作区、跑测试      | 自动 + trace |
| 外部副作用    | 发消息、部署、购买     | **显式批准**   |
| 不可逆 / 敏感 | 删数据、轮换凭证、全局发布 | **硬闸或禁止**  |

**后果越强，门越硬。** 而自主并不是没有控制，**自主是在一个被清晰强制的边界里自由行动的能力**。

（这一条和我们拆 DeepSeek super-agent 时看到的设计是同一个思路：权限由代码强制，不由提示词决定。见文末对照。）

## 十、恢复要针对失败类别

最常见的"恢复"策略是：出错了，再试一次。那不是恢复，那是重复。

harness 应该**先分类，再选动作**：

| 失败类别     | 正确动作       |
| -------- | ---------- |
| 工具超时     | 退避后重试      |
| 参数非法     | 修工具调用      |
| 缺上下文     | 检索具体来源     |
| 测试失败     | 检查失败行为     |
| 权限被拒     | 申请批准或走安全路径 |
| 需求自相矛盾   | 升级给人       |
| 同一失败反复出现 | **停止循环**   |

一次重试至少应该改变一个相关条件，否则你就是在花钱复现同一个失败。

```text
observe
  -> decide
      -> act
          -> measure
              -> accept / repair / escalate / stop

```

每个循环都要有预算：最大尝试次数、最大时间、最大花费、最大破坏范围、升级条件。**可靠的 agent 知道怎么继续，也知道什么时候继续不再理性。**

## 十一、把指令变成基础设施

当 agent 指令解释"本地现实"时，它很有用；但指令本身是弱强制。**一条规则如果反复重要，就把它往下挪一层。**

| 从             | 到            |
| ------------- | ------------ |
| "记得用格式化工具"    | 自动跑格式化       |
| "不要跨层 import" | 加一条架构测试      |
| "迁移要带回滚"      | CI 里要求回滚文件存在 |
| "不要改生成文件"     | 阻断对生成路径的写入   |
| "每个外部主张都要引用"  | 校验引用覆盖率      |

于是有了一条**指令阶梯**：解释 → 清单 → 模板 → 自动检查 → 强制策略。

能往下挪就往下挪。**提示词负责解释判断，harness 负责强制不变量。**

## 十二、观察过程，不只看结果

一个干净的最终产物可以掩盖一个糟糕的过程：它可能访问了错的数据、忽略了失败的命令、把外部动作重试了两次、花掉十倍预算、或者**用错误的理由得到了正确的答案**。

你需要能把这次运行**重建出来**的 trace：

```text
09:14  contract created
09:15  context source loaded: architecture.md
09:17  file edited: checkout.ts
09:18  focused test failed: duplicate coupon
09:21  implementation repaired
09:22  focused test passed
09:24  integration test passed
09:25  external deployment blocked: approval required

```

一份有用的 trace 要记：状态迁移、上下文来源、工具输入输出、环境变化、验证结果、重试原因、批准决定、成本与延迟。

目的不是监视，是**局部修复**：当一次运行在第 18 步崩掉时，你该能从一个可信的检查点重启，而不是从零重放整个任务。

## 十三、每次运行都要一份变更回执

长转录很难评审。一次运行结束时，harness 应该编译出一份小小的**变更回执**：

```text
OBJECTIVE
Fix duplicate coupon application during checkout.

CHANGED
- checkout validation logic
- focused regression test

VERIFIED
- lint passed
- unit tests passed
- checkout integration test passed

NOT VERIFIED
- production payment provider

DECISIONS
- preserved existing coupon priority order

RISKS
- legacy mobile client was not available locally

APPROVAL NEEDED
- deploy to staging

```

回执不是"模型说了什么"的摘要，而是**系统能证明什么**的摘要。它给人一个紧凑的评审面，也给下一个 agent 会话一个可信的起点。

> 最好的交接不是"这是对话记录"，而是"这是状态、证据，和未解决的风险"。

## 十四、每次失败都该升级 harness

最弱的团队修掉失败的产出；最强的团队**同时修掉让这个失败成为可能的系统**。

失败之后问八个问题：契约含糊吗？上下文不可见吗？暴露了错的工具吗？缺了前置条件吗？结果不可验证吗？策略被留在提示词里吗？恢复范围过宽吗？trace 不够吗？

然后把教训变成可复用的改进：失败 → 诊断 → 新的传感器 / 规则 / 地图 / 测试 / 工具契约 → **未来的运行自动变好**。

这就是 harness 飞轮：**修好一个答案只帮一次，修好 harness 帮每一次。**

## 十五、harness 自己也会腐坏

不是越多越好。模型在变强、工具在变强、任务在变，昨天的护栏可能变成今天的摩擦：为旧模型写的绕行方案，会挡住新模型的好策略。

```text
old model limitation
  -> harness workaround
      -> model improves
          -> workaround remains
              -> system becomes slower or less capable

```

把 harness 组件当生产代码对待：对每个 router、evaluator、记忆层、重试规则都问——它防的是哪种失败？这种失败现在还有多常见？它增加了多少延迟和复杂度？**同样的结果现在能不能更简单地达到？如果删掉会发生什么？**

最好的 harness 不是最大的那个，而是**能可靠闭合"意图到证据"之间差距的最小系统**。

> 构建是为了删除（build to delete）。

## 十六、最小可行 harness：六层

你不需要一个编排平台才开始。分层搭：

| 层           | 内容                                 |
| ----------- | ---------------------------------- |
| **1 有界的任务** | 目标、范围、约束、验收检查                      |
| **2 可读的环境** | 项目地图、命令、局部说明、已知依赖                  |
| **3 受控的动作** | 带类型的工具、参数校验、路径与权限边界、结构化结果          |
| **4 持久的执行** | 显式运行状态、检查点、决定、教训                   |
| **5 证据**    | 确定性检查、对抗式验证、变更回执                   |
| **6 恢复与学习** | 失败分类、有界重试、升级、把反复出现的失败变成 harness 更新 |

**先建能消除你当下真实失败的最小一层。** 不要因为"单个提示词偶尔需要澄清"就上多 agent 架构——**复杂度要靠观察到的失败来赚。**

## 十七、可复用的 harness spec

在给 agent 实质自主权之前，把这八节填完：

```text
AGENT HARNESS SPEC

1. CONTRACT
   objective / scope / constraints / acceptance evidence

2. CONTEXT
   always-loaded map / retrieval sources / local instructions / freshness rules

3. TOOLS
   allowed tools / preconditions / side effects /
   success evidence / timeout and retry policy

4. STATE
   facts / decisions / progress / lessons / checkpoint format

5. POLICY
   automatic actions / approval-required / prohibited / budget limits

6. VERIFICATION
   deterministic checks / adversarial checks / acceptance rule

7. RECOVERY
   failure classes / retry limits / escalation conditions / safe rollback

8. OBSERVABILITY
   trace events / metrics / final change receipt

```

**这些字段没定义，agent 就不是自主的，它是在即兴发挥。**

## 十八、在正确的层级度量

token 数不是终点，尝试过的任务数也不是。有用的单位是**被接受的工作**：

```text
accepted outputs
--------------------------------
human review minutes + run cost

```

另外跟踪：一次通过率、工具失败后的恢复率、重复失败率、每任务人工干预次数、**没有依据的"完成"声明**、从请求到被验证结果的时间、各组件的 harness 开销。

这能防住一个常见错觉：**一个 agent 看起来极其高产，实际上在制造昂贵的评审工作。** 目标不是更多 agent 活动，而是**每单位人类注意力换到更多可信结果**。

## 十九、什么时候不需要重 harness

不是每次模型调用都需要一个操作系统。以下情况用简单提示词就够：任务短、输出容易检查、失败代价低、没有外部副作用、人一直在回路里。

该上 harness 的信号：工作跨多个工具或会话、环境会变、动作有真实后果、完成与否难以人工判断、同一种失败反复出现、**人工评审成了瓶颈**。

harness 的目的不是让 demo 看起来高级，而是**让真实工作可靠**。

## 真正的转变

第一代 AI 产品围绕**提示词**构建；下一代正在围绕**环境**构建。

问题不再只是"怎么让模型答得更好"，而是：**怎么建一个系统，让好动作容易发生、危险动作被控制、失败可见、完成可证明？**

这就是从提示词工程到 harness 工程的转变。**模型提供智能，harness 提供结构，两者合起来才有可靠执行。**

如果 agent 老是散架，**别再往提示词里加形容词了**——去搭它成功所需要的环境。

---

## 我们的整理：这份清单和我们写过的三篇怎么对

| 这份指南的机制                 | 我们站内的对应拆解                                                                                                                            | 差异                                                         |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| "模型提议，策略授权"+风险四档        | [DeepSeek super-agent：把「别打扰人」写成一张准入表](https://www.hubwiz.com/blog/deepseek-superagent-authorization-model/)：显式 / 推断 / 准入表三档 + 不受理的情况 | 本篇给的是**通用原则**；那篇是**已落地的实现**（不可变 Mandate、默认 observe、恢复前重校验） |
| "每次失败升级 harness"、"有界循环" | [循环在节点之内，图在节点之间](https://www.hubwiz.com/blog/loops-inside-nodes-graph-between-them/)：循环负责做对、图决定哪几步存在                                 | 那篇讲**控制流结构**，本篇讲**运行环境**；两者互补，不重叠                          |
| "验证要攻击结果"、"完成需要证据"      | [Agent 安全事故九起与六项控制](https://www.hubwiz.com/blog/agent-security-nine-incidents-six-controls/)：真实事故里的控制项                               | 那篇是**事后取证**，本篇是**事前设计**                                    |

三件最容易今天就做、收益最大、成本最低的事：

1. **写一份任务契约**（第五问"哪些动作要批准"经常被漏）。一份 YAML 就能把"看起来在做事"变成"可验收"。
2. **把一条提示词下沉成检查**。挑一条你重复提醒过的规则（不许跨层 import、必须带迁移回滚），把它变成 CI 里的一条断言。**这一步比再加十句提示词有效。**
3. **加一份变更回执**。哪怕只是一个 Markdown 模板，要求 agent 每次收尾填 `VERIFIED / NOT VERIFIED / DECISIONS / RISKS`。它会同时改善评审体验和下一轮的上下文。

## 边界

- 本文**完整编译**英文长文《Harness Engineering: The Complete Guide to Building AI Agents That Don't Fall Apart》（Lunar / [@LunarResearcher](https://x.com/LunarResearcher?ref=hubwiz.com)，X Article，**2026-09-06**，约 2,900 万浏览）。原文为经验性方法论，**没有基准测试、没有实测数据**；刊出时间距本文约 57 天，属"近 60 天"窗口内。
- 原文的推荐语与引流（Substack、收藏、转发）**未保留**；结构图与代码块按原文顺序保留，转为等价的表格与代码块。
- 这不是"用了这套就不会失败"的保证。文中若干主张（如"同一上下文里自我复查会保住错误假设"）是作者的工程经验判断，**没有给出实验**；我们在正文里按"主张"而非"结论"处理。
- 本文由 Software 2.0 编译整理，转载请注明出处；我们未对其中的方法做本地复测。

**Sources**

- 原文：Lunar《Harness Engineering: The Complete Guide to Building AI Agents That Don't Fall Apart》[https://x.com/LunarResearcher/status/2096570562625655088](https://x.com/LunarResearcher/status/2096570562625655088?ref=hubwiz.com)（X Article 正文：[https://x.com/i/article/2096536117130481673](https://x.com/i/article/2096536117130481673?ref=hubwiz.com)），2026-09-06
- 作者主页：[https://x.com/LunarResearcher](https://x.com/LunarResearcher?ref=hubwiz.com)

**同主题阅读**

- [DeepSeek super-agent：把「别打扰人」写成一张准入表](https://www.hubwiz.com/blog/deepseek-superagent-authorization-model/)
- [循环在节点之内，图在节点之间](https://www.hubwiz.com/blog/loops-inside-nodes-graph-between-them/)
- [Agent 安全事故九起与六项控制](https://www.hubwiz.com/blog/agent-security-nine-incidents-six-controls/)

> **这是「Agent / MCP」专题的一部分。**完整地图见：[Agent / MCP / 自动化完全指南](https://www.hubwiz.com/blog/agent-stack/)