claude-agent-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Claude Agent SDK

Claude Agent SDK

Provides patterns and best practices for building production AI agents using the Claude Agent SDK (Python:
claude-agent-sdk
, TypeScript:
@anthropic-ai/claude-agent-sdk
).
为使用Claude Agent SDK(Python版:
claude-agent-sdk
,TypeScript版:
@anthropic-ai/claude-agent-sdk
)构建生产级AI Agent提供模式与最佳实践。

Installation

安装

bash
undefined
bash
undefined

TypeScript

TypeScript

npm install @anthropic-ai/claude-agent-sdk
npm install @anthropic-ai/claude-agent-sdk

Python (uv — recommended)

Python(推荐使用uv)

uv add claude-agent-sdk
uv add claude-agent-sdk

Python (pip)

Python(pip)

pip install claude-agent-sdk

Set the API key before running any agent:

```bash
export ANTHROPIC_API_KEY=your-api-key
Third-party providers are also supported: set
CLAUDE_CODE_USE_BEDROCK=1
,
CLAUDE_CODE_USE_VERTEX=1
, or
CLAUDE_CODE_USE_FOUNDRY=1
alongside the respective cloud credentials.
pip install claude-agent-sdk

在运行任何代理前设置API密钥:

```bash
export ANTHROPIC_API_KEY=your-api-key
同时支持第三方提供商:设置
CLAUDE_CODE_USE_BEDROCK=1
CLAUDE_CODE_USE_VERTEX=1
CLAUDE_CODE_USE_FOUNDRY=1
,并配置对应云服务的凭证。

Core Pattern: The
query()
Function

核心模式:
query()
函数

Every agent is built around
query()
, which returns an async iterator of streamed messages:
python
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    async for message in query(
        prompt="Find and fix the bug in auth.py",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],
            permission_mode="acceptEdits",
        ),
    ):
        if hasattr(message, "result"):
            print(message.result)

asyncio.run(main())
typescript
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Find and fix the bug in auth.py",
  options: { allowedTools: ["Read", "Edit", "Glob"], permissionMode: "acceptEdits" }
})) {
  if ("result" in message) console.log(message.result);
}
The loop ends when Claude finishes or hits an error. The SDK handles tool execution, context management, and retries internally.
每个代理都围绕
query()
构建,它返回一个流式消息的异步迭代器:
python
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    async for message in query(
        prompt="Find and fix the bug in auth.py",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],
            permission_mode="acceptEdits",
        ),
    ):
        if hasattr(message, "result"):
            print(message.result)

asyncio.run(main())
typescript
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Find and fix the bug in auth.py",
  options: { allowedTools: ["Read", "Edit", "Glob"], permissionMode: "acceptEdits" }
})) {
  if ("result" in message) console.log(message.result);
}
当Claude完成任务或出现错误时,循环结束。SDK会在内部处理工具执行、上下文管理和重试逻辑。

Built-in Tools

内置工具

Grant only the tools the agent actually needs — principle of least privilege:
ToolPurpose
Read
Read any file in the working directory
Write
Create new files
Edit
Make precise edits to existing files
Bash
Run terminal commands, scripts, git operations
Glob
Find files by pattern (
**/*.ts
,
src/**/*.py
)
Grep
Search file contents with regex
WebSearch
Search the web for current information
WebFetch
Fetch and parse web page content
AskUserQuestion
Ask the user clarifying questions
Task
Spawn subagents (required when using subagents)
仅授予代理实际需要的工具——遵循最小权限原则:
工具用途
Read
读取工作目录中的任意文件
Write
创建新文件
Edit
对现有文件进行精准编辑
Bash
运行终端命令、脚本、Git操作
Glob
按模式查找文件(如
**/*.ts
src/**/*.py
Grep
使用正则表达式搜索文件内容
WebSearch
联网搜索最新信息
WebFetch
获取并解析网页内容
AskUserQuestion
向用户询问澄清性问题
Task
生成子代理(使用子代理时必须配置)

Recommended tool sets by use case

按场景推荐工具组合

Use caseTools
Read-only analysis
Read
,
Glob
,
Grep
Code modification
Read
,
Edit
,
Write
,
Glob
,
Grep
Full automation
Read
,
Edit
,
Write
,
Bash
,
Glob
,
Grep
Web-augmentedAdd
WebSearch
,
WebFetch
to any set
Subagent orchestrationAdd
Task
to the parent agent's set
使用场景工具
只读分析
Read
,
Glob
,
Grep
代码修改
Read
,
Edit
,
Write
,
Glob
,
Grep
全自动化
Read
,
Edit
,
Write
,
Bash
,
Glob
,
Grep
联网增强在任意组合中添加
WebSearch
,
WebFetch
子代理编排在父代理的工具集中添加
Task

Permission Modes

权限模式

Set
permissionMode
/
permission_mode
in options:
ModeBehaviorBest for
default
Delegates unresolved requests to
canUseTool
callback
Custom approval flows
acceptEdits
Auto-approves file edits and filesystem opsTrusted dev workflows
bypassPermissions
Runs all tools without promptsCI/CD pipelines
plan
No tool execution — planning onlyPre-review before changes
Best practice: use
acceptEdits
for interactive development; use
bypassPermissions
only in isolated, sandboxed environments. Never use
bypassPermissions
in multi-tenant or user-facing applications.
Permission mode changes mid-session are supported — start restrictive, loosen after reviewing Claude's plan:
python
q = query(prompt="Refactor auth module", options=ClaudeAgentOptions(permission_mode="plan"))
await q.set_permission_mode("acceptEdits")  # Switch after plan is approved
async for message in q:
    ...
在选项中设置
permissionMode
/
permission_mode
模式行为适用场景
default
将未解决的请求委托给
canUseTool
回调函数
自定义审批流程
acceptEdits
自动批准文件编辑和文件系统操作可信开发工作流
bypassPermissions
无需提示直接运行所有工具CI/CD流水线
plan
不执行工具——仅生成计划在变更前进行预审核
最佳实践:在交互式开发中使用
acceptEdits
;仅在隔离的沙箱环境中使用
bypassPermissions
。切勿在多租户或面向用户的应用中使用
bypassPermissions
支持在会话中途切换权限模式——初始使用严格模式,在审核Claude的计划后再放宽:
python
q = query(prompt="Refactor auth module", options=ClaudeAgentOptions(permission_mode="plan"))
await q.set_permission_mode("acceptEdits")  # 计划批准后切换
async for message in q:
    ...

Permission evaluation order

权限评估顺序

  1. Hooks — run first; can allow, deny, or pass through
  2. Permission rules — declarative allow/deny in
    settings.json
  3. Permission mode — global fallback setting
  4. canUseTool
    callback
    — runtime user approval (when mode is
    default
    )
  1. 钩子(Hooks) — 优先执行;可允许、拒绝或传递请求
  2. 权限规则 — 在
    settings.json
    中声明允许/拒绝规则
  3. 权限模式 — 全局回退设置
  4. canUseTool
    回调函数
    — 运行时用户审批(当模式为
    default
    时)

Session Management

会话管理

Capture session ID

捕获会话ID

python
session_id = None
async for message in query(prompt="Analyze auth module", options=ClaudeAgentOptions(...)):
    if hasattr(message, "subtype") and message.subtype == "init":
        session_id = message.data.get("session_id")
typescript
let sessionId: string | undefined;
for await (const message of query({ prompt: "Analyze auth module", options: { ... } })) {
  if (message.type === "system" && message.subtype === "init") {
    sessionId = message.session_id;
  }
}
python
session_id = None
async for message in query(prompt="Analyze auth module", options=ClaudeAgentOptions(...)):
    if hasattr(message, "subtype") and message.subtype == "init":
        session_id = message.data.get("session_id")
typescript
let sessionId: string | undefined;
for await (const message of query({ prompt: "Analyze auth module", options: { ... } })) {
  if (message.type === "system" && message.subtype === "init") {
    sessionId = message.session_id;
  }
}

Resume a session

恢复会话

Pass
resume
/
resume
in options to continue with full prior context:
python
async for message in query(
    prompt="Now find all callers of that function",
    options=ClaudeAgentOptions(resume=session_id),
):
    ...
在选项中传递
resume
/
resume
,即可携带完整历史上下文继续会话:
python
async for message in query(
    prompt="Now find all callers of that function",
    options=ClaudeAgentOptions(resume=session_id),
):
    ...

Fork a session

分支会话

Set
fork_session=True
/
forkSession: true
to branch without modifying the original:
python
undefined
设置
fork_session=True
/
forkSession: true
,可在不修改原始会话的情况下创建分支:
python
undefined

Explore a different approach without losing the original session

在不丢失原始会话的前提下探索不同方案

async for message in query( prompt="Redesign this as GraphQL instead", options=ClaudeAgentOptions(resume=session_id, fork_session=True), ): ...

Forking preserves the original session; both branches can be resumed independently.
async for message in query( prompt="Redesign this as GraphQL instead", options=ClaudeAgentOptions(resume=session_id, fork_session=True), ): ...

分支操作会保留原始会话;两个分支可独立恢复。

MCP Integration

MCP集成

Connect external services through the Model Context Protocol:
python
options = ClaudeAgentOptions(
    mcp_servers={
        "playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}
    }
)
MCP tool names follow the pattern
mcp__{server_name}__{tool_name}
. List them explicitly in
allowed_tools
to restrict access:
python
allowed_tools=["mcp__playwright__browser_click", "mcp__playwright__browser_screenshot"]
通过模型上下文协议(Model Context Protocol)连接外部服务:
python
options = ClaudeAgentOptions(
    mcp_servers={
        "playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}
    }
)
MCP工具名称遵循
mcp__{server_name}__{tool_name}
格式。需在
allowed_tools
中显式列出,以限制访问权限:
python
allowed_tools=["mcp__playwright__browser_click", "mcp__playwright__browser_screenshot"]

Message Handling

消息处理

Filter the stream for meaningful output. Raw messages include system init and internal state:
python
from claude_agent_sdk import AssistantMessage, ResultMessage

async for message in query(...):
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if hasattr(block, "text"):
                print(block.text)          # Claude's reasoning
            elif hasattr(block, "name"):
                print(f"Tool: {block.name}")   # Tool being called
    elif isinstance(message, ResultMessage):
        print(f"Result: {message.subtype}")   # "success" or "error"
typescript
for await (const message of query({ ... })) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if ("text" in block) console.log(block.text);
      else if ("name" in block) console.log(`Tool: ${block.name}`);
    }
  } else if (message.type === "result") {
    console.log(`Result: ${message.subtype}`);
  }
}
过滤流以获取有意义的输出。原始消息包含系统初始化和内部状态信息:
python
from claude_agent_sdk import AssistantMessage, ResultMessage

async for message in query(...):
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if hasattr(block, "text"):
                print(block.text)          # Claude的推理过程
            elif hasattr(block, "name"):
                print(f"Tool: {block.name}")   # 正在调用的工具
    elif isinstance(message, ResultMessage):
        print(f"Result: {message.subtype}")   # 结果为"success"或"error"
typescript
for await (const message of query({ ... })) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if ("text" in block) console.log(block.text);
      else if ("name" in block) console.log(`Tool: ${block.name}`);
    }
  } else if (message.type === "result") {
    console.log(`Result: ${message.subtype}`);
  }
}

System Prompts

系统提示词

Provide a
system_prompt
/
systemPrompt
to give Claude a persona or project-specific context:
python
options = ClaudeAgentOptions(
    system_prompt="You are a senior Python developer. Always follow PEP 8. Prefer explicit error handling over bare excepts.",
    allowed_tools=["Read", "Edit", "Glob"],
    permission_mode="acceptEdits",
)
Keep system prompts concise and focused on constraints the LLM doesn't already know.
通过设置
system_prompt
/
systemPrompt
为Claude赋予角色或提供项目特定上下文:
python
options = ClaudeAgentOptions(
    system_prompt="You are a senior Python developer. Always follow PEP 8. Prefer explicit error handling over bare excepts.",
    allowed_tools=["Read", "Edit", "Glob"],
    permission_mode="acceptEdits",
)
系统提示词应简洁,重点关注大语言模型未知的约束条件。

Best Practices

最佳实践

Tool selection

工具选择

  • Grant only the tools the task requires — no
    Bash
    for read-only analysis
  • Verify tool set is sufficient before launching; a missing tool causes the agent to stall
  • Include
    Task
    in the parent's
    allowed_tools
    when defining subagents
  • 仅授予任务所需的工具——只读分析场景无需
    Bash
    工具
  • 在启动前验证工具集是否足够;缺少工具会导致代理停滞
  • 定义子代理时,需在父代理的
    allowed_tools
    中包含
    Task

Prompts

提示词

  • Write prompts as specific task instructions, not open-ended descriptions
  • Name files explicitly when they are the target (
    "Review auth.py"
    vs
    "Review some code"
    )
  • Use explicit subagent invocation when precision matters:
    "Use the code-reviewer agent to..."
    )
  • 将提示词编写为具体的任务指令,而非开放式描述
  • 当文件为目标时,明确指定文件名(如“审核auth.py”而非“审核一些代码”)
  • 当需要高精度时,显式调用子代理:如“使用代码审核代理来……”

Error handling

错误处理

  • Always handle
    ResultMessage
    with
    subtype == "error"
    — never assume success
  • Catch exceptions around the
    async for
    loop, not inside it
  • Avoid bare
    except
    in hook callbacks; a swallowed exception can silently halt the agent
  • 始终处理
    subtype == "error"
    ResultMessage
    ——不要默认任务会成功
  • async for
    循环外部捕获异常,而非内部
  • 在钩子回调中避免使用裸
    except
    ;被吞掉的异常可能会导致代理静默停止

Security

安全

  • Never use
    bypassPermissions
    in production systems with user-supplied prompts
  • Use
    PreToolUse
    hooks to block access to sensitive paths (
    .env
    ,
    /etc
    , secrets)
  • Restrict subagent tools — subagents do not inherit parent permissions automatically
  • 切勿在包含用户提供提示词的生产系统中使用
    bypassPermissions
  • 使用
    PreToolUse
    钩子阻止访问敏感路径(如
    .env
    /etc
    、密钥文件)
  • 限制子代理的工具权限——子代理不会自动继承父代理的权限

Sessions

会话

  • Store session IDs persistently if the workflow spans multiple process runs
  • Fork sessions when exploring alternative approaches to avoid losing a good baseline
  • Subagent transcripts persist separately; clean up via
    cleanupPeriodDays
    setting
  • 如果工作流跨多个进程运行,需持久化存储会话ID
  • 探索替代方案时使用分支会话,避免丢失良好的基线
  • 子代理的记录会单独保存;可通过
    cleanupPeriodDays
    设置进行清理

Performance

性能

  • Prefer streaming (
    async for
    ) over collecting all messages; it shows progress and allows early exit
  • Use subagents to parallelise independent tasks (security scan + style check simultaneously)
  • Use
    plan
    mode first for expensive or irreversible operations — review before executing
  • 优先使用流式处理(
    async for
    )而非收集所有消息;流式处理可展示进度并支持提前退出
  • 使用子代理并行处理独立任务(如同时进行安全扫描和风格检查)
  • 对于昂贵或不可逆的操作,先使用
    plan
    模式——执行前先审核计划

Additional Resources

额外资源

  • references/hooks.md
    — Lifecycle hooks: blocking tools, modifying inputs, audit logging
  • references/subagents.md
    — Defining, invoking, and resuming subagents; parallelisation patterns
  • references/custom-tools.md
    — Building in-process MCP tools with
    createSdkMcpServer
  • references/hooks.md
    — 生命周期钩子:阻止工具、修改输入、审计日志
  • references/subagents.md
    — 定义、调用和恢复子代理;并行化模式
  • references/custom-tools.md
    — 使用
    createSdkMcpServer
    构建进程内MCP工具