框架工程:14步从单Agent到自改进系统

0xcodez 发布于 2026-06-17 阅读 115

本文强调在构建AI代理循环(loop)时,底层的运行环境(harness)更为关键。作者提出14步路线图,从基础的单代理配置到自改进系统,详细介绍了CLAUDE.md、settings.json、子代理、技能、Hook、记忆等组件的设计与优化,指出一个糟糕的harness上运行再好的循环也会产生垃圾。

图像

每个人都在谈论循环(Loop)。几乎没人谈论循环运行在什么之上。10 个开发者中有 9 个在默认框架(Harness)上运行 Claude Code——没有规则,没有子 Agent,没有 Hook,没有记忆。

然后他们奇怪为什么自己的循环产出垃圾。事实很简单:一个循环的好坏完全取决于其底层的框架。下面是从单一 Agent 到一个自我改进系统的 14 步框架路线图。

这个月,循环工程(Loop Engineering)——构建一个按计划提示 Agent 的系统——吸引了所有关注。但撰写长篇循环文章的 Addy Osmani 谨慎地指出了更底层的内容:

“循环工程位于框架之上。框架是单一 Agent 运行的环境。循环就是框架,但它带有定时器,能够生成辅助工具并自我供给。”

框架工程就是设计这个环境:模型、工具、权限、上下文、记忆。

这是不那么光鲜的一层——但正是它决定了上层的一切能否正常工作。糟糕框架上的优秀循环,是快速批量制造垃圾的方法。

图像

14 步。3 个层级。其他一切以此为基础。

第一部分:什么是框架

01. 框架是单一 Agent 运行的环境。

去掉术语,框架由四部分组成:进行思考的模型、它能访问的工具、这些工具上的权限,以及每次运行时读取的上下文。

这就是全部表面。其他所有东西——子 Agent、Hook、记忆——都是对这四部分的塑造方式。

图像

框架比人们想象的更重要,原因在于:Agent 是一个 while True 循环,它选择一个工具,运行它,查看结果,然后决定下一步。

框架定义了存在哪些工具、Agent 被允许做什么,以及它在启动时知道什么。相同的模型,不同的框架,完全不同的 Agent。

02. 整个框架位于一个文件夹内:.claude/

所有塑造 Agent 的内容都位于项目根目录下的单个目录中。掌握这个布局后,你可以一眼看懂任何人的框架:

.claude/
├─ CLAUDE.md          # 固定事实——每个会话都会读取
├─ settings.json      # 权限、模型、Hook
├─ .mcp.json          # 外部工具连接
├─ rules/             # 路径作用域下的行为
│  ├─ tests.md
│  └─ python-types.md
├─ agents/            # 子Agent定义(约30行每个)
│  ├─ reviewer.md
│  └─ eval-runner.md
├─ skills/            # 可复用工作流
│  └─ pr-checklist/
│     └─ SKILL.md
└─ agent-memory/      # 运行之间持久化的内容
   └─ STATE.md

区分整洁框架与混乱框架的一条规则:保持足够小,使你能解释每个文件存在的原因。如果你说不出某个规则、Hook 或子 Agent 的作用,就删除它。

03. 框架 vs 循环 vs 系统。三个层面,不要混淆。

大多数“我的 Agent 设置一团糟”的问题都来自混淆这三个层面。理清它们:

  • 框架:一个 Agent 运行的运行时。静态配置:模型、工具、权限、上下文。即本文内容。
  • 循环:按定时器提示 Agent,生成辅助工具,自我供给。它运行在框架之上。
  • 自我改进系统:循环加上能累积的记忆——每次运行都让下一次运行更敏锐。

实践做法:将固定事实放在上下文中,强制约束放在 Hook 里,流程放在技能中,隔离放在子 Agent 中。

混淆这些——把强制约束放在 CLAUDE.md 中,把流程塞满上下文——是导致 Agent 不一致且昂贵(Token 消耗大)的根本原因。

04. 默认框架。开箱即用。

安装 Claude Code,打开一个文件夹,你就已经拥有了一个框架——只不过是个空框架。默认配置给你一个能力不错的模型、内置工具(read, write, bash, search),以及所有风险操作前的审批提示。没有项目上下文,没有自定义子 Agent,没有记忆。

图像

对于一次性任务,默认配置没问题。但对于任何你会重复做的事情,默认配置会让 Agent 每次会话都从零重新推导你的项目,为安全操作请求许可,并且关闭终端后忘记一切。

接下来的十步是关于填补这个差距的。

05. CLAUDE.md:固定事实,保持简短。

CLAUDE.md 在每个会话开始时被读取。它是 Agent 对你项目的固定知识——约定、架构、“因为那次事故所以我们不这样做”。

图像

最常见的一个错误:让它膨胀成一份巨大的流程文档,从而拖累每个会话。

每天实践的开发者给出的规则:将主记忆文件保持在 500 Token 以内。固定事实放在这里。

多步骤流程放在技能中(第 8 步)。路径特定的行为放在作用域匹配的 rules/ 文件中。如果 CLAUDE.md 的某部分变成了流程而非事实,它就应该移到别处。

大声朗读你的 CLAUDE.md。每一行都应该是 Agent 在每个会话中都需要的事实(“我们使用 pnpm,而不是 npm”)。如果某一行是流程(“要添加一个功能,首先……”),将其移到技能中。

如果它是针对某个文件夹的规则,移到 rules/。

06. settings.json:权限和模型,一次设置。

默认框架会在每个风险操作前询问。当你盯着屏幕时这是对的,但当你不在时就不对了。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/*)"
    ]
  }
}

自动批准测试:如果操作出错,撤销有多困难?容易撤销 → 自动批准。难以撤销(强制推送、删除文件、触及密钥)→ 总是拒绝或提示。中间地带如果记录日志,也可以自动批准。

07. 子 Agent:为脏活提供隔离的上下文。

子 Agent 是从主 Agent 启动的独立 Claude 会话——拥有自己的上下文窗口和工具列表。目的不是并行本身,而是将噪音排除在主上下文之外。

一个读取 40 个文件的研究任务、一次需要新鲜视角的审核、一次产生大量日志的评估运行——这些应放在子 Agent 中,以免污染主线程。

图像

任何框架中最有价值的子 Agent 是检查主 Agent 工作的那个。模型自审自身输出时太容易放过自己。一个拥有新鲜上下文窗口的独立审核者,能发现写作时自我说服的问题。这就是写者与检查者的分离,它使框架之上的每个循环变得可信。

08. 技能:Agent 复用的流程。

技能是一个 SKILL.md 文件,Agent 会运行它——要么当你用 /skill-name 调用时,要么当任务与描述匹配时自动运行。

图像

与子 Agent 不同,它在同一个上下文窗口中运行。它只是可复用的指令,成为会话的一部分。

创建技能的触发点:你注意到自己在每次新对话中粘贴相同的指令。那就是一个即将诞生的技能。PR 检查清单、评估流程、发布过程——写一次,永久调用。

由于技能是可复用的单元,它们使框架能够随时间改进:每次流程以新方式失败时,你将教训添加到技能中,下一次运行就会继承它。

09. Hook:模型无法绕过的确定性规则。

到目前为止,一切都依赖于模型理解你的指令。Hook 则不依赖。

Hook 是在 Agent 生命周期的固定点触发的 shell 命令——在工具运行之前、文件更改之后、会话结束时——它的退出码可以阻止操作。Hook 是强制约束,CLAUDE.md 是建议。

图像

两个 Hook 在几乎每个框架中都占有一席之地:

  • PreToolUse 门控:确定性阻止危险命令——rm -rf、读取 .env、推送到 main。退出码 2 会在调用发生前停止它。模型无法通过自我说服绕过去。
  • PostToolUse 格式化器:每次编辑后运行你的 linter 或格式化器。Agent 永远不会交付未格式化的代码,因为框架会自动格式化它。
"hooks": {
  "PreToolUse": [{
    "matcher": "Bash",
    "command": "./.claude/hooks/block-dangerous.sh"
    // exit 2 = block the call before it runs
  }],
  "PostToolUse": [{
    "matcher": "Edit|Write",
    "command": "prettier --write \"$CLAUDE_FILE_PATH\""
  }]
}

Hook 用于必须发生或绝不能发生的事情——安全、格式化、审计日志。

不要将它们用于需要判断的决策;那是模型的工作。一个好的框架有一两个锋利的 Hook,而不是二十个。

第三部分:让它累积

10. 添加一个循环。现在框架按定时器运行。

配置好的框架仍然等待你输入。循环让它自主运行。最简单的版本是 Claude Code 中的 /loop——按节奏重复提示。

图像

将其与 /goal 配对,循环会持续进行直到客观条件成立,由独立评分者而不是 Agent 自我评分来检查。

> /loop 30m /goal All tests pass and lint is clean.
  Triage new failures, draft fixes in claude/ branches.

▲ Claude uses the Harness you built:
  - rules/ for conventions
  - reviewer SubAgent to check each fix
  - PreToolUse hook blocks pushes to main
✓ Looping. Independent grader decides “done.”

注意刚刚发生了什么:循环没有增加智能。它复用了框架中的所有东西——规则、审核子 Agent、安全 Hook。一个好的框架让循环变得微不足道。这就是先打好地基的全部意义。

11. 添加动态工作流。框架自行编写编排。

对于单个循环过于复杂的任务——大规模并行、高度结构化、对抗性——Claude 可以即时编写自己的 JavaScript 框架。

这就是动态工作流:agent() 用于生成,parallel() 用于扇出,pipeline() 用于流式处理。它将你框架定义的子 Agent 组合成扇出并综合、或对抗性验证等模式。

图像

与框架工程的联系:动态工作流的好坏取决于它能调用的子 Agent 和技能。

如果你的框架有一个锐利的审核子 Agent 和一个写得好的评估技能,工作流就有好的组件可供编排。如果框架是空的,工作流就没有东西可操作。

工作流是指挥,你的框架是乐团。

12. 添加记忆。Agent 忘记的,框架会记住。

这一步将配置好的框架变成一个真正能够改进的系统。Agent 在运行之间忘记一切。框架不必如此。

一个状态文件——agent-memory/ 中的 markdown 文件,或 Linear 看板——记录尝试了什么、什么有效、什么失败、哪些规则幸存。

图像

使记忆累积的模式,来自最强 Agent 的使用方式:

  • 离开前写入。每次运行结束时更新状态文件——学到的教训、验证过的事实、下一步计划。
  • 开始时读取。每次运行开始时读取状态文件和相关技能,从而继续而非重新开始。
  • 提炼到技能中。当一个教训具有通用性时(“Windows Runner 需要使用 bash,而不是 PowerShell”),它会从状态文件升级到技能中,从而适用于所有未来项目。
## Project memory

### Verified facts # stop guessing about these
- prc is in dollars, not cents (checked via SELECT MIN/MAX)
- auth middleware order: rate_limit -> jwt -> rbac

### Lessons learned # distill the general ones into skills
- Windows CI runners fail TLS 1.2 in PowerShell — use bash
- Migrations on tables >1M rows must batch in 10k chunks

### Last session # resume, don’t restart
2026-06-11 · 3 fixes merged, 2 escalated. Next: verify rate-limit fix.

13. 闭合循环。输出 → 教训 → 技能 → 更好的输出。

这就是三个层面锁定在一起,形成自我改进系统的地方。每次运行产生输出。审核子 Agent(第 7 步)检查它。

结果——哪些通过、哪些失败、学到了什么——被写入记忆(第 12 步)。通用的教训被提炼到技能中(第 8 步)。

下一次运行继承更锐利的技能和更丰富的记忆。

这就是整个自我改进循环,注意它完全由框架部件构建而成:

  • 子 Agent 评分工作——客观检查,新鲜上下文。
  • 记忆记录裁决——在运行之间持久化。
  • 循环再次运行——现在带上了上次运行学到的一切。

模型从未改变。围绕它的框架变得更加锐利。这就是“自我改进”的真正含义——不是模型在学习,而是框架在累积。

14. 交付框架。打包它。分享它。复用它。

在一个项目上有效的框架是一项资产。

将技能、子 Agent 和规则打包成一个插件,你的整个团队可以一步安装相同的设置——相同的约定、相同的安全 Hook、相同的审核者。

图像

框架不再是你的个人设置,而成为共享基础设施。

最后一次强调构建顺序,因为顺序本身就是教训:首先让一次手动运行在干净的框架上可靠。添加上下文和权限。添加审核子 Agent。添加记忆。然后,也只有在这之后,才将其包裹在循环中。良好框架上的循环会累积。糟糕框架上的循环只会更快地失败。

让每个循环更糟的框架错误

  • 在默认框架上运行。没有上下文、没有规则、没有记忆——Agent 每次会话都从零重新推导你的项目。
  • 臃肿的 CLAUDE.md。将流程塞入固定上下文,拖累每次运行。将它们移到技能中。
  • 在 CLAUDE.md 中强制约束而非使用 Hook。模型可以忽略建议,但不能忽略退出码为 2 的 Hook。
  • 一个 Agent 同时编写和评分自己的工作。添加一个拥有新鲜上下文窗口的审核子 Agent。
  • 没有记忆。每次运行从零重启。状态文件是让明天能够继续的关键。
  • 在糟糕的框架上包裹循环。循环只会更快地产生垃圾。先打好地基。
  • 二十个 Hook。一两个锋利的 Hook 胜过一堆无人理解的东西。
  • 不扫描就交付框架。泄露的密钥和过宽的权限会扩散到所有安装它的人。

结论

循环获得了荣耀。框架做了实际工作。

循环工程是令人兴奋的部分——Agent 自我提示,在你睡觉时运行。但循环只是带定时器的框架。

决定输出是好是坏的一切都位于更下一层,在你选择的模型中、在你允许的工具中、在你编写的上下文中、在你添加的审核者中、在你保留的记忆中。

把这一层建好,其上的所有东西都会累积:循环复用你的子 Agent,工作流编排你的技能,记忆让每次运行比上一次更锐利。

自我改进从来不是模型的属性。它是你围绕模型构建的框架的属性。

选择一个你目前没在做的事情——可能是审核子 Agent、安全 Hook 或状态文件——今天就去添加它。保持框架足够小以便能解释清楚。然后在其上放置一个循环,观察地基完成工作。

  • 原文链接: x.com/0xcodez/status/206...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

相关文章

0 条评论