权限系统如何影响 AgentTool
目标
这页回答:
在 Claude Code 里,AgentTool 为什么不只是“启动子 agent”,而是深受 permission system 影响?权限系统到底怎样塑造 agent 行为?
相关文件:
src/tools/AgentTool/AgentTool.tsxsrc/tools/AgentTool/runAgent.tssrc/services/tools/toolExecution.tssrc/utils/forkedAgent.ts
一句话结论
AgentTool 不是一个绕过权限系统的超级入口,反而是 最深度受权限系统支配的工具之一。
因为一旦启动子 agent,问题就不再只是“这个工具能不能调”,而是:
- 子 agent 的权限模式是什么
- 谁来弹权限提示
- 异步 agent 能不能弹提示
- 允许哪些工具继续下钻
- permission decision 是否继承给子 agent
- hooks / classifier 是否继续介入
也就是说,权限系统不是挂在 AgentTool 外面的一层壳, 而是直接进入了子 agent 的运行模型。
1. 第一层:AgentTool 自己首先也是一个 Tool
这意味着 AgentTool 本身也要经过普通工具协议:
checkPermissions()canUseToolrunToolUse()- permission decision
这点很关键
主 agent 想调用 AgentTool 先要被权限系统允许。
所以“是否允许再起一个 agent”本身,就是一个被治理的问题。
2. AgentTool 自己的 checkPermissions() 很保守
在 AgentTool.tsx 里能看到:
- 某些模式下直接 allow
- auto mode 下会走 passthrough / prompt 路线
它不是简单粗暴地总 allow。
这说明什么
系统认为:
- 启动 subagent 不是无代价动作
- 它会带来更多工具调用、更多副作用、更多上下文扩散
所以 AgentTool 自己就是需要权限边界的。
3. 子 agent 的 permission mode 不是天然继承父级
runAgent.ts 有一个关键函数:
agentGetAppState()
里面会动态重写:
toolPermissionContext.modeshouldAvoidPermissionPromptsawaitAutomatedChecksBeforeDialogalwaysAllowRules
这意味着
子 agent 不是简单拿父 AppState 照抄。
而是会基于:
- agentDefinition.permissionMode
- 是否 async
- 是否 bubble mode
- 是否传了 allowedTools
重新构造自己的权限视图。
这就是为什么我说权限系统已经深入 agent runtime,而不是停留在入口处。
4. bubble permission mode 的意义
fork / 某些 agent 会使用:
permissionMode: 'bubble'它代表什么?
不是“无权限控制”,而是:
权限提示不要在子 agent 自己那里消费,而是冒泡给父终端 / 父交互层。
为什么需要这种模式?
因为子 agent 往往:
- 没有自己的 UI
- 没有自己的独立交互面板
- 但又不能直接绕过权限
所以 bubble mode 很像一种“代理审批模式”:
- 子 agent 想做事
- 权限决策由更高一层交互界面承接
这非常适合:
- fork child
- 某些同步交互型 subagent
5. async agent 与 sync agent 在权限行为上完全不同
这是最值得注意的一点之一。
在 runAgent.ts 里
会根据:
isAsynccanShowPermissionPromptsagentPermissionMode === 'bubble'
推导出:
shouldAvoidPermissionPrompts默认规律可以粗暴理解为:
sync / interactive agent
可以让权限提示浮到界面上
async / background agent
通常应该避免权限提示
为什么?
因为后台 agent 没法像前台 agent 那样稳稳占着终端等人点确认。
所以权限系统必须区分:
- 谁可以等用户交互
- 谁必须走自动化或拒绝路径
这就说明权限系统并不是静态规则集, 而是和执行模式强耦合的。
6. shouldAvoidPermissionPrompts 是权限治理里的关键开关
这个字段在多个地方都很重要。
它控制的是
子 agent 在遇到需要许可的工具时, 到底:
- 能不能弹权限提示
- 还是必须走自动决策 / 直接拒绝
在 createSubagentContext() 里
默认子 agent 的 getAppState() 还会被包一层,强制把:
shouldAvoidPermissionPrompts: true打开。
这进一步说明默认设计哲学是:
子 agent 默认不该拥有自己的权限交互面。
除非上层显式把它塑造成一个可交互 agent。
7. awaitAutomatedChecksBeforeDialog 说明权限系统并不想太早打扰用户
runAgent.ts 里对 async but can-show-prompts 的情况,还会设:
awaitAutomatedChecksBeforeDialog: true这说明什么
系统希望:
- 先让 classifier / hooks / 自动规则尽量消化权限问题
- 只有这些都解决不了,才真的弹对话框打断用户
这是很成熟的治理思路:
- 自动化先行
- 人类审批兜底
而不是一遇到潜在敏感动作就立刻把用户炸出来。
8. allowedTools 会把子 agent 权限面收窄
在 runAgent.ts 中如果传了 allowedTools,会重写:
toolPermissionContext.alwaysAllowRules.session = [...allowedTools]同时保留 CLI 级的 allow rules。
含义
这不是简单“继承父级已批准的所有工具”, 而是允许某些子 agent 被约束成:
你只准用这一小撮工具。
这很关键,尤其对:
- 技能型 fork
- 特定命令型 agent
- 最小权限执行
因为 agent 一旦能再起 agent、再调 bash,权限面会迅速膨胀。
所以 allowedTools 是很重要的收口阀门。
9. canUseTool 不会因为进了子 agent 就失效
runAgent() 调用 query() 时,还是会把:
canUseTool继续传进去。
这意味着
子 agent 后续每一次工具调用:
- 仍然要走权限判断
- 仍然可能触发 classifier
- 仍然可能被 hooks 改写 / 阻断
- 仍然可能产生 allow / deny / ask 决策
这点非常重要。
因为如果 AgentTool 一旦起了子 agent,子 agent 内部就可以无限绕过治理, 那整个权限模型就废了。
但这套代码明显不是这么干的。
10. toolExecution.ts 里能看到权限治理的完整执行链
单次工具调用的权限链大致是:
runPreToolUseHooks(...)resolveHookPermissionDecision(...)canUseTool(...)- classifier / mode / rule / hook 综合出
permissionDecision - allow / deny / ask
- 必要时再跑 denied hooks / failure hooks
这说明什么
权限系统在这里不是一个简单 if 判断, 而是一条独立的执行管线。
而 AgentTool 及其子 agent,完全生活在这条管线之内。
11. 为什么说 AgentTool 是最容易引发权限复杂性的工具?
因为普通工具只带来一次动作。
但 AgentTool 会带来:
- 一整个新的 query loop
- 一整套新的 tool permissions
- 可能的后台执行
- 可能的 remote execution
- 可能的 forked child
- 可能的 further delegation(如果不拦)
所以权限系统必须回答的,不再只是:
这次调用 AgentTool 允不允许?
而是:
这个子 agent 启动后,接下来会在什么权限边界内继续活着?
这才是 AgentTool 特别的地方。
12. 这套设计的核心哲学
如果把它说成人话,大概是这样:
- 主 agent 想 delegate,可以
- 但 delegate 本身要被批准
- 子 agent 可以运行
- 但它不能默认拥有和主 agent 一样的交互权
- 子 agent 可以调工具
- 但这些工具仍然要被持续治理
- 某些 agent 可以更交互
- 某些 agent 必须更自动、更克制
也就是说:
权限不是一次性发证,而是伴随 agent 生命周期持续生效。
13. 为什么这对理解整个 runtime 很重要
因为很多人看到 agent runtime,会把重点只放在:
- prompt
- tool calling
- task orchestration
但真正决定一个系统是否“可上线”的,往往是治理层:
- 权限
- 审批
- hooks
- 限权
- 自动/人工边界
Claude Code 在这块明显花了很多心思。 而 AgentTool 正是能把这些复杂性全部暴露出来的那个模块。
当前结论
权限系统对 AgentTool 的影响,不是“启动前多问一句确认”这么浅。
而是深入到:
- 子 agent 的 permission mode
- 提示是否可见
- 自动检查是否先行
- 允许哪些工具继续执行
- 子 agent 后续每轮工具调用是否持续受控
所以如果你把 AgentTool 理解成“delegate orchestration”, 那权限系统就是它的 治理骨架。
没有这层骨架,AgentTool 只会变成一个无限放大副作用的危险入口。