主会话因为权限跑不动某条命令,你转念一想:那派个"子代理"去干这活不就行了?换了执行者,也许就绕过去了。结果它原样回你一句"我无法执行这个命令",路白绕了。
现象
主会话被权限拦住后,改为派一个子代理去执行同一条命令。子代理原样回复"我无法执行这个命令",没有任何区别。同期尝试的替代工具(换个能跑命令的接口)也同样被拒。绕路折腾一圈,问题还在原地。
有个细节值得注意:拒绝的措辞往往和主会话几乎一致。这不是巧合——它说明两边命中的是同一套规则、同一个判定,只是发起人不同。
补充一点:子代理的拒绝通常是"干脆利落"的,没有任何"尝试后失败"的过程——它压根不会发起那条命令。这也是它和"命令执行报错"的区别:前者根本没跑,后者是跑了但出错。
根因:子代理继承父会话的权限模式
这里有个直觉陷阱:我们把"主代理 / 子代理"理解成"上下级"或者"不同的执行者",于是产生一种错觉——换个人来办,规则可能就不一样了。
实际上,子代理继承父会话的权限模式。它既不会、也不能绕过父级的权限限制。这不是"子代理偷懒",而是设计如此:如果子代理能绕开父会话被拒的操作,那权限体系就形同虚设了——任何一次拒绝都可以通过"派个孩子去干"来绕过。
至于"换个工具就能跑"的想法,也走不通:没有任何工具能替代"真正执行脚本"这件事。读取工具读不了、搜索工具搜不了,能产出文件的那一步始终是执行命令,而它恰好就是被拦的那一步。
解决:只能从权限配置层面解
结论很直接——权限类阻塞,只能在权限配置(允许列表 / 权限模式)层面解决。具体动作:
-
确认被拦的到底是哪一类操作。 是执行命令、还是写文件、还是网络访问?不同类别对应不同的配置项。
-
把需要的操作加进允许列表,粒度收窄到刚好够用:
{ "permissions": { "allow": [ "Bash(python /opt/scripts/sync.py:*)", "Bash(git -C /srv/repo pull)" ] } } -
如果确实需要放宽整体策略(例如把会话切到更宽松的权限模式),要清楚这是"我主动放宽了审查",而不是"绕过了一次拒绝"。前者是配置决策,后者是把风险藏起来。
-
验证。 改完配置,用真正会被拦的那条路径重跑一次。
延伸与预防
"换个执行者能不能绕过规则"是权限模型里的经典问题,答案是统一的:不能。 想清楚这点,能省掉很多无效尝试。CI 里换个 runner、容器里换个 user、脚本里换个进程,只要它最终以同一身份、走同一套策略去碰同一份资源,被拒的结果就不会变。
反过来也有个有用的推论:当你发现"换执行者、换工具、换写法"全都失败,且失败信息一致时,基本可以断定这是策略层的问题,直接去查配置,别再改代码了。
再补一句:这套逻辑不只适用于 AI 助手,它其实是所有权限系统的通用规律——权限沿调用链继承,而不是每次调用重新协商。 理解这一点,"为什么换个入口还是不行"就不再需要反复试错了。
还有一点值得记:这类"绕路"尝试本身也是有成本的——每试一种绕法都在消耗时间,而且看起来像在"解决问题",实际上只是在重复验证同一个结论。更高效的做法是:第一次被拒时,就把它判定为权限问题,直接去看配置,而不是动脑筋找替代路径。
一句话教训
"换个执行者"解决不了"规则不允许"。