Skip to content

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)等文件系统级功能。

如果不传 settingSourcesquery() 会自动读取与 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.jsonsettings.json 和钩子从 <cwd>/.claude/ 加载;CLAUDE.md 和规则从 <cwd> 及所有父目录加载;技能从 <cwd> 起向上直到仓库根目录
"user"用户 CLAUDE.md、~/.claude/rules/*.md、用户技能、用户设置~/.claude/
"local"CLAUDE.local.md、.claude/settings.local.jsonsettings.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.mdsettingSources 包含 "project"
项目规则<cwd>/.claude/rules/*.md 以及每个父目录中的 .claude/rules/*.mdsettingSources 包含 "project"
项目(父目录)cwd 上层的 CLAUDE.md 文件settingSources 包含 "project",在会话启动时加载
项目(子目录)cwd 子目录中的 CLAUDE.md 文件settingSources 包含 "project",当代理读取该子树的文件时按需加载
本地<cwd>/CLAUDE.local.md 以及每个父目录中的 CLAUDE.local.mdsettingSources 包含 "local"
用户~/.claude/CLAUDE.mdsettingSources 包含 "user"
用户规则~/.claude/rules/*.mdsettingSources 包含 "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 更多的钩子事件,包括 SessionStartSessionEndTeammateIdleTaskCompleted。完整事件兼容表参见 钩子指南

关于程序化钩子的完整细节,见 用钩子控制执行。关于文件系统钩子的语法,见 钩子

选择合适的功能

Agent SDK 提供了多种扩展代理行为的方式。下表将常见目标映射到对应的实现方法。

你希望…使用SDK 表面
设置代理始终遵守的项目规范CLAUDE.mdsettingSources: ["project"] 自动加载
让代理在相关时加载参考材料技能settingSources + skills 选项
运行可重复的工作流(部署、审查、发布)用户可调用的技能settingSources + skills 选项
将隔离的子任务委托给全新的上下文(研究、审查)子代理agents 参数 + allowedTools: ["Agent"]
协调多个 Claude Code 实例,共享任务列表并支持代理间直接消息代理团队不是通过 SDK 选项直接配置。代理团队是 CLI 功能,一个会话担任团队负责人,协调多个独立工作组成员
在工具调用上执行确定性逻辑(审计、阻止、转换)钩子hooks 参数(含回调)或通过 settingSources 加载的 shell 脚本
为 Claude 提供对外部服务的结构化工具访问MCPmcpServers 参数

子代理 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 控制,默认处于启用状态。