子智能体也有两个钩子:启动时注入上下文,结束时验收输出。一道管进去,一道管出来。 注入的难点是精度:全局注入一次配好、所有子智能体都读,但每个都读进了不属于自己的规矩。
上一节的质量钩子挂在主窗口的工具调用上,这一节把钩子挂到第 4 章那个「隔离区」的门口。 这一节和 4.3 节(定义)、4.8 节(回执)是同一条线的三段:怎么定义、进去给什么、出来验什么。
一、两道口
启动时(SubagentStart):它还没有开始干活,这时候注入的上下文会跟着它整段工作。 结束时(SubagentStop):它已经干完、回执还没交回主窗口。这时候能验、能拦、能打回。 两道口的分工很自然:进去给「它需要知道的」,出来验「它交的合不合格」。
这和 4.5 节「技能管怎么做、子智能体管在哪做」是配套的:技能的内容怎么进到子智能体那儿? 靠启动时注入。 所以注入这件事,本质上是「把技能或者规范搬到隔离区门口」。
二、全局注入与 frontmatter 注入
全局注入:在全局配置里写一条启动钩子,所有子智能体启动时都跑。一次配置,人人受益。 frontmatter 注入:在某个子智能体的定义里声明它要什么。只有它跑,别人不跑。 演示里三种情况:全局注入八百 token、frontmatter 注入两百、完全不注入。
全局那份花八百送了两百有用的,另外六百是别的子智能体的规矩——它读了,但用不上。 更要紧的是噪声:它读到的规矩里有一半不适用自己的活,而模型分不清哪条适用。
三、精度的代价
全局注入好写:一次配置,所有子智能体都受益。 代价是每个子智能体都读一遍全部内容。五个子智能体,就是五份。 而「读进不属于自己的规矩」不只是浪费,还可能误导:它可能照着一份不属于它的规范干活。
所以默认应该走 frontmatter:谁需要什么,谁自己声明。 全局只放「所有子智能体都必须知道的」——比如「不许改 migrations 下已提交的脚本」。 这条判据和记忆层一样:范围越大放得越靠上,但靠上的内容必须真的通用。
四、SubagentStop 验什么
常见的三条:回执是不是合法 JSON、必填字段在不在、返回值有没有超过大小限制。 这三条全是规则,用 command 处理器就够,不需要模型(5.4 节的阶梯第一级)。 第一条对应 5.5 节的协议,第二条对应 4.7 节的四个字段,第三条对应 4.8 节的坑一。
所以子智能体的两道口,其实是前面几节所有约定在门口的落点:进去靠注入,出来靠校验。 如果校验不过怎么办?打回。 SubagentStop 能阻止,所以可以让它重做一次——但要有次数上限,否则会转成 4.8 节那个循环。
五、什么时候不需要这两道口
只读型子智能体不需要注入太多:它的活就是「读并判断」,给太多规矩反而干扰。 一次性的探索型子智能体不需要严格校验:它交的东西你只看一眼就丢。 所以两道口也是按需的。挂得越多,隔离区门口的检查越慢,而慢会抵消掉隔离的好处。
判据:这道口如果不挂,出问题会不会被发现?不会 → 挂。会 → 先别挂,等真出事再说。 这条和 5.11 节的四个判据是一路的:先问「漏了会不会出事」,再决定挂不挂。
六、动手 Demo:三个子智能体,注入方式不同,产出合规率差多少
三个子智能体:一个靠全局钩子注入、一个在定义里声明注入、一个完全不注入。 比较注入的 token 和实际需要的 token,再看产出合规率。
SUBS = [(u"全局注入", 800, 200, 1), # 注入 800,其实只需要 200
(u"frontmatter 注入", 200, 200, 1),
(u"不注入", 0, 200, 0)]
实跑输出:
--------------------------------------------------------------------
三个子智能体,注入方式不同,产出合规率差多少
--------------------------------------------------------------------
子智能体也有钩子:SubagentStart 在它启动时注入上下文,SubagentStop 在它结束时验证输出。
① 三种注入方式
--------------------------------------------------------------------
| 方式 | 作用范围 | 特点 |
|---|---|---|
| 全局 Hooks | 所有子智能体都注入 | 一份通稿,谁都得读 |
| frontmatter 里声明 | 只有这个子智能体注入 | 精准,按需 |
| 不注入 | 什么都不给 | 它只能靠通用知识 |
② 三份产出对比
--------------------------------------------------------------------
| 注入方式 | 注入 token | 需要的 token | 合规率 | 结果 |
|---|---:|---:|---:|---|
| 全局注入 | 800 | 200 | 100% | 合规 |
| frontmatter 注入 | 200 | 200 | 100% | 合规 |
| 不注入 | 0 | 200 | 0% | 漏关键约定 |
全局注入那份花八百 token 送了两百有用的,另外六百是别的子智能体的规矩——它读了,但用不上。
③ 全局注入的问题:精度
--------------------------------------------------------------------
全局注入好写:一次配置,所有子智能体都受益。
代价是每个子智能体都读一遍全部内容。五个子智能体,就是五份。
更要紧的是「噪声」:它读到的规矩里有一半不适用自己的活,
而模型分不清哪条适用——它可能照着一份不属于它的规范干活。
④ SubagentStop 验证什么
--------------------------------------------------------------------
它发生在子智能体结束、回执还没交回主窗口的那一刻。能阻止,所以可以在这里卡一道。
常见的三条验证:回执是不是 JSON、必填字段在不在、返回值有没有超过大小限制(4.8 节的坑一)。
这三条全是规则,用 command 处理器就够,不需要模型。
! 所以子智能体的两道口是:进去时注入什么(精度问题),出来时验收什么(格式问题)。
两道都是钩子,都不归模型决定。
①三种注入方式:全局钩子(所有子智能体都跑)、frontmatter 声明(只有它跑)、不注入。 ②全局注入那份花八百 token 送了两百有用的,另外六百是别的子智能体的规矩——它读了,但用不上。 更麻烦的是噪声:它读到的规矩里有一半不适用自己的活,而模型分不清哪条适用, 可能照着一份不属于它的规范干活。 ③全局注入好写,代价是每个子智能体都读一遍全部内容;五个就是五份。 所以默认应该走 frontmatter:谁需要什么,谁自己声明。 ④SubagentStop 验三条:回执是不是合法 JSON、必填字段在不在、返回值有没有超大小限制。 三条全是规则,用 command 处理器就够。 这三条正好对应前面几节的约定:第一条是 5.5 的协议、第二条是 4.7 的四个字段、第三条是 4.8 的坑一。 所以子智能体的两道口,是前面所有约定在门口的落点:进去靠注入,出来靠校验。
30 秒实验
- 把全局注入的内容砍到只剩通用的三条(从八百降到三百),重跑第 ② 步。合规率会掉吗? 这说明「哪些规矩真该全局」怎么判?
- 给「不注入」那个加上 frontmatter 注入两百 token,重跑一遍。它和全局注入的差距在哪?
- 给 SubagentStop 加一条「回执超过五百 token 就打回」,重跑一遍。这条校验对应的是哪个坑?
常见误区
- 什么都往全局注入里塞。每个子智能体都读一遍,读到的绝大部分用不上,还可能误导。
- 完全不注入。子智能体不知道项目规矩,只会按通用做法来,产出不合规。
- 用 prompt 处理器做格式校验。回执是不是合法 JSON 是一行命令的事,用模型是浪费。
- SubagentStop 打回不设上限。会转成 4.8 节那个循环:一遍遍重做,你不知道它在转。
- 给只读型子智能体注入一大堆规矩。它的活就是读并判断,规矩太多反而干扰。
自测三问(点开对答案)
1. 子智能体的两个钩子分别管什么? —— SubagentStart 在它启动时注入上下文(进去给什么), SubagentStop 在它结束时验收输出(出来验什么)。 2. 全局注入的问题是什么? —— 精度。所有子智能体都读同一份通稿,每个都读进不属于自己的规矩,既浪费又可能误导。 3. SubagentStop 通常验哪三条? —— 回执是不是合法 JSON、必填字段在不在、返回值有没有超过大小限制。 三条都是规则,用命令处理器就够。两道口讲完了,下一节解决一个很现实的问题:钩子慢怎么办——异步。
- ☐ (本篇完,下一篇 5.9 异步 Hooks:后台执行不阻塞)
相关笔记
- 定义与配置:子智能体怎么定义
- 从软件工程看:回执该有哪几个字段
- Claude Code 橙皮书 · 索引
- 🐎 Claude Code 实战 · 索引