代码语言
选择后全站课程跟随

子代理:同一个循环,新上下文

4,309 字 · 预计阅读 12 分钟

前情提要

  • 子代理有三个特点:独立上下文、只带回结论、可以定制
  • 自定义子代理写在 .claude/agents/ 下,一个 .md 文件就是一个:
markdown
---
name: code-reviewer
description: 代码审查子代理。改完代码、准备提交前使用。
tools: Read, Grep, Glob, Bash
model: sonnet
---

你是一名严格的代码审查员……(正文就是它的系统提示词)
  • 派活要把背景写全,把它当成一个完全不了解项目的外包同事
  • 计划模式:Claude 只读、只出方案,你批准之后才动手
  • 「隔」是上下文工程的第四种手段:换一张干净的台面(第11节)

第11节讲了写、选、压,这一节讲最后一种手段:隔。

子代理为什么看不到主线的对话?为什么它不能向你提问?为什么派活的时候要写那么多背景?这一节去 AgentTool/ 里找答案。最后用同样的「软约束 + 硬约束」思路,做出计划模式。


一、子代理就是再调一次 query()

子代理复用同类循环但拥有独立上下文

主代理调用 Agent 工具之后,进入 AgentTool/runAgent.ts:

主代理调用 Agent 工具(subagent_type、prompt)
  │
  └─ runAgent()
       ├─ 消息:新建一个列表,里面只有一条——主代理写的任务描述
       ├─ 系统提示词:换成子代理自己的(自定义子代理就是那个 .md 文件的正文)
       ├─ 工具:按定义里的 tools / disallowedTools 过滤,再去掉所有子代理都不能用的几个
       ├─ 模型:按定义里的 model 选
       ├─ 运行:调用的还是 query() —— 就是第2节那个循环
       └─ 结束:只取最后一条回复里的文字,作为 Agent 工具的结果交还给主代理

子代理不是另一套系统。它用一份新的消息列表、新的系统提示词、新的工具列表,再调用一次同一个循环。

这是整个架构最漂亮的地方:循环只写一份,主代理、子代理、context: fork 的 Skill(第7节),用的都是它。

子代理 = 同一个循环 + 一份新的消息列表。


二、所有子代理都不能用的工具

src/constants/tools.ts 里有一份名单 ALL_AGENT_DISALLOWED_TOOLS。对普通用户来说,里面最重要的两个是:

不能用的工具 意味着
Agent 子代理不能再派子代理,避免无限套娃(Anthropic 内部员工的版本例外)
AskUserQuestion 子代理不能向你提问

第二条是「派活要把背景写全」这条建议的根源。

想象一下:子代理在干活的时候,遇到一个不清楚的地方。主代理可以停下来问你,子代理不行。它没法回头问,只能自己猜。

所以背景只能在派活的那一刻一次给全。

子代理不能提问,不清楚的地方只能猜;所以派活时,背景要一次给全。


三、只带回最后一条回复

子代理把最终结论交回主线

agentToolUtils.ts 里的 finalizeAgentTool() 只取子代理最后一条回复里的文字。它中间读了 50 个文件、跑了 20 条命令,主线一个字都看不到。

这就是「隔」:过程留在子代理那边,主线只拿到结论,上下文干干净净。

子代理自己也知道这一点。内置的通用子代理(general-purpose),系统提示词里写着:

完成任务后,用一份简洁的报告说明做了什么、有哪些关键发现。调用你的一方会把它转述给用户,所以只需要要点。

所以你自己写子代理的系统提示词时,也要写清楚「最后一条回复要包含什么」。比如:

markdown
最后一条回复按这个格式:
## 问题(按严重程度排序)
- 文件:行号 — 问题 — 建议
## 结论
可以提交 / 需要修改

格式固定下来,主代理拿到之后好处理,也不会漏掉关键信息。

子代理只交回最后一条回复,所以要规定好这条回复写什么。


四、主代理怎么派活

Agent 工具的说明,相当于写给主代理的「派活指南」。里面有三句话特别值得读:

像给一个刚走进房间的聪明同事交代任务那样写:他没看过这段对话,不知道你试过什么,也不明白这个任务为什么重要。

命令式的短句,只会换来浅薄、泛泛的结果。

不要把「理解」也外包出去。不要写「根据你的发现修复这个 bug」「根据调研结果实现它」。要写出能证明你已经理解了的指令:文件路径、行号、具体改什么。

最后一条尤其值得记住,而且它对人同样适用。你给 Agent 派活时说「看看哪里有问题,修一下」,就是在外包理解。

对比一下:

外包了理解 先理解了再派
「登录有 bug,帮我修一下」 「src/auth/login.ts:42 在 token 过期时没有刷新,直接返回了 401。改成先调 refreshToken(),失败了再返回 401。改完跑 npm test auth」

派活要像给刚进门的同事交代:目标、背景、已知的、具体到文件和行号。


五、Explore 看不到你的 CLAUDE.md

第6节讲过:只读的 Explore、Plan 子代理不带 CLAUDE.md,每周能省下 50 亿到 150 亿 token。它们同样不带 git 状态。

副作用是:你在 CLAUDE.md 里写的「不要看 vendor/ 目录」「生成的代码在 dist/,别当源码」,Explore 不知道。

本文是会员内容

全文 4,309 字,已试读约 29%。 开通专业版可阅读全文,并解锁全部课程与后续更新。

开通专业版

支持 7 天无理由退款 · 早鸟期前 500 名自动升级永久卡