🛠️ 第8章 Skill、Subagent 与 MCP:把能力和上下文装进系统
📄 一句话概括

拆的是上下文,不是工作量——总工作量不减,每一刻要装的东西减。 看峰值,不看总量:上下文窗口是上限,不是账单。 Demo 里峰值从一百八十五降到六十一,合计也从五百五十五降到一百八十。

📝 本章和前面几章的关系

上一篇讲把脚本升级成能力。这一篇讲另一种扩容:把一件事拆给几个子 Agent。 为什么需要拆?因为上下文有上限。 一个任务要读十个文件时,全塞进去会超;拆开之后每份只读两三个。 Demo 真起三个子进程,每个只看自己那一段文档,各回一份结论。 峰值和合计两个数都算出来,和「一个 Agent 顺序做」对比。

一、拆的是上下文,不是工作量

这句话容易听成文字游戏,但它决定了你怎么拆。 如果你按「工作量」拆——三件事分给三个人做——每个人还是要读全部背景,因为三件事互相依赖。 那拆分只增加了沟通成本。 如果你按「上下文」拆——每个人只看自己那段——每个人读的东西少了,而且不需要知道别人那段。 这才是有效的拆。 Demo 里就是这么拆的: 一段文档切成三份,判空、判情绪、选回复各看一份,各回一行结论。 三个子进程之间互不知道对方存在。

二、一个主 Agent 三个子 Agent 的信息流

环节 发生什么 经过谁
拆分 主 Agent 把任务切成三份 主
分发 每份带自己的上下文出去 主到子
各自判断 只看自己那份,回一行结论 子
汇总 三行结论合成一个答复 主

关键在于「回一行结论」这个约定。 子 Agent 不把读到的原文带回来,只带判断结果。 这是峰值能降下来的原因——如果它把原文一起带回来,主 Agent 的上下文又满了。 所以子 Agent 的输出格式要提前定死。 Demo 里定的是 JSON,三个字段:任务名、结论、状态。 定死之后,汇总就是拼三个 JSON,不需要理解内容。

三、拆分失败的两种样子

样子 症状 原因
拆得太碎 合计暴涨、结论互相矛盾 每份都不足以独立判断
拆得不彻底 每个子 Agent 还是要读全文 只是换了个壳

「拆得太碎」的表现很好认:合计比不拆还多。 因为每个子 Agent 都要写一份结论,结论本身也是 token。 拆成十个,就是十份结论——比原文还长。 「拆得不彻底」更隐蔽。 形式上你起了三个子 Agent,实际上每个都读了全文。 判断方法只有一个数:子 Agent 拿到的上下文,比主 Agent 少多少。 没少,就是白拆。 一个实用的拆法:按「能不能独立判断」切。 一份上下文如果单独给出去,那个子 Agent 能自己得出结论,就算切对了; 如果它还得回来问「那另一段呢」,就切错了。

四、动手 Demo:Subagent:拆的是上下文,不是工作量

一份三百字的流程文档,两种做法:一个 Agent 顺序做三件事,或者三个子 Agent 各看一段。 子 Agent 是真起的子进程:主进程往 stdin 写 JSON,子进程算出结论写回 stdout。 三种做法的上下文量都是真算的。

for i, (name, goal) in enumerate(three):
    chunk = parts[i]
    r = subprocess.run([PY, u"sub.py"], cwd=base,
                       input=json.dumps({"name": name,
                                         "text": chunk}).encode())
    out = json.loads(r.stdout.decode(u"utf-8").strip())
    subs.append((name, tokens(chunk), tokens(json.dumps(out))))

实跑输出:

--------------------------------------------------------------------
Subagent:拆的是上下文,不是工作量
--------------------------------------------------------------------


  ① 一个主 Agent 顺序做三件事
  --------------------------------------------------------------------
  文档 185 token,顺序做三件事,每件都要带全文
  峰值上下文 185 token,合计 555 token

  ② 三个子 Agent,各看一段
  --------------------------------------------------------------------
  判空     只看 61 token,回了 10 token 的结论
  判情绪   只看 32 token,回了 12 token 的结论
  选回复   只看 53 token,回了 12 token 的结论
  峰值上下文 61 token,合计 180 token

  ③ 两种做法对比
  --------------------------------------------------------------------
| 做法 | 峰值上下文 | 合计 | 结果怎么来 |
|---|---:|---:|---|
| 一个 Agent 顺序做 | 185 | 555 | 三件事在同一份上下文里做 |
| 三个子 Agent 并行 | 61 | 180 | 各自出结论,主 Agent 汇总 |

  峰值从 185 降到 61,降了 3.0 倍;合计从 555 降到 180,降了 3.1 倍。
  ! 这两个数一起降,是因为「各看一段」比「每件都带全文」省。所以拆对了,峰值和合计是同时降的。
  如果拆完之后每个子 Agent 还是要读全文,合计会涨回去——那是「拆得不彻底」,⑤ 里会讲。

  ④ 为什么峰值比总量重要
  --------------------------------------------------------------------
  上下文窗口是一个上限,不是账单。
  装不下就是装不下——所以你要看的是「最挤的那一刻」,不是「一共花了多少」。
  ! 这也解释了为什么「拆得越细越好」是错的:拆得越细,每个子 Agent 都要写一份结论,合计涨得很快。
  拆到「每份都能独立判断」就够,再细就是浪费。

  ⑤ 拆分失败的两种样子
  --------------------------------------------------------------------
| 样子 | 症状 | 原因 |
|---|---|---|
| 拆得太碎 | 合计暴涨、结论互相矛盾 | 每份都不足以独立判断 |
| 拆得不彻底 | 每个子 Agent 还是要读全文 | 只是换了个壳,没减上下文 |

  ! 判断拆对了没有,看一个数:子 Agent 拿到的上下文,比主 Agent 少多少。没少,就是白拆。

顺序做:峰值一百八十五、合计五百五十五。 三个子 Agent:峰值六十一、合计一百八十。 两个数都降了三倍。 为什么合计也降了? 因为「各看一段」比「每件都带全文」省。 顺序做的时候,三件事每件都带着全文,等于读了三千;拆开之后,三份加起来才一百八十五。 注意子 Agent 回的结论只有十来个 token。 这就是「只带判断,不带原文」的具体样子。 如果它把原文带回来,主 Agent 的峰值立刻回到一百八十五。 最后那句判断标准要记住:子 Agent 拿到的上下文,比主 Agent 少多少。 没少,就是白拆。

30 秒实验

  1. 找一个你嫌大的任务,试着按「能不能独立判断」切一次。 切完看每一份是不是都能自己得出结论。
  2. 给你的子 Agent 定一个输出格式,只允许结论。 一旦允许它带原文回来,拆分就白做了。
  3. 量一下拆分前后的峰值上下文。 没降一半,说明拆得不够彻底。

常见误区

  1. 「拆得越细越好。」 拆得越细,结论越多,合计涨得很快。 拆到「每份能独立判断」就够。
  2. 「子 Agent 应该把读到的都带回来,方便主 Agent 判断。」 那峰值立刻满。 拆分的全部收益就在「不带回来」这一条上。
  3. 「拆分能提高总吞吐。」 拆分降的是峰值,不是总量。 总量甚至可能上升,因为多了写结论这一步。
自测三问(点开对答案) 1. 「拆上下文」和「拆工作量」有什么不同? —— **拆工作量:每个人还是要读全部背景,因为任务互相依赖。** **拆上下文:每个人只看自己那段,不需要知道别人那段。** **只有后者能降峰值。** 2. 为什么子 Agent 只该回结论,不该带原文? —— **因为带回来主 Agent 的上下文又满了。** **拆分的全部收益就在「不带回来」这一条上。** 3. 怎么判断拆分失败了? —— **看子 Agent 拿到的上下文比主 Agent 少多少。** **没少就是白拆;如果合计比不拆还多,就是拆得太碎。**

下一篇 8.3 讲 MCP:先问是否值得接,再问怎么接——顺便看一次真的握手报文。

相关笔记