把大问题切给一个新开的 agent
「Process isolation gives context isolation for free.」子 agent 做脏活,父 agent 只收干净摘要。
父 agent 的困境
想象你让 Claude Code「搞懂这个 10 万行的 Rust 仓库是怎么处理并发的」。直觉做法:它自己 ls、cat、grep,在主 context 里搜一遍。
问题:这一圈探索会往 messages[] 里堆 30 条 tool_result,每条几千 token。等它真的开始写答案时,上下文已经被探索过程塞满——后面再做几步就触发上限,答得还乱。
s04 的解法:把探索任务丢给一个新 agent。新 agent 从 messages=[] 启动,自己探自己的,最后只把 summary 返回给父 agent。父的 context 只多了一条「调了一次 task 工具,结果是 XXX」,清爽。
def run_subagent(prompt: str) -> str: sub_messages = [{"role":"user", "content": prompt}] # 全新 context for _ in range(30): # 安全上限,防失控 response = client.messages.create(..., messages=sub_messages, tools=CHILD_TOOLS, ...) ... # 只返回最后的文字,中间推理全部丢弃 return "".join(b.text for b in response.content if hasattr(b, "text"))
父子 context 对比
这个 widget 模拟一个真实任务:「把这个仓库里所有调用 deprecated API 的地方列出来」。你可以用两种策略跑:(A) 父 agent 自己做;(B) spawn 一个 subagent。左右对比最后两个 context 的大小。
CHILD_TOOLS:子 agent 能拿到什么工具
s04 的实现里有个细节容易错过:子 agent 拿不到 task 工具。
# 子 agent 只能用基础工具,不能再 spawn 孙子 CHILD_TOOLS = [bash, read_file, write_file, edit_file] # 父 agent 多一个 task 工具 PARENT_TOOLS = CHILD_TOOLS + [task]
为什么?避免递归派发变成树状爆炸。一个 subagent 又 spawn 4 个 subsubagent,几轮就几十个并发调用,token 和 API 限速都扛不住。s04 的约定:spawn 是扁平的,父→子一层就是一层。Claude Code 真实实现里也这样——Task tool 里禁止再调 Task tool。
看得到和看不到
权责梳理一下:下面几个问题,你觉得哪些 T、哪些 F?