第 3 章:配置选项详解

上一章我们学会了理解 Claude 的消息系统。这一章,我们来搞清楚怎么"调教" Claude —— 通过配置选项,让它按你的要求来干活。

ClaudeAgentOptions — Claude 的遥控器面板

想象一下,你买了一台新空调。拆开遥控器一看,上面有温度、风速、模式、定时……一堆按钮。但你平时用的时候,大部分按钮都不需要碰,按一下开机、调调温度就够了。

ClaudeAgentOptions 就是 Claude 的"遥控器"。它有二十多个"按钮"(配置项),但你完全不需要全部设置。事实上,什么都不设置也能用:

from claude_agent_sdk import query, ClaudeAgentOptions

# 不传任何配置,全部用默认值 —— 完全没问题
async for msg in query(prompt="你好"):
    print(msg)

# 等价于传一个空的配置
options = ClaudeAgentOptions()
async for msg in query(prompt="你好", options=options):
    print(msg)

核心原则:用到哪个设哪个,不需要的别碰。

接下来,我把这些配置项分成五组来讲,从最常用的开始。


第一组:基础配置 — 最常用的三个

这三个配置项你几乎每个项目都会用到。

system_prompt — 告诉 Claude 它是谁

系统提示词就像给 Claude 一份"岗位说明书"。不设置的话,Claude 会用默认的行为。设置了,Claude 就会按你的要求来表现。

options = ClaudeAgentOptions(
    # 简单的字符串提示词
    system_prompt="你是一个 Python 专家,所有回答都用中文,代码注释也用中文。"
)

你也可以用预设值,在默认提示词后面追加内容:

options = ClaudeAgentOptions(
    # 使用预设,再追加自定义内容
    system_prompt={
        "type": "preset",
        "preset": "claude_code",
        "append": "所有回答必须包含代码示例。"
    }
)

model — 选择用哪个模型

Claude 有好几个模型,能力和价格不同。不设置的话用 CLI 的默认模型。

options = ClaudeAgentOptions(
    model="claude-sonnet-4-5"  # 性价比之王,速度快、够聪明
)

常用模型:

模型 特点 适合场景
claude-sonnet-4-5 速度快,价格适中 日常开发、代码生成
claude-opus-4-1-20250805 最强推理能力 复杂架构设计、疑难 bug
claude-haiku-3-5-20241022 速度最快,价格最低 简单任务、批量处理

cwd — 工作目录

告诉 Claude 在哪个目录下干活。Claude 读文件、写文件、执行命令都以这个目录为根目录。

options = ClaudeAgentOptions(
    cwd="/home/user/my-project"  # Claude 会在这个目录下操作
)

不设置的话,默认用当前进程的工作目录。

三个基础配置组合起来:

from claude_agent_sdk import query, ClaudeAgentOptions

options = ClaudeAgentOptions(
    system_prompt="你是一个严格的代码审查员,用中文指出所有问题。",
    model="claude-sonnet-4-5",
    cwd="/home/user/my-project",
)

async for msg in query(prompt="审查 src/ 目录下的所有 Python 文件", options=options):
    print(msg)

第二组:工具配置 — 决定 Claude 能用什么工具

Claude 之所以强大,是因为它不只会说话,还能动手——读文件、写文件、执行命令。这些能力叫做"工具"。工具配置就是控制 Claude 能用哪些工具。

allowed_tools — 工具白名单

只允许 Claude 使用你指定的工具。没在列表里的,Claude 用不了。

options = ClaudeAgentOptions(
    # 只给 Claude 读和搜索的权限,不能写文件、不能执行命令
    allowed_tools=["Read", "Glob", "Grep"]
)

disallowed_tools — 工具黑名单

禁止 Claude 使用某些工具。没在列表里的,Claude 都能用。

options = ClaudeAgentOptions(
    # 不允许执行命令和访问网络,其他都可以
    disallowed_tools=["Bash", "WebFetch", "WebSearch"]
)

内置工具一览

Claude Code 自带的工具有这些:

工具 功能 说明
Read 读文件 读取文件内容
Write 写文件 创建或覆盖整个文件
Edit 编辑文件 替换文件中的部分内容
MultiEdit 批量编辑 一次替换文件中的多处内容
Bash 执行命令 在终端执行 shell 命令
Glob 查找文件 按文件名模式搜索(如 *.py
Grep 搜索内容 在文件内容中搜索文本
WebFetch 抓取网页 获取指定 URL 的内容
WebSearch 搜索网络 在互联网上搜索信息

白名单 vs 黑名单怎么选?

# 场景 1:只做代码审查(只读),用白名单
# 思路:"只允许这几个"
review_options = ClaudeAgentOptions(
    allowed_tools=["Read", "Glob", "Grep"]
)

# 场景 2:正常开发,但不要碰网络,用黑名单
# 思路:"除了这几个都行"
dev_options = ClaudeAgentOptions(
    disallowed_tools=["WebFetch", "WebSearch"]
)

经验法则: 如果你想限制到很少几个工具,用白名单。如果你想开放大部分工具、只禁几个,用黑名单。


第三组:行为限制 — 防止失控

Claude 非常勤奋,有时候你让它做一件事,它可能会连续执行几十轮操作。这两个配置项就像给 Claude 套上"安全绳"。

max_turns — 最多执行几轮

一"轮"就是 Claude 执行一次工具调用或回复一次消息。设置上限,防止 Claude 陷入无限循环。

options = ClaudeAgentOptions(
    max_turns=10  # 最多 10 轮,到了就停
)

max_budget_usd — 最多花多少钱

直接限制这次调用的花费上限。超了就停。强烈建议在生产环境中始终设置此项。

options = ClaudeAgentOptions(
    max_budget_usd=0.50  # 最多花 5 毛钱(美元)
)

两者配合使用

在实际项目中,建议同时设置两个限制。双保险,哪个先到就停:

options = ClaudeAgentOptions(
    max_turns=20,         # 最多 20 轮
    max_budget_usd=1.00,  # 最多花 1 美元
)

实际应用场景参考:

场景 max_turns max_budget_usd 说明
快速问答 3 0.05 简单问题,几轮就够
代码审查 10 0.50 读文件 + 分析,不算太多
功能开发 30 2.00 需要读、写、测试,轮次较多
复杂重构 50 5.00 大规模改动,给够空间

第四组:认证与环境 — 连上 Claude 的钥匙

Claude SDK 支持两种认证方式。选哪种取决于你的使用场景。

方式一:API Key 模式

适合服务端部署、自动化脚本、CI/CD。你有一个 API Key,SDK 用它直接调用 Claude API。

import os

options = ClaudeAgentOptions(
    # 通过 env 参数传递 API Key
    env={
        "ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]
    }
)

或者你也可以直接在环境变量里设好,SDK 会自动读取:

# 终端里设置
export ANTHROPIC_API_KEY="sk-ant-xxxxx"
# 代码里不需要额外配置,SDK 自动读取环境变量
options = ClaudeAgentOptions()

方式二:订阅模式

适合个人开发、本地使用。你有 Claude Pro/Max 订阅,先用 CLI 登录,SDK 就能用了。

# 先在终端登录一次
claude login
# 登录后直接用,不需要额外配置
options = ClaudeAgentOptions()

两种模式对比

对比项 API Key 模式 订阅模式
获取方式 Anthropic Console 创建 Claude Pro/Max 订阅
认证方式 环境变量 ANTHROPIC_API_KEY claude login 登录
费用 按 API 用量计费 包含在订阅内
适合场景 服务端、自动化、CI/CD 个人开发、本地使用
需要网络
代码配置 需设置 env 或环境变量 无需额外配置

env — 传递环境变量

除了 API Key,你还可以通过 env 传递其他环境变量给 Claude CLI 进程:

options = ClaudeAgentOptions(
    env={
        "ANTHROPIC_API_KEY": "sk-ant-xxxxx",
        "MY_CUSTOM_VAR": "some_value",      # 自定义变量
    }
)

cli_path — 指定 CLI 路径

如果你的 Claude CLI 不在系统 PATH 里,可以手动指定路径:

options = ClaudeAgentOptions(
    cli_path="/usr/local/bin/claude"  # 手动指定 claude 命令的位置
)

第五组:高级配置(预览)

这些配置项更进阶,这里先简单介绍一下概念,后续章节会详细展开。

thinking — 扩展思考

让 Claude 在回答之前"想一想"。就像考试时先在草稿纸上演算,再写答案。对复杂问题很有帮助。

# 自适应思考 —— 让 Claude 自己决定要不要思考
options = ClaudeAgentOptions(
    thinking={"type": "adaptive"}
)

# 指定思考预算 —— 最多用 10000 个 token 来思考
options = ClaudeAgentOptions(
    thinking={"type": "enabled", "budget_tokens": 10000}
)

# 关闭思考
options = ClaudeAgentOptions(
    thinking={"type": "disabled"}
)

effort — 思考深度

thinking 更简单的控制方式,直接告诉 Claude 用多大力气想:

options = ClaudeAgentOptions(
    effort="low"     # 快速回答,不深入思考
)

options = ClaudeAgentOptions(
    effort="high"    # 仔细思考,适合复杂问题
)

四个档位:"low" / "medium" / "high" / "max"

permission_mode — 权限模式

控制 Claude 使用工具时的权限级别:

options = ClaudeAgentOptions(
    permission_mode="default"  # 默认模式,危险操作会请求确认
)
模式 说明
"default" 默认模式,危险操作需要确认
"acceptEdits" 自动接受文件编辑
"plan" 规划模式,只分析不执行
"bypassPermissions" 跳过所有权限检查(危险!

权限控制的完整内容请看第 7 章。

hooks — 钩子系统

在 Claude 执行工具前后插入你自己的逻辑。比如:工具调用前检查是否安全,调用后记录日志。

# 简单示例,详细内容请看第 6 章
options = ClaudeAgentOptions(
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Bash",           # 监听 Bash 工具
                hooks=[my_check_function]  # 执行前调用我的检查函数
            )
        ]
    }
)

钩子系统的完整用法请看第 6 章。

output_format — 结构化输出

让 Claude 按照你指定的 JSON Schema 格式返回结果:

options = ClaudeAgentOptions(
    output_format={
        "type": "json_schema",
        "schema": {
            "type": "object",
            "properties": {
                "summary": {"type": "string"},
                "score": {"type": "integer", "minimum": 0, "maximum": 100}
            },
            "required": ["summary", "score"]
        }
    }
)

agents — 子 Agent 定义

创建专门执行特定任务的子 Agent:

from claude_agent_sdk.types import AgentDefinition

options = ClaudeAgentOptions(
    agents={
        "reviewer": AgentDefinition(
            description="代码审查专家",
            prompt="你是一个严格的代码审查员,专注于发现代码中的 bug 和安全问题。",
            model="sonnet",
        ),
    }
)

API Key vs 订阅 — 自动检测

在实际项目中,你可能希望代码能同时兼容两种认证模式。下面是一个实用的自动检测方案:

import os
import shutil

def detect_auth_mode() -> dict:
    """自动检测当前可用的认证模式。"""
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if api_key:
        return {"mode": "api_key", "key": api_key[:12] + "..."}

    # 检查 Claude CLI 是否可用(订阅模式)
    cli_path = shutil.which("claude")
    if cli_path:
        return {"mode": "subscription", "cli": cli_path}

    return {"mode": "none", "error": "未找到认证方式"}


def build_options_for_auth() -> "ClaudeAgentOptions":
    """根据检测到的认证模式构建配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    auth = detect_auth_mode()

    if auth["mode"] == "api_key":
        return ClaudeAgentOptions(
            env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]}
        )
    elif auth["mode"] == "subscription":
        # 订阅模式不需要额外配置
        return ClaudeAgentOptions()
    else:
        raise RuntimeError(
            "未找到认证方式!请设置 ANTHROPIC_API_KEY 环境变量,"
            "或运行 'claude login' 登录。"
        )

完整可运行的示例请看 examples/dual_mode_auth.py


配置最佳实践

1. 最小化原则

只设置你需要的配置项。ClaudeAgentOptions 的每个参数都有合理的默认值,没必要把每个都填上。

# 好 —— 只设置需要的
options = ClaudeAgentOptions(
    system_prompt="你是 Python 专家。",
    max_turns=10,
)

# 没必要 —— 多余的默认值
options = ClaudeAgentOptions(
    system_prompt="你是 Python 专家。",
    max_turns=10,
    model=None,             # 本来就是 None
    cwd=None,               # 本来就是 None
    allowed_tools=[],       # 本来就是空列表
    disallowed_tools=[],    # 本来就是空列表
    env={},                 # 本来就是空字典
    permission_mode=None,   # 本来就是 None
)

2. 安全第一

生产环境中,绝对不要bypassPermissions。这个模式会跳过所有安全检查,Claude 可以随意执行任何操作。

# 开发测试时可以用(方便调试)
dev_options = ClaudeAgentOptions(
    permission_mode="bypassPermissions"
)

# 生产环境 —— 用 acceptEdits 或 default
prod_options = ClaudeAgentOptions(
    permission_mode="acceptEdits",  # 自动接受文件编辑,但其他操作仍需确认
    max_budget_usd=2.00,            # 一定要设预算上限
)

3. 始终设置预算保护

无论什么场景,都建议设置 max_budget_usd。Claude 很能干,但也很能花钱。

# 即使是简单任务,也设个上限
options = ClaudeAgentOptions(
    max_turns=5,
    max_budget_usd=0.10,  # 1 毛钱封顶
)

4. 工具权限要明确

如果你的程序只需要 Claude 分析代码(不需要改代码),就明确限制工具。别给 Claude 多余的权限。

# 只读模式 —— 分析但不修改
readonly_options = ClaudeAgentOptions(
    allowed_tools=["Read", "Glob", "Grep"],
    system_prompt="分析代码并给出建议,但不要修改任何文件。",
)

完整配置速查表

配置项 类型 默认值 一句话说明
system_prompt str \| dict \| None None Claude 的角色设定
model str \| None None 使用哪个模型
cwd str \| Path \| None None 工作目录
allowed_tools list[str] [] 工具白名单
disallowed_tools list[str] [] 工具黑名单
max_turns int \| None None 最大轮次
max_budget_usd float \| None None 预算上限(美元)
env dict[str, str] {} 环境变量
cli_path str \| Path \| None None CLI 路径
permission_mode str \| None None 权限模式
thinking dict \| None None 扩展思考配置
effort str \| None None 思考深度
hooks dict \| None None 钩子系统
agents dict \| None None 子 Agent 定义
output_format dict \| None None 结构化输出格式
mcp_servers dict \| str \| Path {} MCP 服务器配置
sandbox dict \| None None 沙盒配置
continue_conversation bool False 是否继续上次对话
resume str \| None None 恢复指定会话

本章完整示例代码

以下是本章涉及的完整示例文件,可以直接复制运行。

config_playground.py — 配置选项游乐场

from dataclasses import asdict, fields


def print_banner(title: str) -> None:
    """打印一个漂亮的标题横幅。"""
    width = 60
    print()
    print("=" * width)
    print(f"  {title}")
    print("=" * width)


def print_config(name: str, options: object) -> None:
    """打印配置的非默认字段。"""
    print(f"\n  [{name}]")
    config_dict = asdict(options)  # type: ignore[arg-type]
    # 获取所有字段的默认值
    defaults = {}
    for f in fields(options.__class__):
        if f.default is not f.default_factory:  # type: ignore[attr-defined]
            defaults[f.name] = f.default
        else:
            try:
                defaults[f.name] = f.default_factory()  # type: ignore[misc]
            except TypeError:
                defaults[f.name] = None

    # 只显示非默认值的字段
    has_custom = False
    for key, value in config_dict.items():
        default = defaults.get(key)
        if value != default and value is not None:
            print(f"    {key} = {value!r}")
            has_custom = True

    if not has_custom:
        print("    (全部使用默认值)")


def demo_basic_configs() -> None:
    """演示基础配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("第一组:基础配置")

    # 配置 1:最简单 —— 什么都不设
    opts_minimal = ClaudeAgentOptions()
    print_config("最简配置(全默认)", opts_minimal)
    print("    说明: 什么都不设也能用。Claude 使用默认模型、默认提示词、当前目录。")

    # 配置 2:指定角色
    opts_role = ClaudeAgentOptions(
        system_prompt="你是一个 Python 专家,所有回答都用中文。",
    )
    print_config("指定角色", opts_role)
    print("    说明: 给 Claude 一个明确的身份,它会按这个角色来回答。")

    # 配置 3:完整基础配置
    opts_full_basic = ClaudeAgentOptions(
        system_prompt="你是一个严格的代码审查员。",
        model="claude-sonnet-4-5",
        cwd="/home/user/my-project",
    )
    print_config("完整基础配置", opts_full_basic)
    print("    说明: 角色 + 模型 + 工作目录,最常见的配置组合。")


def demo_tool_configs() -> None:
    """演示工具配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("第二组:工具配置")

    # 白名单模式 —— 只读
    opts_readonly = ClaudeAgentOptions(
        allowed_tools=["Read", "Glob", "Grep"],
    )
    print_config("只读模式(白名单)", opts_readonly)
    print("    说明: Claude 只能读文件和搜索,不能写文件、不能执行命令。")
    print("    适合: 代码审查、代码分析。")

    # 黑名单模式 —— 禁止网络
    opts_no_network = ClaudeAgentOptions(
        disallowed_tools=["WebFetch", "WebSearch"],
    )
    print_config("禁止网络(黑名单)", opts_no_network)
    print("    说明: Claude 可以做大部分事情,但不能访问互联网。")
    print("    适合: 离线环境、内网开发。")

    # 白名单 —— 开发模式
    opts_dev = ClaudeAgentOptions(
        allowed_tools=["Read", "Write", "Edit", "MultiEdit", "Bash", "Glob", "Grep"],
    )
    print_config("开发模式(白名单)", opts_dev)
    print("    说明: Claude 可以读写文件、执行命令,但不能上网。")
    print("    适合: 本地功能开发。")


def demo_limit_configs() -> None:
    """演示行为限制配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("第三组:行为限制")

    # 快速问答
    opts_quick = ClaudeAgentOptions(
        max_turns=3,
        max_budget_usd=0.05,
    )
    print_config("快速问答", opts_quick)
    print("    说明: 最多 3 轮,最多花 5 分钱。简单问题够用了。")

    # 日常开发
    opts_daily = ClaudeAgentOptions(
        max_turns=20,
        max_budget_usd=1.00,
    )
    print_config("日常开发", opts_daily)
    print("    说明: 20 轮足够完成一个中等功能,1 美元是合理的上限。")

    # 复杂任务
    opts_heavy = ClaudeAgentOptions(
        max_turns=50,
        max_budget_usd=5.00,
    )
    print_config("复杂任务", opts_heavy)
    print("    说明: 大型重构或复杂调试,给够空间但还是要有上限。")

    # 只限预算
    opts_budget_only = ClaudeAgentOptions(
        max_budget_usd=0.50,
    )
    print_config("只限预算", opts_budget_only)
    print("    说明: 不限轮次,但花到 5 毛钱就停。灵活又安全。")


def demo_auth_configs() -> None:
    """演示认证与环境配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("第四组:认证与环境")

    # API Key 模式
    opts_apikey = ClaudeAgentOptions(
        env={"ANTHROPIC_API_KEY": "sk-ant-xxxxxxxxxxxx"},
    )
    print_config("API Key 模式", opts_apikey)
    print("    说明: 通过 env 传递 API Key。适合服务端部署。")
    print("    提醒: 实际使用时从环境变量读取,别硬编码在代码里!")

    # 订阅模式
    opts_subscription = ClaudeAgentOptions()
    print_config("订阅模式", opts_subscription)
    print("    说明: 什么都不设,前提是已经运行过 'claude login'。")
    print("    适合: 个人本地开发。")

    # 自定义 CLI 路径
    opts_custom_cli = ClaudeAgentOptions(
        cli_path="/opt/claude/bin/claude",
    )
    print_config("自定义 CLI 路径", opts_custom_cli)
    print("    说明: 当 claude 命令不在系统 PATH 中时使用。")


def demo_advanced_configs() -> None:
    """演示高级配置。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("第五组:高级配置(预览)")

    # 扩展思考
    opts_thinking = ClaudeAgentOptions(
        thinking={"type": "enabled", "budget_tokens": 10000},
    )
    print_config("扩展思考", opts_thinking)
    print("    说明: 让 Claude 先在'草稿纸'上想清楚再回答。")
    print("    适合: 复杂的推理、算法设计、架构决策。")

    # 思考深度
    opts_effort = ClaudeAgentOptions(
        effort="high",
    )
    print_config("高强度思考", opts_effort)
    print("    说明: 用 effort 简单控制思考深度,比 thinking 更好上手。")

    # 权限模式
    opts_perm = ClaudeAgentOptions(
        permission_mode="acceptEdits",
    )
    print_config("自动接受编辑", opts_perm)
    print("    说明: Claude 编辑文件时不再弹确认,加快开发效率。")
    print("    注意: 生产环境慎用 bypassPermissions!")

    # 结构化输出
    opts_output = ClaudeAgentOptions(
        output_format={
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "summary": {"type": "string"},
                    "issues": {
                        "type": "array",
                        "items": {"type": "string"},
                    },
                },
                "required": ["summary", "issues"],
            },
        },
    )
    print_config("结构化输出", opts_output)
    print("    说明: 让 Claude 按指定的 JSON 格式返回结果,方便程序解析。")


def demo_real_world_combos() -> None:
    """演示实际项目中的配置组合。"""
    from claude_agent_sdk import ClaudeAgentOptions

    print_banner("实战配置组合")

    # 组合 1:代码审查机器人
    opts_reviewer = ClaudeAgentOptions(
        system_prompt=(
            "你是一个资深的代码审查员。"
            "仔细分析代码,指出潜在的 bug、安全隐患和性能问题。"
            "用中文回答,给出具体的改进建议。"
        ),
        model="claude-sonnet-4-5",
        allowed_tools=["Read", "Glob", "Grep"],
        max_turns=15,
        max_budget_usd=0.50,
        cwd="/home/user/project",
    )
    print_config("代码审查机器人", opts_reviewer)
    print("    说明: 只读权限 + 预算限制 + 专业角色。安全又高效。")

    # 组合 2:自动化开发助手
    opts_developer = ClaudeAgentOptions(
        system_prompt="你是一个高效的 Python 开发者。按要求实现功能,写好测试。",
        model="claude-sonnet-4-5",
        permission_mode="acceptEdits",
        disallowed_tools=["WebFetch", "WebSearch"],
        max_turns=30,
        max_budget_usd=2.00,
        cwd="/home/user/project",
    )
    print_config("自动化开发助手", opts_developer)
    print("    说明: 能读写文件和执行命令,但不能上网。自动接受编辑。")

    # 组合 3:安全审计模式
    opts_audit = ClaudeAgentOptions(
        system_prompt="审查这个项目的安全性,列出所有发现的问题。",
        allowed_tools=["Read", "Glob", "Grep"],
        max_turns=10,
        max_budget_usd=0.30,
        effort="high",
    )
    print_config("安全审计模式", opts_audit)
    print("    说明: 只读 + 高强度思考 + 低预算。专注安全分析。")


def main() -> None:
    """主函数 —— 运行所有配置演示。"""
    print()
    print("Claude Agent SDK 配置选项游乐场")
    print("这个脚本展示不同配置的组装方式和效果说明。")
    print("(不会真的调用 Claude,只展示配置内容)")

    demo_basic_configs()
    demo_tool_configs()
    demo_limit_configs()
    demo_auth_configs()
    demo_advanced_configs()
    demo_real_world_combos()

    print()
    print("=" * 60)
    print("  全部演示完毕!")
    print("  试试修改这些配置,组合出适合你场景的选项。")
    print("=" * 60)
    print()


if __name__ == "__main__":
    main()

运行方式:

python examples/config_playground.py

dual_mode_auth.py — 双模式认证

import os
import shutil
import subprocess


def detect_auth_mode() -> dict:
    """
    自动检测当前可用的认证模式。

    检测顺序:
    1. 先检查是否有 ANTHROPIC_API_KEY 环境变量(API Key 模式)
    2. 再检查 Claude CLI 是否可用(订阅模式)
    3. 都没有则报错

    返回:
        包含认证信息的字典,结构如下:
        - API Key 模式: {"mode": "api_key", "key": "sk-ant-xxxx..."}
        - 订阅模式:     {"mode": "subscription", "cli": "/usr/local/bin/claude"}
        - 未找到:       {"mode": "none", "error": "错误信息"}
    """
    # 第一优先:检查 API Key
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if api_key:
        # 只显示前 12 个字符,保护密钥安全
        masked_key = api_key[:12] + "..." if len(api_key) > 12 else api_key
        return {"mode": "api_key", "key": masked_key}

    # 第二优先:检查 Claude CLI 是否已安装
    cli_path = shutil.which("claude")
    if cli_path:
        # 进一步验证 CLI 是否能正常运行
        try:
            result = subprocess.run(
                [cli_path, "--version"],
                capture_output=True,
                text=True,
                timeout=5,
            )
            if result.returncode == 0:
                version = result.stdout.strip()
                return {
                    "mode": "subscription",
                    "cli": cli_path,
                    "version": version,
                }
        except (subprocess.TimeoutExpired, OSError):
            pass

        # CLI 存在但无法获取版本,仍然可以尝试使用
        return {"mode": "subscription", "cli": cli_path}

    # 都没找到
    return {
        "mode": "none",
        "error": (
            "未找到认证方式!\n"
            "  方式 1: 设置环境变量 ANTHROPIC_API_KEY\n"
            "  方式 2: 安装 Claude CLI 并运行 'claude login'"
        ),
    }


def build_options(
    system_prompt: str = "",
    max_budget_usd: float = 1.0,
) -> "ClaudeAgentOptions":
    """
    根据检测到的认证模式,自动构建 ClaudeAgentOptions。

    参数:
        system_prompt: 系统提示词
        max_budget_usd: 预算上限(美元)

    返回:
        配置好认证信息的 ClaudeAgentOptions

    异常:
        RuntimeError: 未找到任何认证方式时抛出
    """
    from claude_agent_sdk import ClaudeAgentOptions

    auth = detect_auth_mode()

    if auth["mode"] == "api_key":
        # API Key 模式:通过 env 传递
        return ClaudeAgentOptions(
            system_prompt=system_prompt or None,
            max_budget_usd=max_budget_usd,
            env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]},
        )

    elif auth["mode"] == "subscription":
        # 订阅模式:不需要额外设置
        options_kwargs: dict = {
            "max_budget_usd": max_budget_usd,
        }
        if system_prompt:
            options_kwargs["system_prompt"] = system_prompt
        # 如果 CLI 不在默认路径,指定路径
        cli_path = auth.get("cli")
        default_path = shutil.which("claude")
        if cli_path and cli_path != default_path:
            options_kwargs["cli_path"] = cli_path
        return ClaudeAgentOptions(**options_kwargs)

    else:
        raise RuntimeError(auth.get("error", "未知的认证错误"))


def main() -> None:
    """主函数 —— 检测认证模式并展示结果。"""
    print("Claude Agent SDK 认证模式检测")
    print("-" * 40)

    auth = detect_auth_mode()

    if auth["mode"] == "api_key":
        print(f"  认证模式: API Key")
        print(f"  密钥预览: {auth['key']}")
        print()
        print("  配置方式:")
        print('    options = ClaudeAgentOptions(')
        print('        env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]}')
        print("    )")

    elif auth["mode"] == "subscription":
        print(f"  认证模式: 订阅(Claude CLI)")
        print(f"  CLI 路径: {auth['cli']}")
        if "version" in auth:
            print(f"  CLI 版本: {auth['version']}")
        print()
        print("  配置方式:")
        print("    options = ClaudeAgentOptions()  # 无需额外配置")

    else:
        print(f"  认证模式: 未检测到")
        print(f"  错误信息:")
        print(f"    {auth['error']}")

    print()
    print("-" * 40)

    # 尝试构建配置(如果认证可用)
    if auth["mode"] != "none":
        try:
            options = build_options(
                system_prompt="你是一个友好的助手。",
                max_budget_usd=0.10,
            )
            print("  build_options() 成功!配置已就绪。")
            print(f"    system_prompt = {options.system_prompt!r}")
            print(f"    max_budget_usd = {options.max_budget_usd}")
            if options.env:
                # 只显示键名,不显示值
                print(f"    env 包含的键 = {list(options.env.keys())}")
        except Exception as e:
            print(f"  build_options() 失败: {e}")
    else:
        print("  跳过 build_options()(无可用认证)")

    print()


if __name__ == "__main__":
    main()

运行方式:

python examples/dual_mode_auth.py

小结

这一章我们学了 ClaudeAgentOptions 的五组配置:

  1. 基础配置system_promptmodelcwd —— 最常用,几乎每次都要设
  2. 工具配置allowed_toolsdisallowed_tools —— 控制 Claude 能做什么
  3. 行为限制max_turnsmax_budget_usd —— 防止失控和烧钱
  4. 认证环境envcli_path —— 连上 Claude 的钥匙
  5. 高级配置thinkinghookspermission_mode 等 —— 进阶功能

记住核心原则:用到哪个设哪个,安全第一,始终设预算。

下一章,我们进入进阶篇 —— 用 ClaudeSDKClient 实现多轮对话和流式交互。


动手试试: 运行 examples/config_playground.py 看看不同配置组合的效果。

下一章: 第 4 章 - 多轮对话与流式交互