子智能体与上下文隔离:保持思维清晰的关键

来自程序员技术小站
跳转到导航 跳转到搜索

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

随着 Agent 工作,messages 数组越来越胖。每次读文件、跑命令的输出都永久留在上下文里。

"这个项目用什么测试框架?" 这个问题可能需要读 5 个文件,但父智能体只需要一个词:"pytest"

如何把探索的细节隔离,只把结论带回?

一、问题:上下文膨胀

想象这个场景:

父 Agent 正在做大型重构,上下文里已经累积了:

  • 20 个文件的读取结果
  • 10 次测试运行输出
  • 5 次 Git 状态检查
  • 各种中间文件的 diff

现在它想知道:" utils.py 里的 parse_data 函数是做什么的?"

为此它需要:

  1. 读取 utils.py
  2. 查看相关依赖
  3. 分析函数逻辑
  4. 返回结论

这些探索过程会进一步膨胀父 Agent 的上下文,稀释真正重要的信息。

二、解决方案:子智能体

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.

父智能体有一个 task 工具。子智能体运行自己的循环,只有最终文本返回给父智能体。

三、核心机制

1. 工具分离

父智能体拥有所有基础工具 + task

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

子智能体拥有除 task 外的所有基础工具(禁止递归生成)。

2. 独立循环

子智能体以 messages=[] 启动,运行自己的循环:

def run_subagent(prompt: str) -> str:
    sub_messages = [{"role": "user", "content": prompt}]
    for _ in range(30):  # 安全限制
        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)"

3. 上下文隔离

子智能体可能跑了 30+ 次工具调用,但整个消息历史直接丢弃。父智能体收到的只是一段摘要文本,作为普通 tool_result 返回。

四、使用场景

场景 1:信息检索

父 Agent:这个项目用什么测试框架?
↓
子 Agent(独立上下文):
  - 读取 pytest.ini
  - 读取 setup.py
  - 检查测试目录结构
  - 分析依赖
↓
返回:"pytest"

父 Agent 的上下文保持干净,只有结论。

场景 2:多文件分析

父 Agent:分析所有 Python 文件的依赖关系
↓
子 Agent:
  - 遍历所有 .py 文件
  - 提取 import 语句
  - 构建依赖图
  - 生成报告
↓
返回:精简的依赖关系摘要

场景 3:代码生成

父 Agent:创建一个数据处理模块
↓
子 Agent:
  - 设计 API
  - 实现核心函数
  - 添加错误处理
  - 编写测试
↓
返回:模块完成确认 + 文件路径

五、试一试

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

试试这些 prompt:

  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

观察父 Agent 如何派发子任务,子 Agent 独立工作,最后只返回简洁的结果。

六、对比无隔离 vs 有隔离

场景 无子智能体 有子智能体
探索性任务 上下文膨胀,主任务迷失 探索细节隔离,主任务清晰
多文件分析 所有文件内容留在上下文 只保留分析结论
长对话 后期上下文窗口溢出 定期清理,保持高效

七、进阶:递归与层级

本文的子智能体是单层的。更复杂的系统可以支持:

  • 递归子智能体:子智能体也可以派发孙智能体
  • 层级架构:父-子-孙三级结构,每层有不同职责
  • 并行子智能体:同时派发多个子任务,聚合结果

但要注意:层级越深,协调成本越高。对于多数场景,单层子智能体已经足够。

八、Harness 层的职责

守护模型的思维清晰度——这是 Harness 的核心职责之一。

  • 子智能体隔离是机制
  • 模型决定什么时候用、用来做什么
  • Harness 保证隔离的执行

这种设计模式不仅适用于编程 Agent,也适用于任何需要复杂推理的场景:

  • 研究 Agent:主 Agent 协调,子 Agent 深入具体领域
  • 客服 Agent:主 Agent 处理对话,子 Agent 查询知识库
  • 创意 Agent:主 Agent 把控方向,子 Agent 探索具体方案

好的 Harness 像一个好的工作环境——提供清晰的边界,让智能高效运转。


Bash 就够了。真正的 Agent 是宇宙所需要的全部。