
Claude Code SDK #4:内置工具全解——11 种工具 × 5 种权限模式,精准控制 Agent 能干什么
SDK 内置 11 种工具(Read/Write/Edit/Bash/Glob/Grep/WebSearch 等),搭配 allowed_tools、disallowed_tools 两个过滤器和 5 种 permission_mode,构成一套完整的工具权限体系。本篇完整拆解 11 种工具的能力范围、两个过滤器的本质区别、权限评估的 5 步顺序,附三种典型配置代码示例和选型建议。
Research Brief
给 Agent 太多权限,你睡觉时它帮你把
node_modules 删了;给太少,它跑两步就卡住。这是很多人上手 Claude Code SDK 后遇到的第一个真实问题:工具到底怎么配?
SDK 内置了 11 种工具,搭配一套五档权限模式和两个过滤器,能精确控制每次
query() 调用时 Agent 可以碰什么、不能碰什么。本篇把这套机制从头到尾拆一遍。11 种内置工具,先看全貌
区别于 Client SDK 需要开发者自己实现工具循环,Agent SDK 的工具是开箱即用的1。Claude 自主判断调用时机,你只需要告诉它允许用哪些:
| 工具 | 做什么 |
|---|---|
Read | 读取工作目录下的任意文件 |
Write | 创建新文件 |
Edit | 对已有文件做精准修改(非整体覆盖) |
Bash | 执行终端命令、脚本、git 操作 |
Monitor | 监听后台脚本,把每行输出当事件处理 |
Glob | 按模式匹配查找文件,如 **/*.ts |
Grep | 用正则搜索文件内容 |
WebSearch | 搜索网络获取实时信息 |
WebFetch | 抓取并解析指定网页 |
AskUserQuestion | 向用户提出澄清问题(支持多选) |
Agent | 调用子代理,需显式加入 allowed_tools |
Agent 工具要单独关注:它允许 Claude 生成子代理来处理子任务,但只有你把 Agent 写进 allowed_tools 才会激活。多 Agent 编排的话题后面会单独一期讲,这里先记住它需要显式开启2。
allowed_tools vs disallowed_tools:两个过滤器的本质区别
很多人会把这两个参数混着理解,其实它们作用在权限评估的不同位置,效果也完全不同。
allowed_tools:预批准清单列在这里的工具,调用时不需要任何额外确认,直接通过。没列的工具不是被禁止了,而是进入后续的
permission_mode 和 canUseTool 流程。from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="分析这个仓库里的所有 Python 文件,找出潜在的安全问题",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"], # 这三个直接放行,不追问
),
):
if hasattr(message, "result"):
print(message.result)disallowed_tools:硬屏蔽规则效果更激进。裸工具名(如
"Bash")会直接把这个工具从 Claude 的上下文里移除——Claude 根本看不见它,更无法调用。作用域写法(如
"Bash(rm *)")更细粒度:Bash 工具本身还在,但凡调用里包含 rm * 的请求,即使在 bypassPermissions 模式下也会被拦截。options = ClaudeAgentOptions(
disallowed_tools=["Write", "Edit", "Bash(rm *)"],
)这个配置下,Claude 能读文件、能搜索,但不能创建新文件、不能改已有文件,更不能执行删除命令。适合只读分析场景。
5 种 permission_mode:从最严格到最宽松
allowed_tools 和 disallowed_tools 是条目级的控制,permission_mode 是全局基调。两者叠加使用。| 模式 | 行为 | 典型场景 |
|---|---|---|
default | 未匹配规则的工具触发 canUseTool 回调 | 交互式开发,需要人工确认 |
dontAsk | 未预批准的工具直接拒绝,不问用户 | 无人值守脚本,固定工具范围 |
acceptEdits | 自动批准文件读写操作,其他工具走正常流程 | 快速原型开发,信任 Claude 编辑 |
plan | 只允许只读工具,Claude 仅分析不修改 | 代码评审、修改前先出方案 |
bypassPermissions | 跳过所有权限检查,全部放行 | 完全受控的沙盒环境 |
TypeScript SDK 还有一个
auto 模式,让模型分类器对每次工具调用做批准/拒绝判断,Python SDK 目前没有。
dontAsk + allowed_tools 的锁定组合是生产环境最常用的模式之一:# TypeScript 示例
const options = {
allowedTools: ["Read", "Glob", "Grep"],
permissionMode: "dontAsk",
};
// 效果:只有这三个工具能跑,其他所有工具调用直接拒绝,不发起询问bypassPermissions 有一个容易踩的坑:allowed_tools 管不住它。没有被 disallowed_tools 拦截的工具,在 bypassPermissions 模式下都会被放行——即使那个工具没在 allowed_tools 里。如果你想在 bypassPermissions 下禁止某个工具,必须用 disallowed_tools,不能只靠 allowed_tools 的「不列出」来限制2。权限评估的 5 步顺序
每次 Claude 要调用一个工具,SDK 按以下顺序依次判断:
- 运行 Hooks:PreToolUse hook 可直接拒绝,但 hook 返回 allow 不会跳过后续步骤
- 检查 deny 规则:
disallowed_tools匹配则立即拦截,bypassPermissions也不例外 - 应用当前 permission_mode:
bypassPermissions放行一切,acceptEdits放行文件操作 - 检查 allow 规则:
allowed_tools匹配则批准 - 调用
canUseTool回调:dontAsk模式在此步直接拒绝
理解这个顺序的关键:deny 规则在
bypassPermissions 之前执行。这意味着如果你想在完全开放的沙盒里保留一条底线(比如任何情况下都不允许 rm -rf),用 disallowed_tools=["Bash(rm -rf *)"] 就够了。Loading content card…
代码组合示例:三种典型配置
配置一:只读代码分析 Agent
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def analyze_codebase():
async for message in query(
prompt="找出所有 TODO 注释并生成汇总报告",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"],
permission_mode="dontAsk", # 固定工具范围,不询问
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(analyze_codebase())配置二:受控写入 Agent(允许编辑,禁止删除)
options = ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Write", "Bash"],
disallowed_tools=["Bash(rm *)", "Bash(rmdir *)"], # 显式拦截删除命令
permission_mode="acceptEdits",
)配置三:沙盒全开 + 保留底线
options = ClaudeAgentOptions(
disallowed_tools=["WebSearch", "WebFetch"], # 断网,但代码工具全开
permission_mode="bypassPermissions",
)子代理继承的注意点
父代理设置了
bypassPermissions、acceptEdits 或 auto 时,所有子代理自动继承该模式,无法在子代理层级单独覆盖。子代理会拿到和父代理完全一样的系统级权限。这在多 Agent 编排时需要格外注意:如果不希望子代理拥有父代理的全部权限,需要在父代理层用更保守的权限模式,或者通过
disallowed_tools 显式屏蔽敏感工具。实践建议
用一句话描述选型逻辑:从最小权限开始,按实际需要逐步放开。
具体来说:
- 先列出
allowed_tools白名单,不需要的工具不要加。Bash特别危险,只有真正需要执行命令时才加入 - 对
Bash用作用域写法精细化限制,比如allowed_tools=["Bash(git log *)"]只允许 git 只读命令 - 无人值守脚本一律用
dontAsk,防止 Claude 在执行过程中等待用户输入而卡死 bypassPermissions只在沙盒或测试环境中用,生产代码里出现它需要在代码审查时重点关注- 要屏蔽的底线用
disallowed_tools而非依赖「不加进 allowed_tools」,两者的覆盖范围不同
下一期:Session 机制之后,流式输出(Streaming)是另一个高频用到的能力——
stream-json 模式下如何解析消息流、处理长任务的实时输出,以及如何在流式场景下复用 session。123
Add more perspectives or context around this Drop.