Week 4 的问题不是要不要把任务交给 Agent,而是要在哪一步放手、在哪一步把人留在回路里。这周的阅读和作业从不同角度给出同一套答案:给它清楚的边界、可验证的检查和干净的上下文;需要判断的时候,人仍然要在场。

本周阅读

这周围绕 Claude Code 的使用方式、第三方 Agent 集成与其内部机制,读了下面五篇材料:

  1. How Anthropic Uses Claude Code(PDF)
  2. Claude Code Best Practices
  3. Awesome Claude Agents
  4. Super Claude
  5. Peeking Under the Hood of Claude Code

作业还需要精读 Subagents overview,它是完成作业时的技术参考。

Anthropic 团队案例与官方最佳实践

任务分类:什么该放手,什么该盯紧

几乎每个团队都在说同一件事的不同版本:产品研发团队区分”能异步跑的任务”和”需要同步盯着的任务”;RL 工程团队”先一次性尝试,成功率大概三分之一,不行再切换协作模式”;官方最佳实践给的判断标准更直接——“一句话能描述这个改动,就别做 plan,直接做”。

放手执行同步盯紧
适合场景边缘功能、原型探索核心业务逻辑、关键修复
判断标准能一句话描述这个改动不确定该用什么方案、改动涉及多个文件、不熟悉这块代码
具体例子Vim 模式 70% 由 Claude 自主完成先做 plan,实时监督实现过程

这条本身已经是自己在用的方式,只是不刻意区分”在 Claude.ai 聊 plan”和”在 Claude Code 里聊 plan”——两者用的是同一份 usage 额度,跟 OpenAI 的 ChatGPT/Codex 分开计费不一样,usage 计费方式本身会反过来塑造工作流该怎么搭。

给它一个自己能核实对错的东西

官方最佳实践把这条放在全文第一条原则:给 Claude 一个能跑的检查,区别就是要不要全程盯着。产品研发团队把这个叫”自给自足的循环”,特别提到”先写测试再写实现”效果最好——跟”先写测试再用 Agent 实现”这个做法是同一个道理,这次在完全不同的团队又被独立验证了一次。

没有检查时人是唯一验证环节,有检查时形成自己闭环的对比

上下文是稀缺资源:/clear、checkpoint、Subagent

官方最佳实践的前提是:上下文窗口会很快填满,填满后表现会下降——跟上下文失效这件事是同一个道理,这次给出了具体功能:/clear、checkpoint/rewind、用 Subagent 做调查性工作。这本质上就是 Context Quarantine,只是这次是 Claude Code 里真实存在的功能,不需要分开讲。

主对话委派给 Subagent 做调研,冗长内容留在 Subagent 里只返回摘要,以及该用与不该用的判断标准

创建方式最简单的是直接让 Claude 生成,存到 .claude/agents/ 下可以检入 git、团队共享;调用除了让 Claude 自己判断,也可以用 @ 加引号强制指定某个 subagent,比如 @"code-reviewer (agent)"(code-reviewer 换成自己 subagent 的真实名字)。

先聊清楚写成 spec,再开干净的 session 去实现

官方技巧:大功能先用 AskUserQuestion 工具让 Claude 反过来采访你,写成一份 SPEC.md,再开新 session 去执行。这跟 Claude Code 团队自己”原型放手、核心逻辑盯紧”的区分放在一起看,是 Anthropic 工程团队给出的一致答案,具体分五步:

1. 模糊想法
   "我想做点 xxx"

2. 用 AskUserQuestion 工具,让 AI 反过来采访你
   深挖技术实现、UI/UX、边界情况、权衡取舍
   不问显而易见的问题,一直问到覆盖全部

3. 写成一份 SPEC.md

4. 开一个新 session
   干净上下文,没有历史包袱

5. 照着 spec 专注实现

为什么”让 AI 反过来采访自己”有效:不主动让它发散,它的思考会被限定在自己已经想到的范围里;反过来提问既能拓宽视野,也能倒逼出一份更精准的 spec,降低 implement 阶段”解决了一个错误问题”的概率。

反过来核查:对抗性审查

官方版本:

1. 任务做完,产出一份 diff
2. 开一个"不知情"的 Subagent
3. 只给它 diff + 验收标准(不给思考过程)
4. 它给出中立的审查发现

不给思考过程这一步是关键——这样它不会对已经产生的判断有偏见。

一个延伸想法(未验证):这个思路不必局限在同一家模型内部,可以跨厂商组合,用不同实验室的”审美”互相校正:

ChatGPT 讨论计划并产出 prompt、Codex 实现、Claude Code 不知情审查的跨厂商对抗性审查流程

什么时候该自动触发这类审查、什么时候必须转人工,还没想清楚,先记成开放问题——查了一下,/goal 本质上是一个只在当前 session 生效的、prompt 形式的 Stop hook,技术上是可以把”审查通过”设成完成条件的。

Skills 到底还值不值得写:一个看似矛盾、实际是两件事被混着讨论的争论

一种说法是模型越强 skill 越是拖累,另一种说法是不写 skill 只用了三成实力。查了一下现状:“skill 会过时”这个说法站不住脚,但硬币另一面是真的——给旧模型写的 skill 专门纠正那个模型的弱点,换了新模型后这些指令不仅没用还会干扰。Anthropic 自己就是这么处理的:每次模型升级都会删掉系统提示词里一大截针对上一代弱点写的内容,这跟 MCP 的”Capability over compensation”原则是同一个道理。

两派吵的很可能根本不是同一件事:

补足模型短板按需加载领域知识
具体是什么纠正旧模型的具体弱点项目规范、业务知识
模型变强之后指令没用,甚至干扰新模型价值跟模型聪不聪明没关系
会不会过时会——该删就删不会——模型再强也没法凭空知道这些

一派说”补短板”会过时,是对的;另一派说”按需加载知识”不会过时,也是对的;混在一起讨论才显得矛盾。

几个具体数字

Vim 模式 70% 由 Claude 自主完成,只需要几轮迭代;ML 概念查询时间从原本要 1 小时 Google 搜索压到 10-20 分钟,省了 80%;Growth Marketing 团队(技术人员只有一个人)用两个专门的 sub-agent 分头生成广告标题和描述,广告文案制作时间从 2 小时压到 15 分钟;RL 工程团队一次性把功能做对的概率大概三分之一;安全工程团队用掉了整个代码仓库全部自定义 slash command 的一半。

两个 Agent 集成仓库

这两个仓库都是给 Claude Code 装上一层”重装甲”,思路不太一样。

第一个是一份现成的 subagent 集合,一共 24 个,分四类:3 个负责统筹的编排类(其中一个会自动检测项目用的技术栈,把最合适的几个 agent 配置进 CLAUDE.md);13 个按具体框架分工的专家,覆盖 Laravel、Django、Rails、React、Vue,每个框架下面还细分成后端/API/ORM 这类更具体的角色;4 个不挂靠具体框架的通用专家(前端、后端、API 架构、Tailwind);4 个核心团队角色——专门探索旧代码库的”代码考古学家”、带安全意识的代码审查员、性能优化专家、文档专家。用法是把整个 agents 文件夹链接进 ~/.claude/agents/,跑一次自动配置检测技术栈,之后正常描述需求,由编排 agent 自动路由给合适的专家处理。仓库自己也提醒这是”实验性的,很吃 token”——一个复杂功能的多 agent 协作可能消耗 1 到 5 万 token。

第二个走的是另一条路,不是给一堆现成角色,而是给 Claude Code 整体套上一层结构化的工作流:30 个 /sc: 开头的 slash command,覆盖从头脑风暴、实现到测试、项目管理的完整开发流程;20 个专门 agent;7 种行为模式;还能选装 8 个 MCP server(比如专门做代码理解的、专门做高效推理的、专门查官方文档的),官方说装上这些能有 2-3 倍速度提升、省 30%-50% 的 token。仓库声明里写明”不隶属于 Anthropic,也不是它官方认可的产品”。

两个都没实际装过用过,但查了这类”装一堆现成东西”思路的真实使用反馈,答案跟直觉不太一样:不是没用,但常见的真实结局是装了很多、最后精简到没几个。有人自己写了 100 个 subagent,最后筛下来真正配得上占用一次上下文切换成本的只有 12 个,日常最常用的组合只有 3 个——原话是”少而精,是这件事唯一的技巧”。

100 个 Subagent 精简到 12 个、再到日常常用 3 个的漏斗图,对照 Awesome Claude Agents 和 SuperClaude 的规模

这个结果支持一个判断:暂时不会主动去装这类第三方框架,倾向于跟原生 Claude Code / Codex 直接配合。查到的另一条证据指向同一个方向——用 Claude Code 原生的方式,不额外叠加这些第三方层,模型本身探索、搜索、执行的量就已经比极简替代方案多出 1.5 到 2 倍,说明官方原生能力这条线本身就在很快进步。

这里留一个问题:原生的东西已经这么经打了,为什么装更多定制反而经常划不来?下一篇给出了机制层面的答案。

拆解 Claude Code:藏在背后的提醒机制

上一节留的问题,这篇有具体答案。文章的方法是实际截获 Claude Code 和模型之间的真实通信,看外壳程序到底往对话里塞了什么。

发现的核心机制是一种叫 <system-reminder> 的自定义标签:Claude Code 自己在系统提示词里教会模型这个标签是什么意思。模型本身并不自带这个功能,之后它会在系统提示词、用户消息、工具调用、工具返回结果之间反复插入。它起到一个”带外通道”的作用:往对话里塞入关键提醒,但不会让模型误以为这是用户自己说的话,更像一个只有模型能看到的私人便签,不断把执行过程拉回正轨。关键的一点是:这些提醒对用户是隐藏的,不会显示在界面上,是在外壳程序和模型之间悄悄插入的。

工具调用之后 system-reminder 标签被悄悄插入对话、用户界面完全看不到的流程图

这套机制会让人联想到 CoT(思维链),两者确实都是为了不让模型跑偏,但作用的层面完全不同:CoT 是模型自己在单次生成里吐出来的推理过程,原理是每生成一个 token 算力是固定的,让模型先把步骤写出来,相当于把一次算不完的问题拆成很多步接力完成,整个过程都在模型内部,外壳程序不插手;System reminder 反过来,是外壳程序在特定时机主动插入的东西,模型自己生成不出来,只是被动读到——它要解决的不是”单次回答会不会算错”,而是一个跨很多轮的长任务里,早先定下的目标或者约束会不会被读串、被冲淡。

Chain-of-Thought 与 System Reminder 对比:谁生成、发生在哪、解决什么问题

这套隐藏提醒机制,很可能就是专门用来预防上下文失效(分心、混淆这类问题)的具体工程手段:在关键节点主动把可能被冲淡的信息重新摆到模型面前,而不是等问题真的发生了才补救。外部看起来 Claude Code 表现得”很稳”,背后其实一直有这样一层看不见的脚手架在悄悄纠偏——这正是上一节”原生能力已经这么经打”背后真正的原因。

知道这套机制存在,不会改变实际跟 Claude 对话的方式——它本来就看不见摸不着。但这类把黑箱拆开来看的逆向工程研究本身有价值,值得记这一笔。

Assignment

题目:The Autonomous Coding Agent IRL——给 week4/ 下现成的全栈脚手架(FastAPI 后端 + SQLite + 静态前端,“开发者指挥中枢”定位)做至少 2 个 Claude Code 自动化,可选形式:

  • 自定义 slash command(存进 .claude/commands/*.md)
  • CLAUDE.md 引导文件
  • SubAgents(多个角色分工协作)
  • 集成进 Claude Code 的 MCP server

要求先做自动化,再实际用这些自动化去改造/扩展这个脚手架,writeup.md 里要写清楚设计灵感、每个自动化的目标/输入输出/步骤、怎么跑、改造前后对比、以及实际怎么用它扩展了应用。

这周的作业跟前几周形态不一样,是给 Claude Code 本身做自动化,再要求真的用它去改造这个全栈脚手架应用(notes 和待办事项功能)。最后做了四个自动化:一个统一跑测试/lint/格式检查、给出人话总结的命令;一个能从真实接口定义反向生成接口文档、还能报告哪些接口有变动的命令;一份让每次打开这个项目都自带背景知识(项目结构、已知问题、默认工作流)的引导文件;以及一对分工严格的 Subagent——一个只负责写测试,一个只负责让测试通过。

真正值得写下来的,是这对 Subagent 怎么把前面讲的东西,从”应该这样做”变成了”真的这样跑了一遍”。

写测试的这个角色,权限被卡得很死:它能读整个项目的代码,但物理上不允许碰任何一行实现代码——哪怕看得出问题出在哪,也只能写下来交给另一个负责实现的角色去改,自己绝不能顺手改一下。反过来,负责实现的角色也碰不了测试文件半个字。这个约束写进了各自的权限定义里,不靠”记得要这样做”的君子协定支撑,就算哪次指令给得不够精确,写测试的角色也没有能力去动实现代码——这正是前面讲的”Subagent 之间该怎么划边界”,从一句话说法变成了一个真实存在的例子。

验证这一步也做得比”跑一遍测试通过”更彻底:修完一个问题之后,专门把这次修复用版本控制临时撤掉、重新跑一遍测试,确认测试真的会因为这个修复的存在与否而红绿切换,不是凑巧本来就会过。这是把”给它一个自己能核实对错的东西”这条原则又往前推了一步:不只是有检查,还要证明这个检查真的在检查这件事。

过程中还撞上了两个有意思的情况。一个是纯粹的工具限制:新建的自定义 Subagent,在一个已经开着的交互会话里一开始是识别不到的,得另开一个全新的会话才认得出来,过一阵子原来那个会话又自己刷新认出来了——这条官方文档完全没提,是真的用出来才知道的。另一个更巧:某次Subagent 在读取工具返回结果时,混进去一段格式很像”外部注入指令”的文字,内容其实是这次会话本身自带的标准系统提示,不是谁精心构造的攻击。Subagent 的处理方式是对的——没有把它当成需要执行的新指令,只是如实汇报看到了这个东西。这跟前面拆开讲的那套隐藏提醒机制,是同一件事在真实场景里撞上了一次:提醒本来就是悄悄插进对话里的,让人分不清”这是系统在说话”还是”这是外部内容”,这次只是从”读文章知道有这么回事”,变成了”亲眼在真实任务里见到一次”。

四个自动化各自的分工:

自动化形式做什么
统一检查命令slash command跑测试 + lint + 格式检查,汇总成一句话总结
接口文档同步命令slash command从真实接口定义反向生成文档,报告哪些接口变了
项目背景引导文件CLAUDE.md项目结构、已知问题、默认工作流
写测试 / 写实现 双人组Subagent ×2一个只写测试,一个只让测试通过

四个自动化最后都真的用来做了事:改好了脚手架自带的一个真实 bug(种子数据从来没有真正导入过,问题出在两行初始化代码的先后顺序,是探索阶段用真实请求测出来的,不是看代码看出来的);把已经写好但前端一直没接上的搜索框真正接上了,加了笔记的编辑和删除功能;待办事项的标签解析也补齐了。批量测试从最初的几个涨到十几个,全部通过。

那对 Subagent 的验证流程,比标准 TDD 循环还多一步:

TestAgent 写失败测试到 CodeAgent 实现转绿,再用 git stash 撤掉修复重跑确认变回失败、恢复后确认变回通过的完整验证流程