CrabNote螃蟹笔记

基于Claude 的Agent Harness工程:从单一智能体到自迭代系统的 14 步路线图

基于Claude 的Agent Harness工程:从单一智能体到自迭代系统的 14 步路线图

基于Claude 的Agent Harness工程:从单一智能体到自迭代系统的 14 步路线图 基于Claude 的Agent Harness工程:从单一智能体到自迭代系统的 14 步路线图 Modified June 17 Code block Python Copy "command": "prettier write \"$CLAUDE FILE PATH\"" }] } 把钩子用于那些必须发生或绝不能发生的事:安全、格式化、审计日志。 不要把钩子用于需要判断的事,那是模型该做的工作。好的harness是一两个锋利的钩子,而不是二十个没人理解的钩子。 第 3 部分:让它形成复利 10. 加入循环:现在Harness会按定时器运行 配置好的harness仍然在等你输入。循环让它自己跑起来。最简单的版本是 Claude Code 里的 /loop,也就是按固定节奏重复触发的提示词。 循环按定时器运行 把它和 /goal 搭配起来,循环就会一直运行,直到一个客观条件成立。这个条件由独立评分器检查,而不是让智能体给自己打分。 代码块 Python Copy /loop 30m /goal All tests pass and lint is clean. Triage new failures, draft fixes in claude/ branches. ▲ Claude 会使用你搭好的Harness: rules/ 承载项目约定 reviewer 子智能体检查每个修复 PreToolUse 钩子阻止推送到 main ✓ 循环中。由独立评分器判断“完成”。 注意刚刚发生了什么:循环并没有增加智能。它复用了harness里的一切,包括规则、审查子智能体和安全钩子。好的harness会让循环变得很简单。这就是先打基础的全部意义。 11. 加入动态工作流:Harness会写自己的编排 有些任务对单个循环来说太复杂,比如大规模并行、高度结构化、对抗式任务。Claude 可以即时写出自己的 JavaScript Harness。 这就是动态工作流:用 agent() 拉起智能体,用 parallel() 扇出并行,用 pipeline() 做流式处理。它会把harness里定义的子智能体组合成各种模式,比如扇出并综合,或者对抗式验证。 动态工作流编排 它和harness工程的关系是:动态工作流的上限,取决于它能调用的子智能体和 Skill 的质量。 如果你的harness里有一个敏锐的审查子智能体,以及写得很好的评测 Skill,工作流就有好零件可以编排。如果harness是空的,工作流就无从下手。 工作流是指挥,harness是乐队。 12. 加入记忆:智能体会忘,但Harness可以记住 这一步会把配置好的harness变成真正会改进的系统。智能体会在每次运行之间忘掉一切。Harness不必这样。 一个状态文件,也就是 agent memory/ 里的 Markdown 文件,或者一块 Linear 看板,可以记录试过什么、什么有效、什么失败,以及哪些规则经受住了检验。 记忆让Harness持续改进 最强智能体使用记忆的方式里,有一个能让记忆产生复利的模式: • 离开前先写。 每次运行结束时更新状态文件:学到的经验、已验证事实、下一步是什么。 • 开始时先读。 每次运行开始时读取状态文件和相关 Skill,这样它是在继续,而不是重开。 • 沉淀到 Skill。 当一条经验具有通用性,比如“Windows runner 需要 bash,不要用 PowerShell”,它就从状态文件升级到 Skill,适用于之后的每个项目。 Code block Python Copy 项目记忆 已验证事实 不要再猜这些 prc 的单位是美元,不是美分(已通过 SELECT MIN/MAX 检查) auth 中间件顺序:rate limit jwt rbac 经验教训 通用经验要沉淀到 Skill Windows CI runner 在 PowerShell 里会因为 TLS 1.2 失败,要用 bash 超过 100 万行的表做迁移时,必须按 1 万行一批处理 上次会话 继续推进,不要重开 2026 06 11 · 3 个修复已合并,2 个问题已升级处理。下一步:验证限流修复。 13. 闭合循环:输出 → 经验 → Skill → 更好的输出 这里,三层终于扣在一起,变成一个会改进的东西。每次运行都会产生输出。审查子智能体(第 7 步)检查它。 结果,也就是哪些通过、哪些失败、学到了什么,会写入记忆(第 12 步)。通用经验会沉淀进 Skill(第 8 步)。 下一次运行会继承更好的 Skill 和更丰富的记忆。 这就是完整的自我改进循环,而且注意,它完全由Harness里的部件组成: • 子智能体给工作打分:客观检查,全新上下文。 • 记忆记录结论:跨运行保留。 • Skill带着上一次学到的一切再次执行。 • 循环带着上一次学到的一切再次运行。 模型本身没有变。变锋利的是它周围的harness。这才是“自我改进”的真正含义:不是模型在学习,而是harness在积累。 14. 交付Harness:打包、分享、复用 一个在某个项目里有效的harness,就是资产。 把 Skill、子智能体和规则打包成插件,整个团队就能一步安装同一套配置:同样的约定,同样的安全钩子,同样的审查者。 打包共享Harness Harness不再只是你的个人配置,而会变成共享基础设施。 最后再说一次构建顺序,因为顺序本身就是关键经验:先在干净的harness上,让一次手动运行变得可靠。 加入上下文和权限。加入审查子智能体。加入记忆。然后,也只有到那时,再把它包进循环。 好的harness上的循环会产生复利。坏harness上的循环只会更快失血。 § 让每个循环都变差的Harness错误 • 直接跑默认配置。 没有上下文,没有规则,没有记忆,智能体每个会话都重新推导项目。 • 臃肿的 CLAUDE.md。 把流程塞进常驻上下文,让每次运行都变重。把它们移到 Skill。 • 把强制约束写进 CLAUDE.md,而不是钩子。 模型可以忽略建议,但无法忽略退出码为 2 的钩子。 • 让同一个智能体既写又给自己打分。 加一个带全新上下文窗口的审查子智能体。 • 没有记忆。 每次运行都从零开始。状态文件才会让明天接着今天走。 • 把循环套在糟糕的Harness上。 循环只会更快地产出粗糙内容。先打好基础。 • 二十个钩子。 一两个锋利钩子,胜过一堆没人理解的钩子。 • 交付Harness前不扫描。 泄露的密钥和过宽的权限,会扩散给每个安装它的人。 结尾: 循环拿走了光环。干活的是Harness。 循环工程是令人兴奋的部分:智能体自己提示自己,在你睡觉时继续运行。但循环只是一个套上定时器的Harness。 决定输出是好是坏的一切,都在它下面那一层:你选择的模型、你允许的工具、你写下的上下文、你添加的审查者、你保留下来的记忆。 把这一层搭好,上面的所有东西都会复利增长:循环会复用你的子智能体,工作流会编排你的 Skill,记忆会让每次运行都比上一次更锋利。 自我改进从来不是模型自身的属性。它是你围绕模型搭建的Harness的属性。 挑一件你还没做的事,也许是审查子智能体、安全钩子,或者状态文件,今天就加上。把Harness控制在你能解释清楚的大小。然后在上面放一个循环,看基础层真正开始工作。 把钩子用于那些必须发生或绝不能发生的事:安全、格式化、审计日志。 不要把钩子用于需要判断的事,那是模型该做的工作。好的harness是一两个锋利的钩子,而不是二十个没人理解的钩子。 第 3 部分:让它形成复利 10. 加入循环:现在Harness会按定时器运行 配置好的harness仍然在等你输入。循环让它自己跑起来。最简单的版本是 Claude Code 里的 /loop,也就是按固定节奏重复触发的提示词。 把它和 /goal 搭配起来,循环就会一直运行,直到一个客观条件成立。这个条件由独立评分器检查,而不是让智能体给自己打分。 注意刚刚发生了什么:循环并没有增加智能。它复用了harness里的一切,包括规则、审查子智能体和安全钩子。好的harness会让循环变得很简单。这就是先打基础的全部意义。 11. 加入动态工作流:Harness会写自己的编排 有些任务对单个循环来说太复杂,比如大规模并行、高度结构化、对抗式任务。Claude 可以即时写出自己的 JavaScript Harness。 这就是动态工作流:用 agent() 拉起智能体,用 parallel() 扇出并行,用 pipeline() 做流式处理。它会把harness里定义的子智能体组合成各种模式,比如扇出并综合,或者对抗式验证。 它和harness工程的关系是:动态工作流的上限,取决于它能调用的子智能体和 Skill 的质量。 如果你的harness里有一个敏锐的审查子智能体,以及写得很好的评测 Skill,工作流就有好零件可以编排。如果harness是空的,工作流就无从下手。 工作流是指挥,harness是乐队。 12. 加入记忆:智能体会忘,但Harness可以记住 这一步会把配置好的harness变成真正会改进的系统。智能体会在每次运行之间忘掉一切。Harness不必这样。 一个状态文件,也就是 agent memory/ 里的 Markdown 文件,或者一块 Linear 看板,可以记录试过什么、什么有效、什么失败,以及哪些规则经受住了检验。 最强智能体使用记忆的方式里,有一个能让记忆产生复利的模式: • 离开前先写。 每次运行结束时更新状态文件:学到的经验、已验证事实、下一步是什么。 • 开始时先读。 每次运行开始时读取状态文件和相关 Skill,这样它是在继续,而不是重开。 • 沉淀到 Skill。 当一条经验具有通用性,比如“Windows runner 需要 bash,不要用 PowerShell”,它就从状态文件升级到 Skill,适用于之后的每个项目。 13. 闭合循环:输出 → 经验 → Skill → 更好的输出 这里,三层终于扣在一起,变成一个会改进的东西。每次运行都会产生输出。审查子智能体(第 7 步)检查它。 结果,也就是哪些通过、哪些失败、学到了什么,会写入记忆(第 12 步)。通用经验会沉淀进 Skill(第 8 步)。 下一次运行会继承更好的 Skill 和更丰富的记忆。 这就是完整的自我改进循环,而且注意,它完全由Harness里的部件组成: • 子智能体给工作打分:客观检查,全新上下文。 • 记忆记录结论:跨运行保留。 • Skill带着上一次学到的一切再次执行。 • 循环带着上一次学到的一切再次运行。 模型本身没有变。变锋利的是它周围的harness。这才是“自我改进”的真正含义:不是模型在学习,而是harness在积累。 14. 交付Harness:打包、分享、复用 一个在某个项目里有效的harness,就是资产。 把 Skill、子智能体和规则打包成插件,整个团队就能一步安装同一套配置:同样的约定,同样的安全钩子,同样的审查者。 Harness不再只是你的个人配置,而会变成共享基础设施。 最后再说一次构建顺序,因为顺序本身就是关键经验:先在干净的harness上,让一次手动运行变得可靠。 加入上下文和权限。加入审查子智能体。加入记忆。然后,也只有到那时,再把它包进循环。 好的harness上的循环会产生复利。坏harness上的循环只会更快失血。 § 让每个循环都变差的Harness错误 • 直接跑默认配置。 没有上下文,没有规则,没有记忆,智能体每个会话都重新推导项目。 • 臃肿的 CLAUDE.md。 把流程塞进常驻上下文,让每次运行都变重。把它们移到 Skill。 • 把强制约束写进 CLAUDE.md,而不是钩子。 模型可以忽略建议,但无法忽略退出码为 2 的钩子。 • 让同一个智能体既写又给自己打分。 加一个带全新上下文窗口的审查子智能体。 • 没有记忆。 每次运行都从零开始。状态文件才会让明天接着今天走。 • 把循环套在糟糕的Harness上。 循环只会更快地产出粗糙内容。先打好基础。 • 二十个钩子。 一两个锋利钩子,胜过一堆没人理解的钩子。 • 交付Harness前不扫描。 泄露的密钥和过宽的权限,会扩散给每个安装它的人。 结尾: 循环拿走了光环。干活的是Harness。 循环工程是令人兴奋的部分:智能体自己提示自己,在你睡觉时继续运行。但循环只是一个套上定时器的Harness。 决定输出是好是坏的一切,都在它下面那一层:你选择的模型、你允许的工具、你写下的上下文、你添加的审查者、你保留下来的记忆。 把这一层搭好,上面的所有东西都会复利增长:循环会复用你的子智能体,工作流会编排你的 Skill,记忆会让每次运行都比上一次更锋利。 自我改进从来不是模型自身的属性。它是你围绕模型搭建的Harness的属性。 挑一件你还没做的事,也许是审查子智能体、安全钩子,或者状态文件,今天就加上。把Harness控制在你能解释清楚的大小。然后在上面放一个循环,看基础层真正开始工作。 原帖链接:https://x.com/0xCodez/status/2066867539305459732 原帖链接:https://x.com/0xCodez/status/2066867539305459732 大家都在聊循环。几乎没人认真讨论循环到底跑在什么之上。10 个开发者里有 9 个直接用 Claude Code 的默认harness:没有规则,没有子智能体,没有钩子,也没有记忆。 然后他们会困惑,为什么自己的循环产出一堆粗糙的内容。真相很简单:循环的质量,取决于它底下的harness质量。这是一条 14 步路线图,讲的是如何搭好这层harness,从一个智能体,走到一个能自我改进的系统。 关注我的 Substack,获取最新 AI 前沿信息:movez.substack.com movez.substack.com 循环工程,也就是构建一个能按计划触发提示词的智能体系统。写过那篇循环长文的 Addy Osmani,很明确地指出了它下面那一层: “循环工程位于harness的上一层。Harness是单个智能体运行的环境。循环也是harness,但它按计时器执行、生成辅助智能体并实现自我数据供给。” Harness工程,就是设计这个环境:模型、工具、权限、上下文和记忆。 它不是最光鲜的那一层,却是决定上层一切能否正常工作的那一层。在糟糕的harness上放一个很强的循环,只会更快地规模化产出垃圾。 14 步。3 个层级。所有上层能力都站在这层基础之上。 第 1 部分:什么是harness 01. Harness就是单个智能体运行其中的环境 去掉术语,一个harness其实只有四件事:负责思考的模型,它能够调用的工具,这些工具上的权限,以及每次运行开始时会读取的上下文。 这就是整个表面。其他东西,比如子智能体、钩子、记忆,本质上都是在塑造这四件事里的某一项。 Harness之所以比很多人想得更重要,是因为智能体本质上就是一个 while True 循环:选择工具,运行工具,查看结果,再决定下一步。 Harness定义了有哪些工具、智能体被允许做什么,以及它启动时知道什么。 同一个模型,换一个harness,就会变成完全不同的智能体。 02. 整个Harness都在一个文件夹里:.claude/ 所有塑造智能体行为的东西,都放在项目根目录下的一个目录里。学会这个结构,你就能一眼看懂任何人的harness: 区分干净harness和混乱配置的一条规则是:让它小到你能解释每个文件为什么存在。 如果你说不清某条规则、某个钩子或某个子智能体是干什么的,就删掉它。 03. Harness、循环和系统:这是三个层面,不要混淆 大多数“我的智能体配置一团乱”的问题,都来自把这三层混在了一起。把它们分清楚: • Harness是一个智能体所处的运行环境。它是静态配置:模型、工具、权限、上下文。本文讲的就是这一层。 • 循环会按定时器提示智能体,拉起帮手,把结果反馈给自己。它运行在harness之上。 • 自我改进系统是循环加记忆形成的复利结构,每次运行都会让下一次运行更敏锐。 落到实践里就是:把既定事实放进上下文,把强制约束放进钩子,把流程放进 Skill,把隔离交给子智能体。 把这些放错位置,比如把强制约束写进 CLAUDE.md,或者让流程把上下文撑爆,就是智能体不稳定、成本高的根源。 04. 默认Harness:开箱即得的东西 安装 Claude Code,打开一个文件夹,你就已经有了harness,只不过它是空的。默认配置给你一个有能力的模型、内置工具(读取、写入、执行、搜索),以及对所有高风险操作的审批提示。没有项目上下文,没有自定义子智能体,也没有记忆。 如果只是一次性任务,默认配置够用。但只要是会重复做的事,默认harness就会让智能体每次会话都从头推导项目结构,对安全操作也不断请求许可,并且在你关闭终端后忘掉所有东西。 接下来的十步,就是为了补上这个缺口。 05. CLAUDE.md:既定事实,言简意赅 CLAUDE.md 会在每个会话开始时读取。它是智能体对项目的常驻认知:约定、架构,以及“我们不这么做,是因为以前出过那次事故”这种背景。 最常见的错误,让它发展成一份庞大的程序文档,使每个会话的上下文都变得冗长。 每天使用这套方法的实践者给出的规则是:主记忆文件控制在约 500 个 token 以内。 这里放既定事实。 多步骤流程放进 Skill(第 8 步)。只适用于特定路径的行为,放进按路径限定的 rules/ 文件。如果 CLAUDE.md 的某一节已经从事实变成流程,它就该搬到别处。 大声朗读你的CLAUDE.md。每一行都应该是智能体在每个会话里都需要知道的事实,比如“我们用 pnpm,不用 npm”。如果某一行是流程,比如“要添加功能,先……”,就移到 Skill。 如果它是某个文件夹专属的规则,就移到 rules/。 06. settings.json:权限和模型,一次设好 默认harness会在每个高风险操作前询问。这在你盯着它运行时是对的,在无人值守时就不合适了。settings.json 是你预先批准安全操作、拒绝危险操作、并选择运行模型的地方。 判断什么可以自动批准的标准是:如果这里出错,撤销起来有多难? 撤销成本低,就自动批准。 撤销成本高,比如(强制推送、删除文件、触及机密)→ 始终拒绝或提示。如果有日志记录,中间地带可以自动批准。 07. 子智能体:把脏活隔离到独立上下文里 子智能体是由主会话启动的独立 Claude 会话,有自己的上下文窗口,也有自己的工具列表。它的重点不是为了并行而并行,而是把噪音挡在主上下文之外。 一项需要读取 40 个文件的调研任务,一次需要全新视角的审查,一次会产生大量日志的评估运行,都应该交给子智能体,避免污染主线程。 任何harness里最有价值的子智能体,都是那个检查主智能体工作结果的子智能体。让模型审查自己的输出,往往会太宽容; 一个带着全新上下文窗口的独立审查者,能抓到作者自己已经说服自己的问题。这种“写作者 vs 检查者”的分工,才会让harness之上的每个循环变得可信。 08. Skill:智能体可以复用的流程 Skill 是智能体会执行的 SKILL.md 文件,可以由你用 /skill name 显式调用,也可以在任务匹配它的描述时自动触发。 和子智能体不同,Skill 运行在同一个上下文窗口里。它只是可复用的指令,会成为当前会话的一部分。 什么时候该创建 Skill?当你发现自己每次开新对话都在粘贴同一段指令时。 那就是一个等待被做成 Skill 的流程。PR 检查清单、评测流程、发布流程,都可以写一次,然后永久调用。 而且因为 Skill 是可复用单元,它也让harness能够随时间改进:每次流程以新的方式失败,你就把经验加进 Skill,下一次运行就会继承它。 09. 钩子:模型无法凭空捏造的确定性规则 到目前为止,所有东西都依赖模型理解你的指令。钩子不是。 钩子是在智能体生命周期固定节点触发的 shell 命令,比如工具运行前、文件变更后、会话结束时。它的退出码可以阻止操作。钩子是强制执行,CLAUDE.md 只是建议。 几乎每个harness里,都值得放两个钩子: • PreToolUse 闸门,用确定性方式阻止危险命令,比如 rm rf、读取 .env、推送到 main。退出码 2 会在调用发生前拦下它。模型没法靠话术绕过去。 • PostToolUse 格式化,在每次编辑后运行你的代码检查器或格式化器。智能体不会交付未格式化的代码,因为harness会自动格式化。