📄 一句话概括
一次工具调用要过六道关:挂载期(有效性)→ 注册期(依赖分组)→ 调用前(审批)→ 调用中(沙箱)→ 执行中(超时/溢出)→ 执行后(观察与留痕),关关都有真身。
📝 本节和前面几节的关系
4.3 讲了规则是插件,这一节把它们按时间排成一队——管线 = 关卡顺序,规则 = 每道关卡的判断。
一、六道关,按时间排
- 挂载期:这个插件在这个平台/作用域有效吗?——
disabled条件。 - 注册期:名字、依赖、分组对不对?——
cordis:group。 - 调用前:这一次要不要先问人?——
user-approval。 - 调用中:能在多大范围里动手?——
sandbox-policy。 - 执行中:多久算超时、结果太大怎么办?——timeout/spill policy。
- 执行后:要不要留证据、要不要提醒?——观察策略/repeat-reminder。
前两道关在【挂载阶段】就过完了,跟具体调用无关;后四道才是一次调用真正走过的路。
二、实测数字:挂载期就有 20 处条件
配置里 disabled 一共 58 行,其中 20 处是条件表达式(平台判断、作用域判断),不是写死的布尔值。
典型两处:tool-bash 带 platform === 'win32'、tool-pwsh 带 platform !== 'win32'。
这说明【能力在不在】在挂载期就定了,不是运行时才决定的——排查问题时,这一步先看配置树,比看日志快。
三、分组就是关卡的落点
实测有 10 处 cordis:group(group: true),它们把子能力圈在一起,还带 isolate 声明,例如:
- 压缩分组:
isolate: compaction / toolResultPruner。 - 委托分组:
isolate: workflowEngine。
分组的价值是隔离:某一组换实现、开关,影响不到别的组。关卡要能独立开关,就得先有边界——又是 3.2.2 那个道理。
四、为什么要有管线
因为动手的路径必须唯一。如果每个工具各自决定【要不要问人、能改哪些文件】,权限就散了。
管线把这件事收成一条:所有工具调用从同一道门进来,规则在这一层统一判断。
于是 4.6 的问题自然就有了答案:程序编排也不能绕开这道门。
五、动手 Demo:一次工具调用要过几道关
六道关,每道关配上配置里的真身:
stages = [
("挂载期", "这个插件在此平台/作用域有效吗", "disabled 条件"),
("注册期", "名字、依赖、分组对不对", "cordis:group"),
("调用前", "这一次要不要先问人", "user-approval"),
("调用中", "能在多大范围里动手", "sandbox-policy"),
("执行中", "多久算超时、结果太大怎么办", "timeout/spill"),
("执行后", "要不要留证据、要不要提醒", "观察策略"),
]
for a, b, c in stages:
print(" %-6s %-24s %s" % (a, b, c))
print()
print(" disabled 行 58 处,其中有条件的 20 处")
print(" cordis:group 分组 10 个")
实跑输出:
--------------------------------------------------------------------
一次工具调用要过几道关
--------------------------------------------------------------------
把关卡通按时间顺序摆出来,每一关在配置里都有真身:
阶段 过关时看什么 配置里的真身
------------------------------------------------------------------------
挂载期 这个插件在此平台/作用域有效吗 disabled 条件
注册期 名字、依赖、分组对不对 cordis:group
调用前 这一次要不要先问人 user-approval
调用中 能在多大范围里动手 sandbox-policy
执行中 多久算超时、结果太大怎么办 timeout/spill policy
执行后 要不要留证据、要不要提醒 观察策略/repeat-reminder
------------------------------------------------------------------------
实测数字:
配置里 disabled 的行数 58
其中【有条件】的 disabled 20 <- 平台或作用域决定,不是写死
cordis:group 分组数 10
那 20 处条件说明一件事:挂载期就有判断,
所以【能力在不在】不是运行时才决定的。
前两道关和调用无关:它们在挂载时就过完了——所以【能力在不在】要在配置树里查。
20 处条件表达式是【挂载期判断】的实证,也是 4.1.2 那个实验只多 1 行的原因。
分组带的 isolate 是隔离声明:关卡的边界,就是分组的作用域(3.2.2 的复现)。
30 秒实验
- 在配置里数一数
disabled有多少处、其中有条件的有多少处。 - 找出一处
cordis:group,看它的isolate声明隔离了什么。 - 按六道关的顺序复述一遍:哪几道在挂载时过、哪几道在调用时过?
常见误区
- 错误:工具调用就是【模型说、工具跑】两步。——纠正:要过六道关,前两道在挂载期,后四道在调用期。
- 错误:能力在不在要运行起来才知道。——纠正:挂载期就定了——看配置树里的 disabled 条件。
- 错误:分组只是排版好看。——纠正:分组带
isolate,是隔离与独立开关的单位。
自测三问(点开对答案)
1. 六道关分别是什么? —— 挂载期、注册期、调用前、调用中、执行中、执行后。 2. `disabled` 58 处、其中 20 处有条件,说明什么? —— **能力在不在挂载期就定了**(平台/作用域判断),不是运行时决定的。 3. 为什么要有管线? —— **动手的路径必须唯一**:所有工具调用从同一道门进来,规则统一判断。- ☐ 下一节(4.5.1 为什么 Guard 要【单调】)
相关笔记
- 第三层:用 Hook 改变执行规则 —— 规则插件就是每道关的守卫
- 作用域的意义:动态组合必须有边界 —— 分组的 isolate 就是边界
- 网络的虚拟化① VLAN —— 隔离这件事,基础设施层早就做过一遍
- 🐳 DeepSeek Harness · 索引