Appearance
Agent SDK 的 settingSources 参数决定了代理从文件系统加载哪些设置:用户级、项目级和本地级。默认全部加载(等同于 ["user","project","local"]),传入空数组可切换到纯程序化配置。注意:托管策略、全局 ~/.claude.json 和自动内存(autoMemoryEnabled)不受 settingSources 控制,多租户部署需要额外在 env 中传入 CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。代码示例见 Python 和 TypeScript 两段。
Claude Code SDK 功能配置:settingSources、项目指令、技能与钩子
Agent SDK 与 Claude Code CLI 共享同一套文件系统基础,因此 SDK 代理也能访问项目指令(CLAUDE.md 和规则)、技能(Skills)、钩子(Hooks)等文件系统级功能。
如果不传 settingSources,query() 会自动读取与 CLI 相同的文件系统设置(用户、项目、本地三种来源的配置文件)。若想完全禁用文件系统加载(只保留程序化配置),传入 settingSources: []。不过托管策略和全局配置仍然会被读取。详见 settingSources 不控制的内容。
各功能的概念介绍与场景选择,请参考 扩展 Claude Code。
用 settingSources 控制文件系统设置加载
settingSources 参数(Python 中为 setting_sources,TypeScript 中为 settingSources)控制 SDK 加载哪些文件系统设置。传入明确的列表则只加载列出的来源;传入空数组则完全禁用用户、项目和本地设置。
以下示例只加载用户级和项目级设置:
python
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async for message in query(
prompt="Help me refactor the auth module",
options=ClaudeAgentOptions(
# "user" 加载 ~/.claude/ 中的设置,"project" 加载当前工作目录下 .claude/ 的设置
# 两者共同提供 CLAUDE.md、技能、钩子和权限
setting_sources=["user", "project"],
allowed_tools=["Read", "Edit", "Bash"],
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print(block.text)
if isinstance(message, ResultMessage) and message.subtype == "success":
print(f"\nResult: {message.result}")typescript
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Help me refactor the auth module",
options: {
// "user" 加载 ~/.claude/ 中的设置,"project" 加载当前工作目录下 .claude/ 的设置
// 两者共同提供 CLAUDE.md、技能、钩子和权限
settingSources: ["user", "project"],
allowedTools: ["Read", "Edit", "Bash"]
}
})) {
if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "text") console.log(block.text);
}
}
if (message.type === "result" && message.subtype === "success") {
console.log(`\nResult: ${message.result}`);
}
}每个来源从特定位置加载设置,其中 <cwd> 是 cwd 参数指定的工作目录,未指定则使用进程当前目录。完整的类型定义参见 SettingSource(TypeScript) 或 SettingSource(Python)。
| 来源 | 加载内容 | 位置 |
|---|---|---|
"project" | 项目 CLAUDE.md、.claude/rules/*.md、项目技能、项目钩子、项目 settings.json | settings.json 和钩子从 <cwd>/.claude/ 加载;CLAUDE.md 和规则从 <cwd> 及所有父目录加载;技能从 <cwd> 起向上直到仓库根目录 |
"user" | 用户 CLAUDE.md、~/.claude/rules/*.md、用户技能、用户设置 | ~/.claude/ |
"local" | CLAUDE.local.md、.claude/settings.local.json | settings.local.json 从 <cwd>/.claude/ 加载;CLAUDE.local.md 从 <cwd> 及所有父目录加载 |
省略 settingSources 等价于 ["user", "project", "local"]。
cwd 选项决定了 SDK 查找项目级输入的起始目录。CLAUDE.md 和规则从 <cwd> 及所有父目录加载;技能从 <cwd> 起向上直到仓库根目录;项目级的 settings.json 和钩子只从 <cwd>/.claude/ 加载,不会向上回溯父目录。
settingSources 不控制的配置项
settingSources 只覆盖用户、项目和本地设置。以下几项输入无论 settingSources 的值都会被读取:
| 输入 | 行为 | 禁用方法 |
|---|---|---|
| 托管策略设置 | 宿主机上存在即加载 | 移除托管策略文件 |
~/.claude.json 全局配置 | 始终读取 | 通过 env 中的 CLAUDE_CONFIG_DIR 重定位 |
自动记忆 ~/.claude/projects/<project>/memory/ | 默认加载到系统提示中 | 在设置中关闭 autoMemoryEnabled: false,或在 env 中设置 CLAUGE_CODE_DISABLE_AUTO_MEMORY=1 |
不要依赖默认的
query()选项来做多租户隔离。由于以上输入不受settingSources控制,同一个 SDK 进程可能会读取宿主配置和目录记忆。多租户部署时,应让每个租户运行在自己的文件系统下,同时设置settingSources: []并在env中加上CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。详见 安全部署。
项目指令(CLAUDE.md 与规则)
CLAUDE.md 文件和 .claude/rules/*.md 为代理提供持久的项目上下文:编码习惯、构建命令、架构决策和指令。当 settingSources 包含 "project" 时(如上面的示例),SDK 在会话启动时将这些文件加载到上下文中,代理会遵守项目约定,无需在每条提示中重复。
CLAUDE.md 加载位置
| 层级 | 位置 | 加载时机 |
|---|---|---|
| 项目(根) | <cwd>/CLAUDE.md 或 <cwd>/.claude/CLAUDE.md | settingSources 包含 "project" |
| 项目规则 | <cwd>/.claude/rules/*.md 以及每个父目录中的 .claude/rules/*.md | settingSources 包含 "project" |
| 项目(父目录) | cwd 上层的 CLAUDE.md 文件 | settingSources 包含 "project",在会话启动时加载 |
| 项目(子目录) | cwd 子目录中的 CLAUDE.md 文件 | settingSources 包含 "project",当代理读取该子树的文件时按需加载 |
| 本地 | <cwd>/CLAUDE.local.md 以及每个父目录中的 CLAUDE.local.md | settingSources 包含 "local" |
| 用户 | ~/.claude/CLAUDE.md | settingSources 包含 "user" |
| 用户规则 | ~/.claude/rules/*.md | settingSources 包含 "user" |
各层级是累加的:项目级和用户级的 CLAUDE.md 文件若同时存在,代理会看到两者。层级之间没有硬性优先级冲突规则;如果指令冲突,结果取决于 Claude 如何解释。请编写无冲突的规则,或在更具体的文件中明确说明优先级(例如“本项目指令覆盖任何冲突的用户级默认值”)。
你还可以直接通过
systemPrompt注入上下文,无需使用 CLAUDE.md 文件。详见 修改系统提示。当你想让交互式 Claude Code 会话和 SDK 代理共享相同的上下文时,推荐使用 CLAUDE.md。
关于如何组织 CLAUDE.md 的内容,参见 管理 Claude 的记忆。
技能(Skills)
技能是 markdown 文件,为代理提供专业知识和可调用的工作流。与 CLAUDE.md(每次会话都加载)不同,技能按需加载。代理启动时只获取技能描述,当相关时才加载完整内容。
技能通过 settingSources 从文件系统自动发现。如果在 query() 中省略了 skills 参数,则启用已发现的用户和项目技能,并且 Skill 工具可用,与 CLI 行为一致。若要控制哪些技能可用,将 skills 设为 "all"、技能名称列表,或 [] 以禁用所有。SDK 在设置 skills 后会自动启用 Skill 工具,无需再将其添加到 allowedTools 中。
python
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
# 当 settingSources 包含 "project" 时,.claude/skills/ 中的技能会自动被发现
async for message in query(
prompt="Review this PR using our code review checklist",
options=ClaudeAgentOptions(
setting_sources=["user", "project"],
skills="all",
allowed_tools=["Read", "Grep", "Glob"],
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)typescript
import { query } from "@anthropic-ai/claude-agent-sdk";
// 当 settingSources 包含 "project" 时,.claude/skills/ 中的技能会自动被发现
for await (const message of query({
prompt: "Review this PR using our code review checklist",
options: {
settingSources: ["user", "project"],
skills: "all",
allowedTools: ["Read", "Grep", "Glob"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}技能必须作为文件系统产物创建(
.claude/skills/<name>/SKILL.md)。SDK 没有程序化注册技能的 API。详细信息参见 SDK 中的技能。
关于创建和使用技能的更多内容,见 SDK 中的技能。
钩子(Hooks)
SDK 支持两种定义钩子的方式,它们可以并行运行:
- 文件系统钩子:定义在
settings.json中的 shell 命令,当settingSources包含相关来源时加载。这些钩子与 交互式 Claude Code 会话 中配置的钩子相同。 - 程序化钩子:直接传给
query()的回调函数,在你的应用进程中运行,可以返回结构化决策。详见 用钩子控制执行。
两种类型在同一个钩子生命周期内执行。如果你已经在项目的 .claude/settings.json 中配置了钩子,并且设置了 settingSources: ["project"],这些钩子会自动在 SDK 中运行,无需额外配置。
钩子回调接收工具输入并返回一个决策字典。返回空字典 {} 表示允许工具继续;返回 {"decision": "block", "reason": "..."} 阻止执行,原因将作为工具结果发送给 Claude。完整回调签名和返回类型参见 钩子指南。
python
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, ResultMessage
# PreToolUse 钩子回调。位置参数:
# input_data: HookInput 字典,包含 tool_name、tool_input、hook_event_name
# tool_use_id: str | None,被拦截的工具调用 ID
# context: HookContext,携带会话元数据
async def audit_bash(input_data, tool_use_id, context):
command = input_data.get("tool_input", {}).get("command", "")
if "rm -rf" in command:
return {"decision": "block", "reason": "Destructive command blocked"}
return {} # 空字典:允许工具继续
# 文件系统钩子来自 .claude/settings.json,当 settingSources 加载它们时自动运行
# 你也可以添加程序化钩子:
async for message in query(
prompt="Refactor the auth module",
options=ClaudeAgentOptions(
setting_sources=["project"], # 加载 .claude/settings.json 中的钩子
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[audit_bash]),
]
},
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)typescript
import { query, type HookInput, type HookJSONOutput } from "@anthropic-ai/claude-agent-sdk";
// PreToolUse 钩子回调。HookInput 是一个基于 hook_event_name 的联合类型(discriminated union)
// 通过判断 hook_event_name 可以缩小类型,从而获得该事件正确的 tool_input 形状
const auditBash = async (input: HookInput): Promise<HookJSONOutput> => {
if (input.hook_event_name !== "PreToolUse") return {};
const toolInput = input.tool_input as { command?: string };
if (toolInput.command?.includes("rm -rf")) {
return { decision: "block", reason: "Destructive command blocked" };
}
return {}; // 空对象:允许工具继续
};
// 文件系统钩子来自 .claude/settings.json,当 settingSources 加载它们时自动运行
// 你也可以添加程序化钩子:
for await (const message of query({
prompt: "Refactor the auth module",
options: {
settingSources: ["project"], // 加载 .claude/settings.json 中的钩子
hooks: {
PreToolUse: [{ matcher: "Bash", hooks: [auditBash] }]
}
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}两种钩子类型的使用场景
| 钩子类型 | 最佳用途 |
|---|---|
文件系统(settings.json) | 在 CLI 和 SDK 会话间共享钩子。支持 "command"(shell 脚本)、"http"(POST 到端点)、"mcp_tool"(调用已连接的 MCP 服务器的工具)、"prompt"(LLM 评估提示)以及 "agent"(生成验证代理)。这些钩子在主代理及其生成的任意子代理中触发。 |
程序化(query() 中的回调) | 应用特定逻辑;返回结构化决策;进程内集成。作用域仅限于主会话。 |
TypeScript SDK 支持比 Python 更多的钩子事件,包括
SessionStart、SessionEnd、TeammateIdle和TaskCompleted。完整事件兼容表参见 钩子指南。
关于程序化钩子的完整细节,见 用钩子控制执行。关于文件系统钩子的语法,见 钩子。
选择合适的功能
Agent SDK 提供了多种扩展代理行为的方式。下表将常见目标映射到对应的实现方法。
| 你希望… | 使用 | SDK 表面 |
|---|---|---|
| 设置代理始终遵守的项目规范 | CLAUDE.md | settingSources: ["project"] 自动加载 |
| 让代理在相关时加载参考材料 | 技能 | settingSources + skills 选项 |
| 运行可重复的工作流(部署、审查、发布) | 用户可调用的技能 | settingSources + skills 选项 |
| 将隔离的子任务委托给全新的上下文(研究、审查) | 子代理 | agents 参数 + allowedTools: ["Agent"] |
| 协调多个 Claude Code 实例,共享任务列表并支持代理间直接消息 | 代理团队 | 不是通过 SDK 选项直接配置。代理团队是 CLI 功能,一个会话担任团队负责人,协调多个独立工作组成员 |
| 在工具调用上执行确定性逻辑(审计、阻止、转换) | 钩子 | hooks 参数(含回调)或通过 settingSources 加载的 shell 脚本 |
| 为 Claude 提供对外部服务的结构化工具访问 | MCP | mcpServers 参数 |
子代理 vs 代理团队:子代理是临时的、隔离的:全新的对话,一个任务,汇总结果返回父代理。代理团队协调多个独立的 Claude Code 实例,它们共享一个任务列表并直接相互发送消息。代理团队是 CLI 功能。参见 子代理继承什么 和 代理团队对比。
启用的每个功能都会增加代理的上下文窗口用量。各功能成本以及它们如何叠加,请见 扩展 Claude Code - 了解上下文成本。
相关资源
- 扩展 Claude Code:所有扩展功能的概念总览,包含对比表和上下文成本分析
- SDK 中的技能:程序化使用技能的完整指南
- 子代理:定义和调用子代理处理隔离子任务
- 钩子:在关键执行点拦截和控制代理行为
- 权限:通过模式、规则和回调控制工具访问
- 系统提示:无需 CLAUDE.md 文件即可注入上下文
常见问题
如何完全禁用所有文件系统设置,只用程序化配置?
在 query() 中传入 settingSources: []。注意:托管策略、~/.claude.json 和自动内存仍会被读取,多租户环境需要额外设置 CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。
我只想加载项目设置,不加载用户设置,怎么办?
query() 的 options 中配置 settingSources: ["project"] 即可。这样只会从 <cwd>/.claude/ 及父目录加载项目 CLAUDE.md、规则、技能和钩子,不会读取 ~/.claude/。
自动记忆(auto memory)在哪里关闭?
在项目设置中设置 autoMemoryEnabled: false,或在 env 环境变量中设置 CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。注意该功能不受 settingSources 控制,默认处于启用状态。