使用 Claude Code 进行 Agentic 编码——使用 Claude Code 子智能体

0 阅读49分钟

在本章中,我们将探讨 Claude Code 的 subagents(子智能体) ,以及它们如何支持更结构化、可扩展的工作流。我们会先理解 subagent 是什么、它们与 Claude Code 主 agent 有什么不同,以及为什么**上下文隔离(context isolation)**是其设计核心。在进入更高级的工程化场景之前,这些基础认知是必须先建立起来的。

接着,我们会进入动手实现阶段。我们将配置自定义 subagent,考察 prompt 和工具访问权限如何影响执行过程,并详细分析上下文流动机制。最后,我们会通过 Infinite Agentic Loop 模式,用并发 subagent 来扩展执行规模,展示如何通过并行 agent 编排来探索多种实现方案,并从中挑选出最优结果。

本章将涵盖以下主题:

  • Claude Code subagents 导论
  • 配置第一个 subagent
  • 测试我们的 subagent
  • 在使用 subagent 时维持内容流
  • 通过并发 subagent 进行扩展
  • Infinite prompt

Claude Code Subagents 导论

在这一节中,我们会学习 Claude Code subagents 的概念。这一部分偏理论、偏高层理解,但在进入实操之前非常重要。我们会深入讨论这个主题,包括它底层实现的一些关键方面。

与其写几十条单独的 Prompt,我们可以只执行一个命令,例如 /cook,由它去编排一整组专门化 AI agent。每个 agent 都被设计成只做一件事,但要把这件事做到特别好。

根据官方文档(https://code.claude.com/docs/en/sub-agents),subagents 是 Claude Code 可以委派任务给它们的、预先配置好的 AI 人格。每个 subagent 都有自己的用途和专长领域。从实践角度看,这意味着:每个 subagent 本质上都由一个特定 prompt 来定义。subagent 的一些关键特性包括:

  • 每个 subagent 都有自己的 system prompt。这个 prompt 完全由我们控制,我们可以精确定义这个 agent 应该如何工作、能做什么、以及怎么做。这给了我们非常高的灵活性与控制力。
  • subagent 运行在独立的 context window 中,与主对话上下文分离。这种上下文隔离非常关键,因为它能防止上下文污染。主对话不会把自己的偏差带进 subagent 的任务中。每个 subagent 都能专注于自己的高层目标。这一点非常重要,贯穿本章后续内容。
  • 每个 subagent 都可以被配置成只允许使用一组特定工具。从安全角度看,这一点非常关键,因为它让我们能够遵循最小权限原则(principle of least privilege) 。也就是说,我们只应该给 subagent 实现目标所必需的工具。比如,一个代码审查 agent 可能只需要读文件或联网查资料;但既然它的职责只是审查代码,那它就不应该拥有执行 shell 命令或写文件的能力。这种对工具访问的选择性控制,是 subagent 的核心特征之一。这里的工具访问既包括 Claude Code 原生工具,也包括通过 MCP server 暴露出来的能力。至于 Skills——我们后面会讲——它们处在另一个层级,定义的是结构化能力,而不是直接的工具权限。
  • subagent 是可复用的。我们只需要创建一次,就可以在不同项目间复用,也可以作为团队工作流的一部分共享给团队成员。触发 subagent 的方式有多种。它们可以通过 Markdown 文件进行描述,并遵循 Claude Code 本身的层级体系。如下是一个例子:
name: code-reviewer
 description: Senior code review agent. Automatically analyzes code changes for bugs,
 security flaws, and convention violations. Invoke after any code modification.
 tools: Read, Grep, Glob, Bash
 model: inherit
 ---
 You are a meticulous code reviewer embedded in the he110.me project (Next.js 16, React 19,
 TypeScript, Firebase, Tailwind v4).
 ## Workflow
 1. **Collect diffs**: Execute 
`git diff --staged`
 and 
`git diff`
 to capture all pending
 changes. If both are empty, fall back to 
`git diff 
HEAD~1
`
 for the most recent commit.
 2. **Examine full files**: For each touched file, read it entirely — not just the changed
 lines. Understand the surrounding logic, imports, and how the modification integrates with
 existing code.
 3. **Trace dependencies**: Use Grep/Glob to locate every consumer of modified functions,
 types, or exports. Flag any call sites that need updating.
 4. **Validate project rules** (per CLAUDE.md):
   - Firestore Timestamps converted via 
`.
toMillis
()`
 before reaching client components
   - AI utilities imported exclusively from 
`lib/ai/
langsmith.ts
`
, never from 
`ai`
 directly
   - All profile writes routed through API endpoints, never via client-side Firestore SDK
   - Authenticated requests use 
`
authFetch
()`

   - 
`
VoiceWaves
`
 shares the recorder's MediaStream rather than opening its own
   - Styles follow mobile-first approach (bare classes = mobile, progressively enhanced with
  
`
sm
:`
, 
`md:`
, 
`lg:`
)
 ## Severity Levels
 ### Critical — block merge
 - **Security holes**: injection vectors, XSS, leaked credentials, absent 
`
verifyAuth
()`

 checks, SSRF, open redirects
 - **Data corruption risk**: unguarded write operations, race conditions, malformed Firestore
  batches
 - **Auth gaps**: missing ownership verification (
`
currentUser.uid
 === 
profile.uid
`
), exposed
  protected endpoints
 - **Downstream breakage**: altered signatures or deleted exports without updating all
 dependents
 ### Warnings — resolve before shipping
 - API handlers lacking input sanitization
 - Swallowed promises or absent try/catch around async work
 - Performance pitfalls: gratuitous re-renders, missing memoization on costly computations,
 repeated Firestore round-trips
 - Inconsistent API response shapes across routes
 - Loose typing (
`any`
, implicit 
`any`
)
 ### Suggestions — worth considering
 - Clearer naming for variables or functions
 - Logic that could be expressed more simply
 - Existing helpers in 
`lib/`
 that already solve the same problem
 ## Response Format
 Group findings by severity. For every finding include:
 - **Location**: file path and line number
 - **Issue**: single-sentence summary
 - **Impact**: what goes wrong if ignored
 - **Recommended fix**: a concrete code snippet demonstrating the correction

项目级 subagent,也就是只服务于某个特定仓库的 agent,通常放在 .claude/agents/ 目录下。
用户级 subagent,也就是跨所有项目共享的 agent,则存放在主目录下的 ~/.claude/agents/ 中。

Subagent 文件结构

Subagent 通过 Markdown 定义,结构如下:

image.png

图 7.1 —— Subagent 文件结构

每个 subagent 定义都以一个 YAML frontmatter 块开头。只有 namedescription 是必填字段,但还可以配置很多附加项,例如 toolsskillsmcpmodelhooksmemory 等等。完整 schema 请参考官方文档:https://code.claude.com/docs/en/sub-agents

description 字段的作用,是帮助主 agent 判断:什么时候应该调用这个 subagent

同样的概念在 subagent 上也成立。subagent 本质上也是主 Claude Code agent 可以调用的一类“工具”。因此,namedescription 之所以不能省略,就是因为 Claude Code 需要依赖它们来判断是否该调用某个 subagent。

subagent 定义中还会包含一组允许使用的工具。这些工具按名称列在 Markdown 文件中。如果这一节留空,那么这个 subagent 默认会获得所有可用工具的访问权限。这里的工具集合也可以包括 MCP,相关内容后面会展开。

subagent 定义的最后一部分,就是 system prompt。它包含了 subagent 的全部行为指令。这个 prompt 的格式没有强限制,可以包含静态上下文,也可以包含动态上下文,灵活性非常高。这里强调一下:它是 system prompt,不是 user prompt,这个区别很重要。system prompt 和 user prompt 的差异,会在本章后面进一步讲清楚。

与 React Agents 的关系

如果你之前做过 LLM 应用,这套结构可能会让你有熟悉感。它和 React agent 模式很像:模型会被赋予一组工具,每个工具都有名字和描述,同时还有一个 prompt,用来定义总体指令并限定 agent 的专长边界。例如:

from langgraph.prebuilt import create_react_agent

agent = create_react_agent(
    model="anthropic:claude-4-7-sonnet-latest",
    tools=[get_weather],
    # A static prompt that never changes
    prompt="Never answer questions about the weather."
)

agent.invoke(
    {"messages": [{"role": "user",
        "content": "what is the weather in sf"}]}
)
``

Claude Code agents、Claude Code subagents,以及传统 React agents 之间,确实存在很强的相似性。不过有一个关键区别:Claude Code 的主编码 agent 以及它的 subagents,具备处理长时间运行任务以及端到端实现功能的能力。

一种理解方式是:React agents 属于一个更大的范畴,而在这个范畴内部,还有一个更小的子集,叫 deep agents。Claude Code 的 coding agent 及其 subagents,就落在这个子集里。要被视为 deep agents,它们必须具备若干特征,这些内容会在后面的课程中继续讲。

理解这些 agent 在底层是怎么工作的,会帮助我们更准确地把握它们的行为方式,也能更有效地使用 Claude Code 的 subagents。

配置第一个 Subagent

这一节会聚焦于如何配置第一个 subagent。创建一个新分支,打开 Claude,然后使用 /agents 命令查看当前可用的 agent 列表:

image.png

图 7.2 —— 使用 /agents 查看可用 agent

此时,既没有项目级 agent,也没有用户级 agent。唯一可用的是一个内置的通用型 general-purpose agent。也就是说,我们还没有任何用户自己创建的 agent。

正如前面提到的,agent 可以在两个不同的 scope 下创建。在这里,我们选择创建一个项目级 agent,这样这个配置就可以被提交进仓库,并作为项目的一部分共享。

创建 agent 有两种方式:

  • 通过 Claude 自动生成
  • 手工配置

我们先走第一种方式,因为它最简单,直接通过 Claude 来生成。

定义 Agent Description

点击第一种创建方式之后,系统会先要求你定义 agent 的 description。这个 description 用来指定 agent 的目标,以及它应该如何运作。Claude Code 的主 agent 会依赖这段 description 来判断:是否应该调用这个 subagent。

Create new agent
Step 3: Describe what this agent should do and when it should be used (be comprehensive for best results)

A funny staff senior ultra software engineer that will review the code provided to him. Use this agent when you get an input like funny review.

在这个例子里,我让系统定义一个“有趣的、资深的、超强的软件工程师”,它会去审查用户给出的代码。这个 agent 预期会在用户输入包含诸如 funny review 这样的表达时被调用。这样一来,它的人设和主要目标——进行代码审查——就都被明确下来了。

这里还引入了一个关键词触发器,用来控制 agent 在什么情况下被调用。这在你与 Claude 交互、显式调用 agent 时会很方便。这个 agent 也可以通过 slash command 触发。

如果一个 prompt 感觉太模糊、太宽泛,与其手工反复打磨,不如另开一个 Claude 实例,让它帮你优化这个 subagent prompt。只需要把原始 prompt 作为输入,告诉它“请把这段定义得更清晰”,它就能帮你生成一个更完整、更细致的 system prompt。然后你再把这个改进后的 prompt 拿来直接用。这里之所以没有手工写 Markdown 文件,是因为我们现在是通过 CLI 直接在 agent 目录里创建 agent。

应用 System Prompt

输入 prompt 之后,界面会向你展示一些 activation trigger,例如 funny reviewfunny code review。这些 trigger 决定了 agent 会在什么时候被调用。

image.png

图 7.3 —— 配置 subagent 的 system prompt 与 activation triggers

按下 Enter,继续配置流程,然后系统就会生成对应的 agent 配置。

为 Agent 选择工具

下一步是选择这个 agent 可以使用哪些工具:

image.png

图 7.4 —— 在 setup 过程中为 subagent 选择工具列表

你可以选择:

  • 所有工具
  • 或按需选择某些具体工具

在我们的这个例子里,因为它是一个代码审查 agent,所以它主要只需要只读工具。如果确实有需要,也可以额外开启编辑工具和执行工具。MCP 工具也同样可以加入。

通过打开高级选项,我们可以看到 Claude Code 中完整的工具列表,包括 bashglobgreplsreadedit 等。前面配置过的 Context7 MCP 工具也会出现在可选项中。选完之后,再隐藏高级选项并继续。

选择模型与视觉设置

接下来需要为 subagent 选择它所使用的模型:

image.png

图 7.5 —— 选择模型并查看 subagent 配置摘要

模型选择的问题,后面书中会详细讲。但在这个例子里,我们选择 Sonnet,因为它在性能、价格和延迟之间平衡得比较好。

你还会被要求选一个颜色。这里我们选的是 yellow

在保存之前,系统会展示一份配置摘要。必要的话,你还可以再改。到这里,这个 agent 就被创建出来了。

审查生成出的 Agent 配置

接下来,我们打开生成出的 agent 文件,查看里面的内容。文件中已经包含了全部配置好的信息。

文件顶部是 agent 名称,接着是 agent 的 description。这段 description 会帮助 Claude Code 的主 agent 判断:什么时候应该调用这个 subagent。之后会列出它可用的工具。在这个例子里,并没有启用写入类工具。模型选的是 Sonnet,颜色是 yellow。

---
name: code-comedy-carl
description: >
  Use this agent when you want a humorous, entertaining code review that combines genuine technical feedback
  with comedy. Activate when users request funny review, entertaining review, roast my code, or mention Carl
  or CodeComedy Carl. This agent delivers insightful technical reviews wrapped in programming humor, memes,
  and witty observations while maintaining professionalism and educational value.
tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, mcp__context7__resolve-library-id, mcp__context7__get-library-docs
model: sonnet
color: yellow
---

这些配置值后续都还可以改。现在,这个 agent 已经定义好了,可以正式拿来用。

既然这个 review subagent 已经配置完成了,我们接下来就需要一个具体测试场景,看看它是否真的能按预期工作。为此,我们会先创建一个小样例文件,让 subagent 去分析它。这里的目标不是构建生产级逻辑,而只是生成一点简单代码,用来观察 subagent 是如何做代码审查的。

测试我们的 Subagent

首先,我们创建一个主 Python 文件,让它去计算 Fibonacci 函数:

write a main python file that calculated fibonacci function

这样,一个 Fibonacci 实现就有了。

image.png

图 7.6 —— 在调用 review subagent 之前,先创建一个 Fibonacci 脚本

运行一个代码审查 Subagent

为了演示 subagent 是如何被调用、以及它实际是如何工作的,我们运行一次针对 @main.py 的有趣代码审查:

funny review @main.py

这条操作会把我们刚才创建的 review agent 调出来,并真正 spawn 出一个实例。这个 agent 会初始化、读取文件内容,然后开始执行自己的任务。

如果此时还有别的文件存在,你完全可以再打开一次 Claude,再起一个同样的 review agent 实例。这里也正好体现了为什么 agent 这种机制有价值:同一个 agent 可以有多个实例,每个实例都运行在彼此隔离的环境里。一个 agent 不会影响另一个正在运行的 agent。

如果展开 agent 视图(Windows/Linux 用 Ctrl + R,macOS 用 Cmd + R),你就能看到 agent 内部的完整活动过程。

同时生成多个 Review 实例

现在,我们不只做一次 review,而是生成两次:

❯ create 2 funny code reviews of @main.py

这时,会 spawn 出两个 review agent 实例。你可以观察第一个和第二个实例各自处理任务的过程:

image.png

图 7.7 —— 为同一个文件生成多个 review subagent 实例

这里有一个很重要的点:这两个 review agent 实际上是串行执行的,而不是并发执行。Claude Code 并不会总是假设任务之间是独立的。如果它对潜在依赖关系拿不准,就更倾向于一个接一个地执行,而不是同时并行。

在实践中,这件事会受到你怎么写任务描述的影响。如果你确实希望它并行执行,那就需要把这一点说清楚。比如,与其说“review this PR”,不如明确说“review these files in parallel”或者“create separate review agents for each file”。只要你把任务独立性表达得足够明显,并发执行的可能性就会更高。

虽然这个例子里 agent 是串行运行的,但 Claude Code 的真正威力,其实要等到你有意识地让多个 subagent 并行执行时才会体现出来。后面本章还会继续深入这件事。

添加额外 Agent

如果还需要其他 agent,那么只要在 agents 目录中新增一个定义文件即可。

使用 Subagent 时的上下文流

这一节,我们来分析使用 subagent 时的上下文流动,并借助下面这张图理解:为什么 subagent 在这件事上会这么有用。我们先从主 agent thread 开始,也就是主对话线程。这个线程中的每一条消息,都会增加上下文中的 token 规模。

image.png

图 7.8 —— 主 agent 与 subagent 之间的上下文流

当主 agent 决定去调用一个 subagent 时,它会先构造一个新的 prompt。这个 prompt 会传递给 subagent,而这就是 subagent 执行时唯一会拿到的上下文。subagent 并不知道主对话前面完整发生过什么,它只知道主 agent 此刻生成并传给它的这段 prompt。

我们完全可以反过来影响这段 prompt,也就是说:让主 agent 在给 subagent 下达任务时,以更利于执行的方式去组织提示,从而提升结果质量。subagent 的执行效果,本质上完全取决于这段 prompt,因为这是它唯一拥有的上下文。subagent 会在这个上下文中独立工作,调用自己所需的工具,也可能做各种外部集成,最后只返回一个压缩后的响应。每次新的 subagent 被 spawn 出来时,它拿到的都是一个全新的 context,其中只有那条生成好的 prompt。

这种做法的价值在于:它能让主线程保持“瘦”。大量上下文被委派给 subagent 去消化,而 subagent 在隔离环境中完成工作,最后只把结果产物返回给主 agent。这样一来,主对话本身就能维持一个更小的 context window。

由于主 agent 的性能会随着上下文不断增大而下降,这种方式也能减少我们对 /compact/clear 这类命令的依赖。保持主上下文精简,有助于维持性能和稳定性。

总结一下就是:主 agent 给 subagent 发送一个输入;subagent 完成工作;然后只返回一个输出给主 agent。这是一种非常有效的上下文压缩方式,同时又不耽误工作继续推进。

上下文窗口在实践中的表现

为了更直观地理解这一点,我们可以观察:随着与 Claude Code 的对话推进,context window 是怎么逐渐变大的。大语言模型都有 token 上限,我们最终都会受限于能发送多少 token

image.png

图 7.9 —— 多轮对话中 context window 的增长

你可以选择一个 200K token 的模型,或者 100 万 token,甚至未来可能还有 200 万、1000 万 token 的模型。但无论窗口多大,它始终是有限的。而达到这个极限,是我们应该尽量避免的。一旦超过上限,请求就会失败。就算还没超限,更大的上下文也会带来更高成本,因为每个 token 都是有价格的,而且上下文越大,响应越慢,延迟也会增加。

更重要的是,当我们逐渐逼近上限时,就会越来越容易出现上下文污染。上下文里会积累越来越多已经和当前任务无关的信息,结果质量也随之下降。这显然不是理想的工作方式。所以,我们始终希望让上下文尽量保持精简。

在与 Claude Code 的交互中,每一轮、每一条消息都会消耗 token,并继续往 context window 里塞东西。比如,第一轮可能加了 10K token,第二轮可能把上下文抬到 30K,到第五轮时,context 可能已经涨到 100K。

如果只使用一个 Claude Code 实例,迟早会走到这样一个点:累积上下文已经大到很难有效管理。这时,你要么得用 /compact 压缩上下文,要么直接清空重来,或者干脆打开一个新的 Claude Code 实例重新开始。这就是在有界上下文窗口下工作的自然结果。

这里的关键点在于:上下文是有限的,一个单独 Claude Code 实例不可能无限期承载一切。上下文上限会直接约束我们如何与 Claude Code 交互。

subagent 提供了一个优雅的绕行方式。每次调用 subagent,它都运行在自己的 context window 里。subagent 所消耗的 token 不会记到主 Claude agent 的上下文账上

image.png

图 7.10 —— 通过把工作卸载给 subagent 来保护主上下文

执行结束后,subagent 只返回一个经过压缩的响应。这个响应本身可能有 15K 或 20K token,也可能包含总结、代码变更等内容。关键在于:subagent 的完整内部上下文不会全部累积进主对话里

这种方式能够让主上下文保持精简,同时又允许真正的大量工作发生。每个 subagent 都像一个带有独立 system prompt 的“侧链”,专门服务某个特定任务。由于它具备这种专门化能力,subagent 往往能比主 agent 单独处理时做得更好。

这种把上下文和职责拆开的方式,就是 subagent 的核心思想。概念本身很简单,但威力非常大。

到这里,我们主要聚焦在:subagent 如何隔离上下文,并把压缩后的结果返回给主 agent。下一步,就是继续看:我们如何更有意识地去塑造 subagent 的行为。

示例:创建一个 Mermaid Diagram Subagent

下面我们会通过一个具体例子,仔细观察 subagent 的 system prompt 和配置,并看看当我们修改这些内容时,执行流和输出会发生怎样的变化。

创建 Subagent 配置

开启一个新的 Claude Code 会话。首先,调整输出风格,并查看可用 agent。这个 agent 的目标,是根据文本输入生成 Mermaid 图。因此,我们需要新建一个 agent。使用 /agents 命令,选择项目级 agent,并通过 Claude 直接生成它。

Create new agent
 Describe what this agent should do and when it should be used (be comprehensive for best results)
help me write a mermaid diagram agent which is going to receive my input and create a mermaid diagram out of it

Mermaid 是一个基于 JavaScript 的图表与流程图工具,它允许我们用简洁、可读的语法来定义图形(https://mermaid.live/)。这些图可以在 GitHub 等文档平台中非常清晰地被渲染出来。它支持多种图类型,而它的语法本身也被设计得非常轻量。

Claude Code 会根据这段输入为新的 subagent 生成元数据。这个阶段,我们的目标并不是一步就做出“最强版本的 agent”,而是观察 Claude Code 主 agent 与 subagent 之间是如何交互的:它们如何通信、主 agent 会传什么输入进去、最后返回什么输出。现在的 prompt 故意保持基础,后面还会继续 refinement。

工具选择与上下文考量

生成完 subagent 之后,下一步要选它能使用哪些工具:

image.png

图 7.11 —— 为 Mermaid diagram subagent 选择工具

这里我们启用了:

  • 只读工具
  • 编辑工具
  • 执行工具

但要注意:这其实比这个 subagent 真正需要的工具多了。

Mermaid 图生成器的唯一职责,是根据文本输入产出 Mermaid 语法。它并不需要执行 bash 这种执行工具,也不需要写文件权限。把这些额外能力都授予给它,其实是没必要的。

这就是一个典型的 tool pollution(工具污染) 例子:一个 subagent 被赋予了自己根本不需要的工具。每一个工具定义都会给 subagent 的 context window 增加额外 token。因此,工具配置过度不仅会让上下文变大,也会引入额外开销;同时还会在安全层面扩大暴露面,让 agent 获得超出自己职责范围的能力。

在实践中,subagent 应该只被授予完成任务所需的最小工具集合。这依然是在贯彻最小权限原则:组件应该只拥有完成自身任务的最低权限,而不是更多。过度配置工具,不管从上下文效率还是安全性角度,都是应该避免的。

选完工具后,我们可以给它选 Sonnet 模型,并指定一个颜色。最终配置保存后,会生成一个名为 mermaid-diagram-generator.md 的文件。

image.png

图 7.12 —— 完成并保存 Mermaid diagram subagent 配置

理解 Subagent 配置

现在,我们来查看刚生成出来的文件。里面包含了完整的 subagent 定义。这个 subagent 的名字是 mermaid-diagram-generator。你还会发现:有一段 description 被附加进了 Claude Code 主 agent 的 system prompt 中。

---
name: mermaid-diagram-generator
description: Use this agent when you need to convert textual descriptions, requirements, processes, or concepts into visual Mermaid diagrams. Examples include: <example>Context: User wants to visualize a software architecture flow. user: 'I have a web app with a React frontend that calls a Node.js API, which then queries a PostgreSQL database and caches results in Redis' assistant: 'I'll use the mermaid-diagram-generator agent to create a visual diagram of this architecture' <commentary>Since the user is describing a system architecture, use the mermaid-diagram-generator agent to create an appropriate Mermaid diagram.</commentary></example> <example>Context: User needs to document a business process. user: 'Can you help me create a flowchart for our customer onboarding process? It starts with registration, then email verification, profile setup, and finally account activation' assistant: 'I'll use the mermaid-diagram-generator agent to create a flowchart diagram for your onboarding process' <commentary>The user is describing a sequential process, so use the mermaid-diagram-generator agent to create a flowchart.</commentary></example> The main agent should always and always simpilfy the concept to the GIST. Also write some asci drawing to the subagent representing the concept.
tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, BashOutput, KillBash, Edit, MultiEdit, Write, NotebookEdit, Bash
model: sonnet
color: cyan
---

这个 description 决定了:主 agent 眼里有哪些 subagent 可用,以及它会在什么情况下调用某个 subagent。换句话说,我们可以通过这个字段来“引导主 agent 如何做 delegation”。

description 会先给出一个高层概述,说明 agent 是做什么的,然后再给出一系列用户输入示例,告诉主 agent 什么样的请求应该触发这个 subagent。在这里,这个 agent 的职责是把文本描述、需求、流程和概念,转换成可视化的 Mermaid 图。高层概述和示例共同帮助主 agent 判断是否应该把任务交给它。

更关键的是,description 不只是决定“什么时候调用 subagent”,它还会影响主 agent 是怎么去给 subagent 下 Prompt 的。由于 subagent 运行在隔离上下文中,它唯一拿到的信息就是主 agent 生成的那段 prompt。所以,只要我们仔细设计 description,就可以间接控制这段 prompt 的结构、格式和内容。能够影响主 agent 是如何 prompt subagent 的,这其实是 Claude Code 非常强大的一个能力点。

在 YAML frontmatter 下面,我们定义的是 subagent 的内部逻辑。这部分就是 subagent 的 system prompt,它包含了专门为这个任务量身定制的指令。它可以写成逐步流程,也可以定义 subagent 最终该如何组织输出格式。

当一个 subagent 完成执行后,它自己的内部上下文会被清掉,只保留一条返回给主 agent 的响应。也就是说,这个返回结果是唯一被保留下来的产物。而我们其实也可以主动去塑造:这个返回结果应该包含什么、采用什么格式,才能让主 agent 更容易处理它。

调用这个 Subagent

配置完成后,我们来真正调用一次这个 subagent:请求它为一个 retrieval-augmented generation(RAG) 流程画一张 Mermaid 图。主 agent 会把这个请求委派给 Mermaid diagram subagent,并生成类似如下过程:

image.png

图 7.13 —— 调用 Mermaid subagent

通过检查这次调用过程,我们可以看到,传给 subagent 的 prompt 是什么。这个 prompt 要求 subagent 生成一张完整的 Mermaid 图,用来展示一个典型 RAG 流程,涵盖向量数据库、embedding 模型、文档切分、检索、查询处理以及 LLM 生成器等组件,同时还要求它选用适当的 Mermaid 图类型,并保持标签清晰、逻辑流程明确。

一旦被调用,subagent 就会在自己的独立上下文中执行。执行完成后,Claude Code 会自动把 subagent 的最终响应转发回主 agent。通常这个响应会同时包含 Mermaid 图语法,以及对图的文字说明。

评估结果

我们把 subagent 生成出的 Mermaid 语法复制出来,并用支持 Mermaid 的绘图工具渲染。这里我用的是 Excalidrawhttps://excalidraw.com),它是免费的。我只是简单地把 Mermaid 语法粘进去,然后按下 Enter。

image.png

图 7.14 —— 在 Excalidraw 中渲染生成出来的 Mermaid 图

如你所见,图确实被成功生成了,而且它确实把 RAG 架构可视化出来了。

不过,生成的结果并不一定总是让人满意。图可能还是不够直观,结构不够清晰,甚至让人一眼看上去有点压迫感。即便我们本身已经很熟悉 RAG,也未必能立刻看清各组件是怎么互相作用的。

这就说明:当前 subagent 的配置还需要 refinement。接下来,我们会去微调 subagent 的定义,争取得到更清晰、更有结构感的结果。具体做法,就是去修改那份描述 subagent 的 Markdown 文件。

精炼 Subagent Description

我们先回到 subagent 配置文件,在 description 中再加一些额外指令。由于当前目标是让图中细节尽量简化,所以我加上了这样一句话:

The main agent should always and always simplify the concept to the GIST. Also write some ascii drawing to the subagent representing the concept.

这里的意思是:主 agent 在给 subagent 构造 prompt 时,应该尽可能把概念压缩到核心 gist,并且最好先提供一个 ASCII 草图来帮助它理解概念。

我们还加了一句额外要求,希望它更强调“视觉表达本身”,弱化对代码形式的关注。这个阶段,我们关注的不是 subagent 内部怎么干,而是先继续影响主 agent 如何构造发给 subagent 的 prompt。通过修改 description 字段,我们就能够间接操控主 agent 对 subagent 的 prompting 方式。

实际上,我们甚至还可以在这里让主 agent 做一些额外动作,比如去发 API 调用。正因为这层能力非常强,所以它也会带来安全风险。

因为这个 description 会被附加进 Claude Code 主 agent 的 system prompt 中,所以如果你从一个不可信来源复制了某个 subagent,它的 description 完全可能夹带恶意指令。一个带有恶意 description 的 subagent,甚至可能诱导主 agent 在本地机器上执行一些你根本不想发生的动作。这恰恰说明:description 级别的控制权有多强,也说明它的风险有多真实。

观察更新后的 Prompt Flow

为了验证这些更新是否真的生效,我们保存文件,重新打开 Claude Code,再次发出一个类似请求:让它为一个 RAG 流程画 Mermaid 图。

image.png

图 7.15 —— 更新后的 prompt flow,展示 gist 级简化指令如何传递给 subagent

检查发送给 subagent 的 prompt,我们会发现其中已经包含了“gist 级简化”的要求。这就说明:主 agent 已经被我们更新后的 description 成功影响到了。新的请求里包含了一个简化后的概念表达,而这也正是被注入到 subagent 中的唯一上下文。

这段 prompt 就是 subagent 拿到的全部完整上下文。我们此时的预期是:这种 refinement 会提升 subagent 的执行表现,也会改善它的输出质量。

评估更新后的 Subagent 输出

执行完成后,我们再去检查生成出来的流程图。相比前一个版本,这次的结构应该会更清晰,索引和检索部分更容易分辨,整体流程也更容易一眼看懂:

image.png

图 7.16 —— 更新配置后生成的、更精炼的 RAG 流程图

新的图明显更简单,步骤更少,因此也更容易理解。

不过,这里还有一个问题:subagent 返回给主 agent 的最终响应里,并不会直接包含 Mermaid 代码本身。只有当你展开 subagent 输出并手工复制时,才能看到那段代码。主线程里默认看到的,更多是对它完成工作的一个摘要:

image.png

图 7.17 —— Subagent 返回的是摘要,而不是原始 Mermaid 代码

这就暴露了当前 subagent 配置的一个限制:它返回的是总结,而不是实际图代码,因此还没有真正完全达成我们的目标。subagent 会清掉自己的内部上下文,只返回一条响应;而这条响应里并没有包含我们最想保留的核心产物。这个行为需要被修正,而书里后面会在 Refining the Subagent Output 小节中处理这个问题。

到目前为止,我们一直聚焦在“如何操控主 agent 发给 subagent 的 prompt”。这确实已经带来了结果改善,但单靠这一层还不够。

下一步,我们要进一步往里走,不只影响 prompt 形状,而是开始直接操控 subagent 自己的内部逻辑与执行流。只有这样,我们才能对它“如何执行任务”这件事进行更细粒度控制,并继续提升输出质量。

精炼 Subagent 输出

接下来,我们需要修改 subagent 配置,明确要求它在返回结果时只返回真正的 diagram 本体,不要任何额外 fluff。这会成为这个 agent 的第七步,也是最后一步。这里的目标,是影响它把结果返回给主 agent 时的输出格式。

image.png

图 7.18 —— 更新 subagent,使其只返回 Mermaid 图本身,而不附带额外文本

我还额外加入了一个“第 0 步”,要求 subagent 先检查网络上是否已经存在某种可直接参考的预制图,用它来启发自己的生成过程。

image.png

图 7.19 —— 添加一个第 0 步:先检查是否已有现成 diagram 可供参考

这里提到的是 diagram,而不是专指 Mermaid diagram。这之所以可行,是因为 subagent 已经有 web search 工具可用。

如果你希望输出保持非常简洁,那么这件事就必须明确写进 description 中,并且反复提醒它:保持 minimal。

image.png

图 7.20 —— 更新 subagent 的 system prompt,以强制输出更简单、更极简

这一部分 Markdown 定义的是 subagent 的内部逻辑,它只作用于 subagent 自己,并不会影响主 agent。

完成这些修改之后,保存配置。

观察更新后的执行流

现在再次发出同样的请求,生成 RAG 的 Mermaid 图。任务照样会被委派给 Mermaid diagram subagent。

通过查看调用细节,我们可以看到主 agent 传进去的完整 prompt。这段 prompt 就是 subagent 执行时所拥有的全部上下文。

image.png

图 7.21 —— 检查主 agent 传给 subagent 的完整 prompt

搜索过程会花一点时间,但最终,我们应该能确认:我们已经成功影响了 subagent 的执行流。它做的第一件事,就是按指示先进行 Web 搜索。

执行结束之后,subagent 依然返回的是一个摘要,而不是原始 diagram code。这是当前 agent harness 暴露 subagent 响应方式的一个限制。完整 Mermaid 语法其实已经在内部被生成出来了,只是不会直接显示在主线程中。要查看真正的图代码,你仍然需要展开 subagent 输出并手工复制,然后把 Mermaid 语法粘贴到绘图工具里进行渲染。

image.png

图 7.22 —— 在 Excalidraw 中渲染时出现的 Mermaid 解析错误

在渲染过程中,还出现了一个解析错误,问题出在某个 process box 的样式上。解决方式很简单:把样式去掉。这样处理之后,图就能成功渲染。

image.png

图 7.23 —— 去掉 Mermaid 样式问题后正确渲染的 RAG 架构图

这一次渲染出来的图,比之前明显规整得多。图中可以清楚看到两条不同的流:

  • 一条是 retrieval path(检索路径)
  • 另一条是 indexing path(索引路径)

在 retrieval 这一侧,流程展示的是:用户查询先被 embedding,然后去向量库里做相似度搜索,取回 top K 文档,再对 prompt 进行增强。检索到的上下文会被附加到 prompt 中,然后再发给语言模型。
在 indexing 这一侧,流程展示的是:文档被加载、预处理、切分、embedding,最后写入向量数据库。

整体来看,这个结果明显比之前更好:图更简单、更结构化,也更适合一眼扫过去就理解。

配置更新完成后,我们把这些改动提交到仓库中。commit 中包含了更新后的 subagent 定义,以及相关修改文件。

push 之后,这份更新后的配置就会出现在仓库的 subagents 分支中。

到这一步,我们已经看过了 subagent 的核心机制:它们如何被创建、上下文如何在主 agent 与 subagent 之间流动,以及怎样通过配置和 system prompt 去塑造它们的行为。我们也通过动手示例看到了:无论是修改 description 来影响主 agent,还是直接修改 subagent 内部逻辑,都会实际改变执行过程与输出结果。

但前面所有例子都只涉及单个 subagent。而这种方法真正的威力,要等到多个 subagent 被同时 spawn 并并行运行时,才会真正显现。通过并发执行任务,我们可以同时探索多种实现方案,并更高效地扩展工程工作流。接下来,我们就从单 agent 委派,进入到协调式并行执行。

通过并发 Subagents 进行扩展

这一节的实现,基于 IndieDevDanInfinite Agentic Loop 仓库:https://github.com/disler/infinite-agentic-loop。如果你对 agentic coding pattern 和 multi-agent workflow 感兴趣,他的工作非常值得研究。他会持续分享很多 agentic development 的实践经验,更多内容也可以在 agenticengineer.com 上找到。

这一节里,我们会探索如何 spawn 出多个并发工作的 subagent,共同去实现一个 feature。每个 subagent 都会给出自己的实现,然后我们再统一评估这些不同版本,并挑出最强的那个。它展示的是一种软件工程模型:不是只生成一个实现,而是并行生成多个实现,再做筛选后集成。

当然,这种方式在 token 消耗上会非常昂贵。多个 subagent 一起跑时,每个都有自己的上下文和执行过程,因此都会各自独立消耗 token。每个 agent 不仅生成代码,还可能进行评估和进一步推理,所以整体 token 消耗会迅速放大。

这里我故意不给出具体成本估算。因为定价经常变化,而且 token 用量会随着代码库大小、agent 数量和任务复杂度大幅波动。如果你要用这种模式,一定要仔细监控 usage。

本节演示所使用的实现,依旧基于 IndieDevDan 的仓库 Infinite Agentic Loophttps://github.com/disler/infinite-agentic-loop)。我们会以它为基础,来运行本节中的并发 subagent。IndieDevDan 本人是一位专注 agentic coding 内容的 YouTuber,这个仓库正是本节并发子智能体流程的基础。仓库本身和相关视频讨论,都在本章中作为参考资料被提及。

搭建环境

这一节我们继续在 Project Hookhub 项目中操作。先把仓库 clone 到本地,然后进入工作目录:

git clone https://github.com/PacktPublishing/Agentic-Coding-with-Claude-Code

然后进入 Claude Code crash course 目录,切换到 project/hookhub 分支。在 commit 列表中,我们会选取如下这条 commit:

Merge pull request #1 from emarco177/claude/add-anthropic-footer-01NXAnJSjYR7cx3t5Ag9HzAE

这就是本节所使用的基线 commit。复制它的 commit hash,并执行:

git checkout -b project/hookhub<commit-hash>

你应该会看到类似下面的输出:

image.png

图 7.24 —— 在 Cursor 中打开的 HookHub 项目,位于正确分支

确认我们已经在正确分支上之后,进入 hookhub 目录。此时可以打开已有的 Next.js 项目。

安装依赖

项目打开后,先安装依赖:

npm install

安装过程中,如果发现有漏洞,再执行:

npm audit fix --force

等所有关键漏洞都修复完后,再启动开发服务器:

npm run dev

这样,使用 Anthropic 风格主题的 HookHub 应用就会成功跑起来。到这里,环境已经准备就绪:

image.png

图 7.25 —— 成功运行中的 HookHub 应用(Anthropic 主题)

现在 setup 已经完成,可以进入并行编排多个 agent 的阶段了。

The Infinite Slash Command

接下来,我们关注 agent 解码部分。在 Infinite Agentic Loop 仓库中,有一个 slash command 叫做 infinite

这个命令接收三个输入:

  • 一个 spec file
  • 一个输出目录
  • 一个数字

它会先读取 spec file,理解我们希望实现什么功能;然后根据这个数字 spawn 出对应数量的 agent;这些 agent 会并发工作;每个 agent 都会生成一个独立 artifact,并把结果写进输出目录。

这个命令既可以以一个“小批量 agent”的轻量模式运行,也被设计成可以扩展到更大规模,甚至逼近“无限循环式并发生成”的模式。

这一节里,我们先使用轻量版。

在这个例子里,我们让 subagents 去实现 Hero 组件的不同变体

重构 Hero 组件

首先,创建一个新的目录 specs。这个目录将用于保存所有 spec 文件。

此时,应用里已经有 components 目录,里面有 footer 和 hook card,但还没有一个专门独立的 Hero 组件。当前 Hero 的实现还直接写在 page.ts 中。

在创建 spec 之前,我们先把 page.ts 里的 Hero 逻辑抽出来,放到 components 目录下,以便先把仓库组织得更干净一些。这里我用的 prompt 是:

Hi, can you please take the implementation from page.ts? There is a hero implementation there.
I want to create a new component from it under the components directory, just to organize the code a little bit.

执行后,Hero 实现会从 page.ts 中抽出,并在 components 目录下创建一个新的 hero.tsx 文件。与此同时,page.tsx 中的 import 也会被改掉,改为引用这个新组件。

image.png

图 7.26 —— 将 Hero 区块抽离成一个单独的 hero.tsx 组件

接着,我们再用下面这个 prompt,把 hero.tsx 挪到 components 下一个单独的 hero 目录中:

Can you please also move the hero.tsx file into a hero directory under components?
Don't forget to explicitly tag the file during this operation to ensure that the correct file is modified.

完成后,原本 page.ts 中的 Hero 实现就会被移除,项目结构也就演化成了“Hero 组件放在独立目录中”的形态。

此时,我们已经创建好了一个 heros 目录。这个目录的作用,是用来存放之后多个 subagent 生成出来的输出 artifact。到这里,项目结构已经被整理干净,可以进入 specification 阶段。

基于 Hero 文件生成 Spec File

接下来,请求 Claude 基于 hero.tsx 生成一份 spec file,使用如下 prompt:

Can you please review the hero.tsx file and create from it a spec file describing what this component should do, what its goals are, and specific guidelines, because I'm going to implement different variations of this component. @../src/components/heros/Hero.ts

这条 prompt 包含了以下要求:

  • 审查 hero.tsx
  • 生成一份 spec,描述这个组件的职责、目标和具体指导原则
  • 把生成出的 spec 文件放进 specs 目录(并显式 tag 文件)

Claude 会先分析 Hero 实现,然后生成规格说明文件。

image.png

图 7.27 —— 生成出的 hero.spec.md,用于定义 Hero 组件规格

这样,一个新文件就被创建出来了,其中包含完整的 Hero 组件 specification。这个 Hero 组件的职责,是作为 HookHub 的主 landing section,第一时间向用户传达产品价值主张、目标,以及页面背景层次。

接下来,在本地创建一个 .claude 目录。因为这是一个全新的分支,而 Claude 还没有在这份仓库副本上初始化过,所以这个目录此时还不存在。

然后在里面再添加一个 commands 文件夹。接着,从 Infinite Agentic Loop 仓库里,把 infinite.md 这个 slash command 拷贝进来。

这个 command 负责真正编排多个 subagent 的并发执行。

在当前阶段,我们先不去分析它的内部实现。眼下重点是:先在实践中把它跑起来。

运行 Infinite Slash Command

先退出 Claude,再重新启动,这样新加入的 slash command 才会被加载。Claude 初始化完成后,你就可以看到 /infinite 命令已经可用。

根据仓库说明,这个命令需要三个输入:

  • 一个 spec file:在我们的例子里是 hero.spec
  • 一个输出目录:在我们的例子里是 heros
  • 一个 count:这里我们用 6 个 agent

按如下方式执行这个命令:

>/infinite @../specs/hero.spec.md @../src/components/heros/

主 agent 会先读取 spec file。一旦读完,它就拥有了当前要实现内容的完整上下文。然后 Claude Code 会启动 6 个并行 subagents,去生成不同版本的 Hero。你会看到类似下面这样的任务:

image.png

图 7.28 —— 并行 subagent 任务:生成多个 Hero 组件变体

待办列表会不断更新,subagent 也会开始并行运行。

再次提醒一下,这种 workflow 成本不低。每个 agent 都是独立跑的,都要生成自己的代码,甚至还可能自测。如果你不是用 max 模式,而是 Anthropic API key,那么就一定要盯住 token usage,因为这个流程会消耗非常多 token。

每个 subagent 都是在本地机器上执行的。如果你把 agent 数量继续放大,比如开到 100,那么单机就不够了,届时就需要扩展到多机器执行。Claude 的云端能力可以用于这种扩展。随着 agent 一个个完成,它们会开始往 heros 目录中写入输出文件。

如果本地环境在文件创建上遇到问题,Claude Code 也会尝试自动恢复。

等到文件创建权限问题解决后,heros 目录中就会逐渐出现多个 hero 文件。最终,6 个版本都会被生成出来。

image.png

图 7.29 —— 在 heros 目录中生成出的多个 Hero 实现文件

到这一步,我们已经拥有了 6 个不同的 Hero 实现。

现在,发出一个新的 prompt:

Take all the hero implementations and show them on the main landing page one after another so we can compare them and choose the best one.

这是一条全新的 prompt,不属于 slash command 本身。这里要记住的是:每个 subagent 都运行在自己的隔离上下文中。它们彼此之间并不感知对方,都像从白纸开始一样启动。这种方式对上下文管理非常有利。

主页面接下来会被更新,把每个 Hero 变体都 import 进来,然后顺序渲染出来。

page.tsx 中预期发生的变化包括:

  • heros 目录引入所有 hero
  • 在页面布局中逐个渲染它们

检查 diff 后,我们会确认:

  • 新 imports 已经加上
  • 每个 hero 都按顺序渲染了出来

此时,应用会显示这些不同版本的 Hero:

  • Minimal
  • Centered
  • Waveform
  • Particles
  • Terminal
  • Gradient mesh

每一种版本都能在 landing page 上看到。

在这些版本里,我们最终选择 terminal hero 作为最佳实现。

在进一步精炼之前,先清理上下文

继续下一步之前,先检查一下 context window。由于前面做了很多操作,它此时通常已经变得非常臃肿。

我们先清空上下文,然后再发出一个新 prompt:

Keep only the terminal hero in page.tsx.
Remove all other heroes from the main landing page.
Leave all hero files under the heroes directory untouched.

这里,page.tsxheroes 目录都需要被显式 tag。

因为现在上下文已经被清理干净,所以执行速度会更快。

最终,主页面会被更新成只渲染 terminal hero。其他 Hero 组件则依然保存在 heros 目录中,页面本身也重新变得简洁。

接下来就可以提交这些改动。先执行:

git add
git status

然后请求 Claude 帮我们写一条 commit message,内容需要同时涵盖:

  • 主页面 Hero 的变更
  • 新增了一个用于运行多个 subagent 的 slash command

我使用的 prompt 是:

Hi, can you please create a commit message about changing the hero in the main page? And please add that we also added a slash command for running multiple subagents.

Claude 会审查 diff,然后生成 commit message。commit 会被创建并 push。

刷新仓库之后,你会看到一条类似这样的 commit message:

Add hero component system and infinite agent slash command

到目前为止我们做了什么

我们通过 /infinite slash command 并行 spawn 出多个 subagent。每个 subagent 各自独立实现一个 variation。等全部实现生成后,我们把它们并排渲染到页面上,逐个观察、比较,最后选出最佳版本。

这种方法实际上是在用算力换探索空间。你愿意投入多少 token,就决定了你能承受多大规模的并行方案搜索。

不过,我们到现在还没有拆开看它到底是怎么在底层工作的。这个问题,会在下一节展开。

如果你对 slash command 内部实现本身感兴趣,可以继续去看 Infinite Agentic Loop 仓库,以及 IndieDevDan 配套的 YouTube 视频。

Infinite Prompt

这一节里,我们来拆解 infinite.md 文件,以及那个 spawn 出一大批 subagent 的 prompt。本质上,这其实是一个 高阶 prompt(high-order prompt) 。它接收一个 prompt 作为输入,然后再动态生成更多 prompt。

你可以把它理解成一种 meta-prompting,很像函数式编程里的高阶函数:函数接收函数作为参数,也可以返回函数作为返回值。这里发生的是同样的事,只不过对象从函数变成了 prompt。Infinite Agentic Loop 里的这个 command,正是在做这种事。

这个 prompt 一开始会写:

Think deeply about this infinite generation task. You are about to embark on a sophisticated iterative creation process.

这里的 Think deeply 指令,是为了激活模型的更深层推理能力。注意,这是发给主 agent的 prompt,也就是发给 Claude Code 主 agent 的。

在 Variables 段落中,prompt 会定义这样一行:

spec_file: ARGUMENTSoutputdir:ARGUMENTS output_dir: ARGUMENTS count: $ARGUMENTS

这行声明了三个变量:spec_fileoutput_dircount。每个变量一开始都临时绑定到 $ARGUMENTS 占位符。

/infinite slash command 被调用时,整串参数会作为 $ARGUMENTS 被送进这个 prompt。于是你在 slash command 里提供的值,会被代入这一行中,因此你有时会看到同样的输入被重复出现好几次。这些重复值,本质上都是 slash command 本身收到的输入。

这个 prompt 里面还包含了解析逻辑。整个 prompt——连同 slash command 调用时带上的参数——都会一起发送给 Claude Code 的主 agent。prompt 中会明确告诉主 agent,应该怎样去解析这些输入。

解析逻辑会定义:

  • spec_file:Markdown 规格文件的路径
  • output_dir:用来保存迭代结果的目录
  • count:要生成的迭代次数,可能是 1..N,也可能是 "infinite"

这里的 parsing 完全是由主 agent 动态完成的,并没有单独的代码去解析。也就是说,每次命令执行时,输入都是由 LLM 现时解析的。

变量定义并解析完之后,接下来执行会分成几个阶段。

Phase 1:Specification Analysis

第一阶段是 规格分析。主 agent 会被指示去读取并深入理解位于 spec_file 的那份规格文件,也就是前面解析出来的路径。

spec 文件会定义:

  • 要生成什么类型的内容
  • 格式和结构要求
  • 具体参数或约束条件
  • 不同迭代之间应该如何演化

prompt 会要求主 agent 仔细思考 spec 的真正意图,以及每一个 iteration 应该如何在前一个基础上发展。

在前面的 Hero 示例里,其实并没有在 spec 中写进“上一轮如何演化到下一轮”,所以那时并没有真正出现版本间迭代演化。如果你想实现这一点,这个 prompt 其实是支持的。

也就是说,主 agent 的第一项任务就是:读 spec file,理解我们到底想做什么。

Phase 2:Output Directory Reconnaissance

第二阶段是 输出目录侦察。主 agent 会被要求彻底分析 output_dir,理解当前输出目录中已经存在什么内容。

这一阶段会包括:

  • 列出所有已有文件以及它们的命名模式
  • 找出当前已经存在的最高迭代编号
  • 分析已有迭代之间的演化关系
  • 理解之前生成轨迹的走向
  • 判断新一轮生成有哪些空白点或机会点

在前面的例子里,我们并没有用编号,而是用不同的 style 文件名。

这一步的本质,就是让主 agent 先看看:哪些工作已经做过了。

Phase 3:Iteration Strategy

第三阶段是 迭代策略制定。基于对 spec 的分析和已有 iteration 的理解,主 agent 会被要求去做这些事:

  • 决定当前应该从哪个 iteration 编号或文件名开始
  • 规划如何保证每个 iteration 都有独特性,并且能体现演化关系
  • 思考如何在“继承已有工作”的同时保持新颖性
  • 如果 count"infinite",则要为持续生成做准备,一直到上下文上限逼近为止

这一阶段仍然属于规划阶段。

Phase 4:Parallel Agent Coordination

第四阶段正式进入 subagent 并行执行。主 agent 会被要求部署多个 subagent,并让它们并行生成多个 iteration,以获得更高效率与更丰富的创意多样性。

分发策略被定义为:

  • 如果数量在 1–5 之间:全部同时启动
  • 如果数量在 6–20 之间:按 5 个一批启动,以便管理协调
  • 如果是 "infinite":按 3–5 个一波发起,同时监控上下文,并持续启动新一波

Agent Assignment Protocol

主 agent 会使用 Claude Code 的 task 工具去 spawn subagent。prompt 会进一步规定:主 agent 应该如何构造传给 subagent 的那段 prompt。

每个 subagent 实际上只接收一条 prompt,在上下文隔离环境中运行,并最终只返回一条消息给主 agent。

每个 subagent 会拿到这些输入:

  • Spec context:对整个 specification 的完整分析
  • Directory snapshot:在启动那一刻,output_dir 当前的状态快照
  • Iteration assignment:具体分配给它的 iteration 编号、起始编号,以及 agent index
  • Uniqueness directive:显式要求它不要和已有 iteration 重复
  • Quality standards:来自 specification 的详细质量要求

因为我们把 directory snapshot 也作为输入带了进去,所以 subagent 会知道:目前已经生成过什么。这有助于避免重复点子和重复实现。

在前面的例子里,我们没有用编号,因此 iteration assignment 更多映射成了不同文件名。

Subagent Task Structure

这个 prompt 还会定义真正传给 subagent 的 task 结构。

任务会被组织成类似下面这种形式:

generate iteration [NUMBER] for [SPEC_FILE] in [OUTPUT_DIR]
you are subagent [X] generating iteration [NUMBER]

每个 subagent prompt 会包含这些上下文:

  • Specification(完整 spec 分析)
  • Existing iterations(对当前 output_dir 内容的总结)
  • Your iteration number(你的编号)
  • Assigned creative direction(分配给你的创意方向)
  • Requirements(约束要求)

prompt 中还会包含类似如下指令:

  • 彻底读懂 specification
  • 分析已有 iteration,确保输出是独特的
  • ……以及其他更细节的执行要求

Parallel Execution Management

之后,prompt 会回到主 agent 的执行管理逻辑。

主 agent 会被要求:

  • 同时启动所有分配好的 subagent
  • 监控每个 agent 的进度与完成情况
  • 如果有 agent 失败,重新分配 iteration 编号
  • 确保不会生成重复 iteration 编号
  • 收集并验证所有完成的 iteration

这就是整个高阶 prompt 的核心:它自己接收一个 prompt 作为输入,然后生成许多 prompt 作为输出,因为每个 subagent 最终都拿到了一份不同的 prompt。

一个 prompt,生成很多 prompt。这个 command 还内建了关于“无限运行”、上下文优化和执行原则的指导逻辑,进一步给主 agent 增加了上下文。

从这个意义上说,这确实是一个非常高层的 prompt。

站在 prompt engineering 的角度看,“让一个 prompt 去接收 prompt 作为输入,再生成 prompt 作为输出”这件事,本身就非常有创造性。对我来说,第一次看到这个思路的时候是很震撼的。也确实应该把 credit 给到 IndieDevDan,他把这个方向想得很深。

我个人也认为,agentic coding 和 software engineering 很可能正在往这种 prompt 方向演进,因为这类 meta prompt 已经几乎承担了工作流里“编排一切”的角色。

总结

在本章中,我们从零开始系统地梳理了 Claude Code subagents 的概念。我们先理解了 subagent 是什么,以及为什么上下文隔离会成为一个如此关键的设计决策。我们看到,与其让主对话无限膨胀、被上下文污染,不如让 subagent 在自己的 context window 中运行,并只返回一个压缩后的结果。这样既能控制 token 使用,又能在项目变大时维持性能。

随后,我们配置了自己的 subagent,观察了 description 如何影响它被调用的时机,也看到 system prompt 与工具选择如何直接塑造其行为。通过一系列实操示例,我们既操控了主 agent 发给 subagent 的 prompt,也直接修改了 subagent 自身的内部逻辑。最后,我们又通过 Infinite Agentic Loop 模式,把执行规模扩展到了并发 subagent:一个高阶 prompt 动态生成多个 subagent prompt,并让它们并行运行。

到这一步,我们应该已经清楚理解了:上下文如何在 agent 之间流动、subagent 是如何被编排起来的,以及这种方法如何以结构化、可控的方式去放大工程执行能力。

在下一章中,我们会继续看 output styles(输出风格) 如何影响 Claude Code 的响应,同时还会讨论如何创建和限定自定义 styles、如何使用 YAML 这类结构化格式,以及如何在 style 定义中自动化行为。