Skip to content

04 子智能体

⭐ 核心路径 — 本课是 Agent Harness 工程的第四块基石,属于核心路径:[[01-agent-loop/01-智能体循环|s01]] → [[02-tool-use/02-工具使用|s02]] → [[03-todo-write/03-待办写入|s03]] → s04 → s05 → s07 → s09


"大任务拆小,每个小任务干净的上下文" — 子智能体用独立 messages[],不污染主对话。

Harness 层:上下文隔离 — 守护模型的思维清晰度。

问题:上下文膨胀

智能体工作越久,messages 数组越胖。每次读文件、跑命令的输出都永久留在上下文里。考虑这个场景:

父智能体问"这个项目用什么测试框架?",子任务需要读 5 个文件才能回答。但父智能体只需要一个词:"pytest"

然而在没有子智能体的架构中,这 5 个文件的全部内容、tool_result 的详细输出、路径尝试的历史记录——全都堆积在父智能体的消息历史中。随着对话进行:

  • 上下文窗口被无关细节吞噬
  • 模型注意力被稀释
  • 关键决策依据被埋没在海量日志中
  • 每次 API 调用成本线性增长

这正对应 [[01-agent-loop/01-智能体循环|s01 智能体循环]] 中提到的循环代价:循环跑得越多,上下文越脏,下一条推理越慢越贵。

解决方案:子智能体隔离

子智能体的核心思想极其简单:为子任务创建一个全新的、干净的上下文环境,任务完成后丢弃。

Parent agent                     Subagent
+------------------+             +------------------+
| messages=[...]   |             | messages=[]      | <-- fresh
|                  |  dispatch   |                  |
| tool: task       | ----------> | while tool_use:  |
|   prompt="..."   |             |   call tools     |
|                  |  summary    |   append results |
|   result = "..." | <---------- | return last text |
+------------------+             +------------------+

Parent context stays clean. Subagent context is discarded.

这解决了 [[03-todo-write/03-待办写入|s03 待办写入]] 无法处理的场景:待办任务是规划层面的"做什么",而子智能体是执行层面的"怎么做的过程数据不污染主脑"。

子智能体的价值

  1. 上下文隔离:子智能体的所有 tool_use → tool_result 循环全部在隔离环境中完成,父智能体只看结果不看过程
  2. 成本可控:子任务 token 用完即弃,不计入父智能体的长期上下文成本
  3. 并行潜力:子智能体之间天然无共享状态,为后续 [[09-agent-teams/09-智能体团队|s09 智能体团队]] 的多 Agent 并行打下基础
  4. 错误包裹:子智能体崩溃不影响父智能体状态,可添加重试逻辑

工作原理

工具层面

父智能体有一个额外的 task 工具。子智能体拥有除 task 外的所有基础工具——禁止递归创建子智能体,这是防止无限生成的关键约束。

python
PARENT_TOOLS = CHILD_TOOLS + [
    {"name": "task",
     "description": "Spawn a subagent with fresh context.",
     "input_schema": {
         "type": "object",
         "properties": {"prompt": {"type": "string"}},
         "required": ["prompt"],
     }},
]

执行层面

子智能体以 messages=[] 启动,运行自己的工具调用循环。只有最终文本返回给父智能体,以普通 tool_result 的形式嵌入父对话。

python
def run_subagent(prompt: str) -> str:
    sub_messages = [{"role": "user", "content": prompt}]
    for _ in range(30):  # safety limit
        response = client.messages.create(
            model=MODEL, system=SUBAGENT_SYSTEM,
            messages=sub_messages,
            tools=CHILD_TOOLS, max_tokens=8000,
        )
        sub_messages.append({"role": "assistant",
                             "content": response.content})
        if response.stop_reason != "tool_use":
            break
        results = []
        for block in response.content:
            if block.type == "tool_use":
                handler = TOOL_HANDLERS.get(block.name)
                output = handler(**block.input)
                results.append({"type": "tool_result",
                    "tool_use_id": block.id,
                    "content": str(output)[:50000]})
        sub_messages.append({"role": "user", "content": results})
    return "".join(
        b.text for b in response.content if hasattr(b, "text")
    ) or "(no summary)"

关键细节:

  • 安全上限:30 次迭代防止子智能体死循环,也隐含了预算控制
  • 截断保护[:50000] 限制单次 tool_result 大小,防止子智能体自己把自己撑爆
  • 默认摘要:即使子智能体没有返回有效文本,也不会让父智能体卡住

子智能体可能跑了 30+ 次工具调用,但整个消息历史直接丢弃。父智能体收到的只是一段摘要文本,作为普通 tool_result 返回。这与 [[03-todo-write/03-待办写入|s03 的待办写入]] 形成互补:待办管理"接下来做什么",子智能体管理"怎么做以及做完就忘"。

相对 s03 的变更

组件之前 (s03)之后 (s04)
Tools55 (基础) + task (仅父端)
上下文单一共享父 + 子隔离
Subagentrun_subagent() 函数
返回值不适用仅摘要文本

从 harness 演进的角度看:

  • [[01-agent-loop/01-智能体循环|s01]] 搭建了循环骨架
  • [[02-tool-use/02-工具使用|s02]] 添加了工具交互能力
  • [[03-todo-write/03-待办写入|s03]] 引入了任务规划和持久化
  • s04 解决了执行过程中的上下文污染问题

何时使用子智能体

子智能体不是银弹。使用前需要判断任务是否值得"派遣"的成本:

适合派生子智能体:

  • 纯信息收集任务("查一下这个库的 API 签名")
  • 文件内容阅读与总结("读这 10 个文件,告诉我它们的关系")
  • 确定性操作("创建这个目录结构")
  • 高噪音操作("搜索所有出现某个模式的代码")

不适合派生子智能体:

  • 结果需要立即参与父决策链("帮我看看这个文件,然后基于它改另一个文件")
  • 子任务本身极轻量(读一个文件,还不如父智能体自己干)
  • 需要子智能体状态延续到后续操作

试一试

sh
cd learn-claude-code
python agents/s04_subagent.py

试试这些 prompt(英文 prompt 对 LLM 效果更好,也可以用中文):

  1. Use a subtask to find what testing framework this project uses
  2. Delegate: read all .py files and summarize what each one does
  3. Use a task to create a new module, then verify it from here

观察父智能体的上下文在子智能体运行前后是否保持精简——这是子智能体有效的直接证据。

本课小结

  • 子智能体是用 干净的 messages[] 执行子任务的机制
  • 核心价值是 上下文隔离,防止过程数据污染主对话
  • task 工具是父智能体独有的入口,子智能体不可递归
  • 子智能体返回的 仅摘要文本,完整工具调用过程全部丢弃
  • 适合信息收集型任务,不适合需要状态延续的操作
  • 这是 Agent Harness 从"单体"走向"分布式"的第一步

下节预告

上下文隔离之后,下一个问题是知识隔离。子智能体解决了执行环境的干净,但智能体仍然需要知道"遇到某个问题该用什么知识"。[[05-skill-loading/05-技能加载|s05 技能加载]] 将教你如何按需加载领域知识,让智能体在需要时才注入专业知识。

延伸阅读

  • Learn Claude Code 项目 — 练习代码和完整文档
  • [[00-课程概览/教学大纲|教学大纲]] — 查看完整课程地图
  • [[00-课程概览/综述|课程综述]] — Agent Harness 工程导论

「干净的上下文是模型理性思考的前提」

基于 Learn Claude Code 项目改编