每个人都在讨论循环。几乎没人讨论循环运行在什么之上。10 个开发者中有 9 个在默认的 harness 上运行 Claude Code——没有规则、没有子 Agent、没有钩子、没有记忆。
然后他们奇怪为什么循环产生垃圾。事实很简单:循环的好坏取决于它底层的 harness。这是一份 14 步的 harness 路线图——从一个 Agent 到一个自我改进的系统。
关注我的 Substack 获取最新 AI 动态:
循环工程——构建一个按计划提示 Agent 的系统——本月吸引了所有关注。但撰写了关于循环的长篇文章的 Addy Osmani 谨慎地指出了它下面的东西:
“循环工程位于 harness 之上的一层。Harness 是单个 Agent 运行的环境。循环是 harness,但它按定时器运行,生成助手,并自我反馈。”
Harness 工程就是设计那个环境:模型、工具、权限、上下文、记忆。
这是一个不光彩的层——但它决定了上面的一切是否有效。一个在糟糕 harness 上的优秀循环是快速大规模产生垃圾的方法。

14 步。3 层。其他一切的基础。
第一部分 · Harness 是什么
01. Harness 是单个 Agent 运行的环境。
去掉行话,harness 是四样东西:模型(负责思考)、工具(它能触及的)、权限(这些工具的权限)、以及上下文(每次运行开始时读取的)。
这就是全部表面。其他一切——子 Agent、钩子、记忆——都是塑造这四个要素的方式。

Harness 比人们想象的更重要:Agent 是一个 while True 循环,选择一个工具,运行它,查看结果,然后决定下一步。
Harness 定义了存在哪些工具、Agent 被允许做什么以及它在启动时知道什么。 相同的模型,不同的 harness,完全不同的 Agent。
02. 整个 harness 存在于一个文件夹中:.claude/
所有塑造你的 Agent 的东西都位于项目根目录的一个单一目录中。学会这个布局,你就能一目了然地读懂任何人的 harness:
1.claude/2├─ CLAUDE.md # 固定事实——每次会话读取3├─ settings.json # 权限、模型、钩子4├─ .mcp.json # 外部工具连接5├─ rules/ # 路径范围行为6│ ├─ tests.md7│ └─ python-types.md8├─ agents/ # 子 Agent 定义(每条约 30 行)9│ ├─ reviewer.md10│ └─ eval-runner.md11├─ skills/ # 可重用工作流12│ └─ pr-checklist/13│ └─ SKILL.md14└─ agent-memory/ # 运行间存活的数据15 └─ STATE.md
区分干净 harness 和混乱一条规则:保持足够小,以至于你能解释每个文件存在的原因。 如果你说不出一个规则、钩子或子 Agent 是做什么的,就删除它。
03. Harness 与循环与系统。三层,不要混淆。
大多数“我的 Agent 设置一团糟”的问题都源于混淆了这三层。把它们分清楚:
- Harness 是一个 Agent 所在的运行时。静态配置:模型、工具、权限、上下文。本期内容。
- 循环 按定时器提示 Agent,生成助手,自我反馈。它运行在 harness 之上。
- 自我改进系统 是循环加上复合记忆——每次运行让下一次更高效。
实际版本:将固定事实放在上下文中,将强制规则放在钩子中,将流程放在技能中,将隔离放在子 Agent 中。
混淆这些——将强制规则放在 CLAUDE.md 中,将流程膨胀到上下文中——是不一致且昂贵 Agent 的根本原因。
04. 默认 harness。开箱即得。
安装 Claude Code,打开一个文件夹,你就有了一个 harness——只是空的。默认提供的是一个能干的模型、内置工具(读、写、bash、搜索),以及对所有危险操作的批准提示。没有项目上下文,没有自定义子 Agent,没有记忆。

对于一次性任务,默认就够用了。对于任何你做不止一次的事情,默认会让 Agent 每次会话都从头重新推导你的项目,请求安全操作的权限,并在关闭终端时忘记一切。
接下来的十步就是关于缩小这个差距的。
05. CLAUDE.md:固定事实,保持简短。
CLAUDE.md 在每次会话开始时被读取。它是 Agent 关于你项目的固定知识——约定、架构、“我们不这样做是因为那次事故”。

一个最常见的错误:让它变成一份庞杂的流程文档,膨胀每次会话。
日常实践者的规则:将主记忆文件保持在约 500 token 以下。 固定事实放在这里。
多步流程放在技能中(第 8 步)。路径特定行为放在作用域对应的 rules/ 文件中。如果 CLAUDE.md 的某个部分变成了流程而不是事实,它就应该放在别处。
大声朗读你的 CLAUDE.md。每一行都应该是
事实
Agent 在每个会话中都需要(“我们使用 pnpm,而不是 npm”)。如果一行是
流程
(“要添加功能,首先…”),将它移到技能中。
如果是针对一个文件夹的规则,将其移到 rules/。
06. settings.json:权限和模型,一次性设置。
默认 harness 会在每个危险操作前询问。当你盯着屏幕时这是对的,当你不在时就是错的。settings.json 是你预先批准安全操作、拒绝危险操作并选择哪个模型运行的地方。
1{2 "model": "claude-sonnet-4-6",3 "permissions": {4 "autoApprove": [5 "Read(*)", "Grep(*)",6 "Bash(npm test)", "Bash(git status)"7 ],8 "deny": [9 "Bash(rm -rf*)", "Bash(git push*)",10 "Edit(.env*)", "Edit(secrets/*)"11 ]12 }13}
判断哪些要自动批准的测试:如果出错了,撤销有多难? 容易撤销 → 自动批准。
难以撤销(force-push、删除文件、触及机密)→ 始终拒绝或提示。中间地带可以自动批准,前提是你记录它。
07. 子 Agent:为脏活提供的独立上下文。
子 Agent 是从主会话启动的独立 Claude 会话——拥有自己的上下文窗口、自己的工具列表。重点不是为并行而并行,而是将噪音排除在主上下文之外。
GIF
一个读取 40 个文件的研究任务、一个需要全新视角的审查过程、一个产生大量日志的评估运行——这些都属于子 Agent,这样它们就不会污染主线程。
任何 harness 中最有价值的子 Agent 是检查主 Agent 所做工作的那个。模型审查自己的输出对自己太宽容;
一个具有全新上下文窗口的独立审查者能抓住写作者自己说服自己的错误。这就是写作者与审查者的分离,使得 harness 之上的每个循环都值得信赖。
08. 技能:Agent 重用的流程。
技能是一个 SKILL.md 文件,Agent 运行它——无论是当你用 /skill-name 调用它,还是当任务匹配其描述时自动运行。

与子 Agent 不同,它运行在相同的上下文窗口中。它只是可重用的指令,成为会话的一部分。
创建技能的条件:你发现自己将相同的指令粘贴到每个新对话中。 那就是一个即将诞生的技能。PR 检查清单、评估流程、发布过程——编写一次,永久调用。
而且因为技能是可重用单元,它们使 harness 随着时间的推移不断改进:每次流程以新的方式失败时,你将教训添加到技能中,下一次运行就会继承它。
09. 钩子:模型无法产生幻觉的确定性规则。
到目前为止,一切都依赖于模型理解你的指令。钩子不需要理解。
钩子是一个 shell 命令,在 Agent 生命周期的固定点触发——在工具运行前、文件更改后、会话结束时——其退出代码可以阻止操作。钩子是强制性的,CLAUDE.md 是建议性的。

两个钩子在几乎每个 harness 中都占有一席之地:
- 一个 PreToolUse 门,确定性地阻止危险命令——rm -rf、读取 .env、推送到 main。退出代码 2 在调用发生前就停止了它。模型无法说服它绕过。
- 一个 PostToolUse 格式化器,在每次编辑后运行你的 linter 或格式化器。Agent 永远不会输出未格式化的代码,因为 harness 会自动格式化。
1"hooks": {2 "PreToolUse": [{3 "matcher": "Bash",4 "command": "./.claude/hooks/block-dangerous.sh"5 // exit 2 = 在运行前阻止调用6 }],7 "PostToolUse": [{8 "matcher": "Edit|Write",9 "command": "prettier --write \"$CLAUDE_FILE_PATH\""10 }]11}
将钩子用于任何必须发生或绝不能发生的事情——安全性、格式化、审计日志。
不要将它们用于判断决策;那是模型的任务。一个好的 harness 有一两个锋利的钩子,而不是二十个。
第三部分 · 让它复合
10. 添加循环。现在 harness 按定时器运行。
配置好的 harness 仍然等待你输入。循环让它自行运行。最简单的版本是 Claude Code 中的 /loop——一个按节奏重复的提示。

将它与 /goal 结合使用,循环就会持续进行,直到一个客观条件成立,由独立的评分者检查,而不是由 Agent 自行评分。
1> /loop 30m /goal 所有测试通过且 lint 干净。2 分类新失败,在 claude/ 分支中起草修复。34▲ Claude 使用你构建的 harness:5 - rules/ 用于约定6 - 审查子 Agent 来检查每个修复7 - PreToolUse 钩子阻止推送到 main8✓ 循环中。独立评分者决定“完成”。
注意刚刚发生了什么:循环没有增加智能。它重复使用了 harness 中的所有东西——规则、审查子 Agent、安全钩子。一个好的 harness 使循环变得微不足道。这就是先打好基础的全部意义。
11. 添加动态工作流。Harness 编写自己的编排。
对于单个循环过于复杂的任务——大规模并行、高度结构化、对抗性——Claude 可以即时编写自己的 JavaScript harness。
这就是动态工作流:agent() 来生成,parallel() 来扇出,pipeline() 来流式传输。它将你的 harness 定义的子 Agent 组合成模式,如扇出再合成或对抗性验证。

与 harness 工程的联系:动态工作流的好坏取决于它能调用的子 Agent 和技能。
如果你的 harness 有一个敏锐的审查子 Agent 和一个编写良好的评估技能,工作流就有好的组件来编排。如果 harness 是空的,工作流就无事可做。
工作流是指挥,你的 harness 是乐团。
12. 添加记忆。Agent 忘记的,Harness 记住。
这是将配置好的 harness 转变为实际改进的系统的步骤。Agent 会忘记运行之间的一切。Harness 不必忘记。
一个状态文件——agent-memory/ 中的 markdown 文件,或一个 Linear 项目——记录尝试过什么、什么有效、什么失败、哪些规则幸存。

使记忆复合的模式,来自最强 Agent 的使用方式:
- 离开前写入。每次运行结束时更新状态文件——学到的教训、已验证的事实、下一步做什么。
- 开始时读取。每次运行开始时读取状态文件和相关技能,因此它恢复而不是重新开始。
- 提炼成技能。当一个教训具有通用性(“Windows 运行器需要 bash,而不是 PowerShell”)时,它从状态文件升级到技能中,适用于每个未来项目。
1# 项目记忆23## 已验证的事实 # 别再猜测这些4- prc 是美元而非美分(通过 SELECT MIN/MAX 检查)5- auth 中间件顺序:rate_limit -> jwt -> rbac67## 学到的教训 # 将通用教训提炼成技能8- Windows CI 运行器在 PowerShell 中 TLS 1.2 失败——使用 bash9- 超过 1M 行的表迁移必须按 10k 批次进行1011## 上次会话 # 恢复,不要重新开始122026-06-11 · 3 个修复已合并,2 个已升级。下一步:验证速率限制修复。
13. 闭环。输出 → 教训 → 技能 → 更好输出。
这就是三层锁在一起形成一个自我改进系统的地方。每次运行产生输出。审查子 Agent(第 7 步)检查它。
结果——哪些通过了、哪些失败了、学到了什么——被写入记忆(第 12 步)。通用教训被提炼成技能(第 8 步)。
下一次运行继承了更锋利的技能和更丰富的记忆。
这就是整个自我改进循环,注意它完全由 harness 部件构建:
- 子 Agent 对工作进行评分——客观检查,全新上下文。
- 记忆 记录判定——在运行之间存活。
- 技能 再次运行它——现在包含上次运行学到的所有东西。
- 循环 再次运行它——现在包含上次运行学到的所有东西。
模型从未改变。它周围的 harness 变得更锋利。这就是“自我改进”的真实含义——不是模型在学习,而是harness 在积累。
14. 交付 harness。打包它。分享它。重复使用它。
在一个项目上有效的 harness 是一项资产。
将技能、子 Agent 和规则打包成一个插件,你的整个团队就能一步安装相同的设置——相同的约定、相同的安全钩子、相同的审查者。

Harness 不再是你个人的设置,而成为共享基础设施。
构建的顺序,最后一次强调,因为顺序就是教训:先让一次手动运行在一个干净的 harness 上可靠。
添加上下文和权限。添加一个审查子 Agent。添加记忆。然后,也只有到那时,把它包装在循环中。 一个在好 harness 上的循环会复合。一个在坏 harness 上的循环只会更快地流血。
§ 让每个循环更糟的 Harness 错误
- 使用默认设置。没有上下文、没有规则、没有记忆——Agent 每次会话都重新推导项目。
- 膨胀的 CLAUDE.md。流程塞进固定上下文,每次运行都膨胀。将它们移到技能中。
- 在 CLAUDE.md 中强制规则而不是用钩子。模型可以忽略建议。但它无法忽略一个退出码为 2 的钩子。
- 同一个 Agent 编写并评分自己的工作。添加一个带有全新上下文窗口的审查子 Agent。
- 没有记忆。每次运行都从零开始。状态文件让明天可以继续。
- 将循环包裹在糟糕的 harness 上。循环只是更快地产生垃圾。先打好基础。
- 二十个钩子。一两个锋利的钩子胜过一堆没人理解的钩子。
- 未经扫描就交付 harness。泄露的机密和过宽的权限会传播给每个安装它的人。
结论:
循环获得荣耀。Harness 做实际工作。
循环工程是令人兴奋的部分——Agent 自我提示,在你睡觉时运行。但循环只是一个带有定时器的 harness。
决定输出是好的还是垃圾的一切都住在下一层,在你选择的模型中、允许的工具中、编写的上下文中、添加的审查者中、保持的记忆中。
把那层建好,它上面的所有东西都会复合:循环重用你的子 Agent,工作流编排你的技能,记忆让每次运行都比上一次更高效。
自我改进从来不是模型的属性。它是你围绕模型构建的 harness 的属性。
选择一件你还没在做的事情——可能是一个审查子 Agent、一个安全钩子或一个状态文件——今天就添加它。保持 harness 足够小以便解释。然后在上面放一个循环,然后看着基础做工作。






