1. 子 Agent 越权调用工具的真实场景与权限边界设计
多 Agent 协作跑起来之后,最容易翻车的地方不是模型能力,而是权限。我见过一个很典型的例子:主 Agent 负责需求拆解,子 Agent 负责代码审查,结果子 Agent 在审查过程中直接调用了 Write 工具把文件改了,理由是"顺手修复"。这种越权操作在单 Agent 场景下不明显,一旦多个子 Agent 并行跑,谁动了什么文件根本追溯不了。
ClaudeCode 的子 Agent 权限机制就是为解决这个问题设计的。它通过allowed-tools和disallowed-tools两个声明式字段,把子 Agent 能碰的工具集锁死。核心逻辑是两层拦截:第一层在子 Agent 启动时做工具池过滤,不在白名单里的工具根本不会出现在子 Agent 的工具列表中,模型看不到也就调不了;第二层在运行时做权限规则检查,即使某个工具绕过了第一层过滤(比如 MCP tools 有特殊放行逻辑),调用时也会被hasPermissionsToUseTool()拦下来返回 deny。
这套机制适合谁?如果你在用 ClaudeCode 做多 Agent 协作,尤其是让子 Agent 处理代码审查、测试执行、文档生成这类需要明确边界的任务,那allowed-tools就是必须配的。不配的话子 Agent 默认继承主线程的完整工具池,等于给了它一把万能钥匙。
实际配置中还有一个容易忽略的点:子 Agent 的请求端点。默认走官方通道时,多 Agent 并行调用容易触发限流,而且工具调用的审计日志分散在各处。把端点统一改到 TaoToken 的通道(https://taotoken.net/api),配合allowed-tools的权限声明,能做到"谁能调什么工具"和"请求从哪走"两件事都可控。下面从配置到验证一步步来。
2. TaoToken 前置准备:Base URL、API Key 与 Model ID 三件套
在写子 Agent 权限配置之前,先把 TaoToken 的接入信息准备好。这一步不复杂,但三个要素缺一不可:Base URL、API Key、Model ID。很多人卡在 401 就是因为 Key 没配对,或者 Base URL 多写了路径。
Base URL 用https://taotoken.net/api,注意不要加 UTM 参数,API 调用不需要这些。API Key 在控制台的 API Keys 页面生成,生成后复制保存,页面刷新后就不再完整显示。Model ID 根据你用的模型填,比如claude-sonnet-4-20250514这类,具体以文档里的模型列表为准。
如果你用的是 Claude Code 的 settings 配置文件,接入信息写在这个文件里。路径通常是~/.claude/settings.json,Windows 下是%USERPROFILE%\.claude\settings.json。配置片段如下:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }这里有个细节:ANTHROPIC_BASE_URL只写到/api,不要在后面拼/v1/messages,SDK 会自己补全路径。我试过写成https://taotoken.net/api/v1结果请求 404,排查了半天才发现是路径重复了。
如果你用的是 Codex 的auth.json,配置方式不同。Codex 的认证文件在~/.codex/auth.json,需要把 Base URL 和 Key 写进去:
{ "OPENAI_BASE_URL": "https://taotoken.net/api", "OPENAI_API_KEY": "sk-你的TaoToken密钥" }Model ID 在 Codex 里通过--model参数或配置文件指定。三件套齐了之后,先别急着配子 Agent,用一次简单请求验证通道是否通。验证命令:
curl https://taotoken.net/api/v1/messages \ -H "x-api-key: sk-你的TaoToken密钥" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 64, "messages": [{"role": "user", "content": "回复 OK"}] }'返回里能看到content字段有内容就说明通道通了。如果返回 401,检查 Key 是否复制完整;如果返回local proxy failed,检查 Base URL 是否写错或网络是否可达。这一步过了再往下配子 Agent,否则权限配得再对也跑不起来。
3. 可复制的子 Agent 权限配置:allowed-tools 与 disallowed-tools 声明
子 Agent 的定义文件通常放在~/.claude/agents/目录下,每个 Agent 一个 Markdown 文件,用 YAML frontmatter 声明权限。文件名就是 Agent 名,比如code-reviewer.md。下面是一个代码审查子 Agent 的完整配置:
--- name: code-reviewer description: 代码审查专用子 Agent,只读不写 allowed-tools: - Read - Grep - Glob - Bash disallowed-tools: - mcp__github - mcp__filesystem model: claude-sonnet-4-20250514 --- 你是一个代码审查专家。你的职责是阅读代码、发现问题、给出建议。 重要约束: - 你只能读取文件,不能修改任何文件 - 你不能调用 Write、Edit 工具 - 你不能创建子 Agent - 如果发现需要修改的地方,在审查报告中说明,由主 Agent 决定是否修改这个配置里,allowed-tools声明了四个工具:Read 读文件、Grep 搜索内容、Glob 匹配文件路径、Bash 执行命令。disallowed-tools显式禁用了两个 MCP server:mcp__github和mcp__filesystem。注意 MCP tools 在 ClaudeCode 里默认是放行的,不受allowed-tools限制,所以必须用disallowed-tools单独禁。
如果你想让子 Agent 完全不能碰某个工具,即使它不在allowed-tools里也再声明一次到disallowed-tools,这是防御深度的做法。比如:
allowed-tools: - Read - Grep disallowed-tools: - Write - Edit - Agent - SkillTool这里Agent被禁用是为了防止子 Agent 递归创建子 Agent,SkillTool被禁用是因为 Skill 加载会引入额外的工具集,可能绕过白名单。虽然 ClaudeCode 内部有ALL_AGENT_DISALLOWED_TOOLS常量已经禁了这些,但显式声明一遍更保险,也方便团队 review 时一眼看清边界。
配置写完后,主 Agent 在调用子 Agent 时通过 Agent tool 指定agent: code-reviewer即可。子 Agent 启动时会走resolveAgentTools(),把allowed-tools白名单和disallowed-tools黑名单都应用一遍,最终resolvedTools里只有 Read、Grep、Glob、Bash 四个工具。模型在推理时看不到 Write 和 Edit,自然不会去调。
还有一个容易踩的坑:allowed-tools里写工具名时大小写要匹配。ClaudeCode 内部工具名是Read、Write、Edit这种首字母大写,写成read会匹配不上,工具会被标记为invalidTools而不是进入resolvedTools。我试过写成小写,结果子 Agent 一个工具都用不了,排查时看日志才发现是名称不匹配。
4. 验证请求:白名单与黑名单的实际生效结果
配置写好后必须验证,不然你不知道权限到底有没有生效。验证分两步:先看子 Agent 的工具列表,再实际触发一次越权调用看拦截结果。
第一步,启动 ClaudeCode 并加载子 Agent。在项目目录下运行:
claude --agent code-reviewer进入交互后,让子 Agent 列出它可用的工具。你可以直接问:"你当前可以使用哪些工具?" 子 Agent 会基于resolvedTools回答。如果配置正确,它应该只提到 Read、Grep、Glob、Bash,不会提到 Write、Edit、Agent。
第二步,故意触发越权调用。给子 Agent 一个需要写文件的指令,比如:"请把 main.ts 里的 console.log 删掉。" 子 Agent 会尝试调用 Write 或 Edit,但这两个工具不在它的工具列表里,模型看不到,所以它不会直接调用。如果模型"猜测"调用(在某些 prompt 下可能发生),权限检查会返回 deny,错误消息是:
Permission to use Write has been denied.这个错误会作为 tool_result 返回给模型,模型收到后重新推理,通常会回复"我没有写文件的权限,建议由主 Agent 执行修改"。
第三步,验证 MCP 黑名单。如果你配了disallowed-tools: [mcp__github],让子 Agent 尝试调用 GitHub MCP 工具,比如:"查一下这个仓库的 issue 列表。" 子 Agent 会尝试调用mcp__github__list_issues,但disallowed-tools会在resolveAgentTools()的黑名单过滤阶段把它移除,模型看不到这个工具。如果模型猜测调用,权限检查同样返回 deny。
验证时可以用--debug参数看详细日志:
claude --agent code-reviewer --debug日志里会打印resolveAgentTools的过滤结果,包括validTools、invalidTools、resolvedTools三个列表。resolvedTools里只有白名单工具就说明配置生效了。如果看到某个工具出现在invalidTools里,说明工具名拼写有问题或者该工具不在availableTools中。
实测下来,白名单和黑名单同时配的时候,黑名单优先级更高。也就是说,如果一个工具同时在allowed-tools和disallowed-tools里,它会被禁用。这个行为符合"最小权限"原则,但配置时要注意别把想用的工具误禁了。
5. 本篇常见错排查:401、local proxy failed、reading choices 与 OAuth
配子 Agent 权限时遇到的报错,大部分不在权限本身,而在接入通道或配置格式。下面按真实报错逐个排查。
401 Unauthorized:最常见。原因通常是 API Key 没配、配错位置、或者 Key 失效。检查~/.claude/settings.json里的ANTHROPIC_API_KEY是否填了 TaoToken 的 Key,注意不要有多余空格。如果用的是环境变量,确认echo $ANTHROPIC_API_KEY能输出正确值。还有一种情况是 Key 复制时漏了前缀sk-,补上即可。
local proxy failed:这个报错说明请求没发出去,通常是 Base URL 写错或网络不可达。检查ANTHROPIC_BASE_URL是否为https://taotoken.net/api,不要多写/v1或/messages。如果 Base URL 正确,用 curl 直接测一下通道是否通,排除网络问题。
reading choices 报错:这个通常出现在用 OpenAI 兼容接口调 Claude 模型时,响应格式不匹配。ClaudeCode 走的是 Anthropic 原生接口,如果你在配置里混用了 OpenAI 的 SDK 或参数,会报reading 'choices'之类的错误。解决方法是确认ANTHROPIC_BASE_URL指向 Anthropic 兼容端点,不要用 OpenAI 的/v1/chat/completions路径。
OAuth 相关报错:如果你之前用官方 OAuth 登录过,配置文件里可能残留了 OAuth token,和 API Key 冲突。检查~/.claude/目录下是否有credentials.json之类的文件,有的话备份后删除,强制走 API Key 认证。另外 Codex 的auth.json里如果同时有 OAuth 和 API Key 字段,也可能冲突,保留 API Key 相关字段即可。
子 Agent 工具列表为空:权限配置写了但子 Agent 一个工具都用不了。检查allowed-tools里的工具名大小写是否匹配,Read不能写成read。另外确认工具名是否在 ClaudeCode 的内置工具列表里,自定义工具需要先注册才能被allowed-tools引用。
MCP 工具禁不掉:配了disallowed-tools: [mcp__github]但子 Agent 还是能调 GitHub MCP。检查 MCP server 名称是否写对,mcp__github对应的是名为github的 MCP server,如果你注册时用的名字是gh,那要写成mcp__gh。名称在 MCP 配置文件里能看到。
排查时建议开--debug日志,resolveAgentTools的过滤结果会打印出来,哪个工具被过滤、哪个被保留一目了然。大部分权限问题看日志就能定位。
6. 把子 Agent 请求统一到 TaoToken 通道的长期实践
子 Agent 权限配好之后,最后一个环节是把请求端点统一到 TaoToken 通道。这件事的价值在多 Agent 并行时特别明显:所有子 Agent 的请求走同一个 Base URL,审计日志集中,限流策略统一,不用每个 Agent 单独配一套认证。
配置方式在 §2 已经给了,这里补充几个长期使用的注意点。第一,ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY建议放在环境变量里而不是硬编码在 settings.json,这样换 Key 不用改文件。第二,如果团队多人协作,把 settings.json 里的敏感字段抽出来,用.env文件管理,.env加入.gitignore。第三,子 Agent 的 Model ID 可以单独指定,比如审查类子 Agent 用便宜快速的模型,主 Agent 用能力强的模型,在 Agent 定义文件的 frontmatter 里写model:字段即可。
如果你需要长期跑编码类 Agent,或者多个子 Agent 协作完成一个完整任务,可以考虑用 Coding Plan 来管理调用配额和模型路由。接入文档里有详细的配置说明,API Keys 页面可以生成和管理密钥。模型对话入口适合快速验证某个模型在子 Agent 场景下的表现,不用改配置就能试。
实际用下来,子 Agent 权限机制的核心就一句话:白名单声明能用的,黑名单声明不能用的,MCP 单独处理,端点统一走 TaoToken。配置不复杂,但每一步都要验证,不然权限配了等于没配。