ClaudeCode 中子 Agent 的权限机制

张开发
2026/4/20 0:36:49 15 分钟阅读

分享文章

ClaudeCode 中子 Agent 的权限机制
概述如果子 Agent 尝试使用未在allowed-tools中声明的工具或 Skill,会经历两层拦截,最终被拒绝执行:第一层拦截:工具集过滤(Tool Pool Filtering)子 Agent 启动时,resolveAgentTools()会根据allowed-tools白名单从availableTools中过滤出resolvedTools。不在白名单中的工具根本不会出现在子 Agent 的工具列表中。第二层拦截:权限规则检查(Permission Rules)子 Agent 的getAppState()会重写toolPermissionContext.alwaysAllowRules.session,将allowed-tools写入为 session 级别的 allow 规则。即使某个工具绕过了第一层过滤(比如 MCP tools),在调用时也会经过hasPermissionsToUseTool()的权限检查,发现不在 allow rules 中就会被拒绝。实际结果✅工具不在子 Agent 的工具列表中:Claude 模型看不到这些工具,无法调用✅即使 Claude 猜测调用:权限检查返回deny,执行被拦截✅Skill 同理:Skill 作为 Tool 注册,同样受 allowed-tools 白名单限制⚠️MCP Tools 例外:MCP tools 默认允许(tool.name.startsWith('mcp__')在 filterToolsForAgent 中直接 return true),不受 allowed-tools 限制✅但 MCP 可被 disallowed-tools 禁用:通过disallowedTools字段可显式禁止特定 MCP server完整代码路径 + 核心函数阶段 1:子 Agent 创建时的工具集过滤// 代码路径: /src/tools/AgentTool/agentToolUtils.ts// 核心函数: resolveAgentTools() L122-225// 调用时机: AgentTool.handler() 调用 runAgent() 前exportfunctionresolveAgentTools(agentDefinition:PickAgentDefinition,'tools'|'disallowedTools'|'source'|'permissionMode',availableTools:Tools,isAsync=false,isMainThread=false,):ResolvedAgentTools{const{tools:agentTools,disallowedTools,source,permissionMode}=agentDefinition// === 第一层过滤: filterToolsForAgent() ===// 移除所有 Agent 禁止的工具(AgentTool、SkillTool 等)constfilteredAvailableTools=isMainThread?availableTools// 主线程不过滤:filterToolsForAgent({tools:availableTools,isBuiltIn:source==='built-in',isAsync,permissionMode,})// === 第二层过滤: disallowedTools 黑名单 ===constdisallowedToolSet=newSet(disallowedTools?.map(toolSpec={const{toolName}=permissionRuleValueFromString(toolSpec)returntoolName})??[])constallowedAvailableTools=filteredAvailableTools.filter(tool=!disallowedToolSet.has(tool.name))// === 第三层过滤: allowed-tools 白名单 ===consthasWildcard=agentTools===undefined||(agentTools.length===1agentTools[0]==='*')if(hasWildcard){// 通配符: 返回所有过滤后的工具return{hasWildcard:true,validTools:[],invalidTools:[],resolvedTools:allowedAvailableTools}}// 构建工具名称映射constavailableToolMap=newMapstring,Tool()for(consttoolofallowedAvailableTools){availableToolMap.set(tool.name,tool)}

更多文章