claude-agent-sdk
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClaude Agent SDK
Claude Agent SDK
Provides patterns and best practices for building production AI agents using the Claude Agent SDK (Python: , TypeScript: ).
claude-agent-sdk@anthropic-ai/claude-agent-sdk为使用Claude Agent SDK(Python版:,TypeScript版:)构建生产级AI Agent提供模式与最佳实践。
claude-agent-sdk@anthropic-ai/claude-agent-sdkInstallation
安装
bash
undefinedbash
undefinedTypeScript
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-keyThird-party providers are also supported: set , , or alongside the respective cloud credentials.
CLAUDE_CODE_USE_BEDROCK=1CLAUDE_CODE_USE_VERTEX=1CLAUDE_CODE_USE_FOUNDRY=1pip install claude-agent-sdk
在运行任何代理前设置API密钥:
```bash
export ANTHROPIC_API_KEY=your-api-key同时支持第三方提供商:设置、或,并配置对应云服务的凭证。
CLAUDE_CODE_USE_BEDROCK=1CLAUDE_CODE_USE_VERTEX=1CLAUDE_CODE_USE_FOUNDRY=1Core Pattern: The query()
Function
query()核心模式:query()
函数
query()Every agent is built around , which returns an async iterator of streamed messages:
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);
}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:
| Tool | Purpose |
|---|---|
| Read any file in the working directory |
| Create new files |
| Make precise edits to existing files |
| Run terminal commands, scripts, git operations |
| Find files by pattern ( |
| Search file contents with regex |
| Search the web for current information |
| Fetch and parse web page content |
| Ask the user clarifying questions |
| Spawn subagents (required when using subagents) |
仅授予代理实际需要的工具——遵循最小权限原则:
| 工具 | 用途 |
|---|---|
| 读取工作目录中的任意文件 |
| 创建新文件 |
| 对现有文件进行精准编辑 |
| 运行终端命令、脚本、Git操作 |
| 按模式查找文件(如 |
| 使用正则表达式搜索文件内容 |
| 联网搜索最新信息 |
| 获取并解析网页内容 |
| 向用户询问澄清性问题 |
| 生成子代理(使用子代理时必须配置) |
Recommended tool sets by use case
按场景推荐工具组合
| Use case | Tools |
|---|---|
| Read-only analysis | |
| Code modification | |
| Full automation | |
| Web-augmented | Add |
| Subagent orchestration | Add |
| 使用场景 | 工具 |
|---|---|
| 只读分析 | |
| 代码修改 | |
| 全自动化 | |
| 联网增强 | 在任意组合中添加 |
| 子代理编排 | 在父代理的工具集中添加 |
Permission Modes
权限模式
Set / in options:
permissionModepermission_mode| Mode | Behavior | Best for |
|---|---|---|
| Delegates unresolved requests to | Custom approval flows |
| Auto-approves file edits and filesystem ops | Trusted dev workflows |
| Runs all tools without prompts | CI/CD pipelines |
| No tool execution — planning only | Pre-review before changes |
Best practice: use for interactive development; use only in isolated, sandboxed environments. Never use in multi-tenant or user-facing applications.
acceptEditsbypassPermissionsbypassPermissionsPermission 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:
...在选项中设置 / :
permissionModepermission_mode| 模式 | 行为 | 适用场景 |
|---|---|---|
| 将未解决的请求委托给 | 自定义审批流程 |
| 自动批准文件编辑和文件系统操作 | 可信开发工作流 |
| 无需提示直接运行所有工具 | CI/CD流水线 |
| 不执行工具——仅生成计划 | 在变更前进行预审核 |
最佳实践:在交互式开发中使用;仅在隔离的沙箱环境中使用。切勿在多租户或面向用户的应用中使用。
acceptEditsbypassPermissionsbypassPermissions支持在会话中途切换权限模式——初始使用严格模式,在审核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
权限评估顺序
- Hooks — run first; can allow, deny, or pass through
- Permission rules — declarative allow/deny in
settings.json - Permission mode — global fallback setting
- callback — runtime user approval (when mode is
canUseTool)default
- 钩子(Hooks) — 优先执行;可允许、拒绝或传递请求
- 权限规则 — 在中声明允许/拒绝规则
settings.json - 权限模式 — 全局回退设置
- 回调函数 — 运行时用户审批(当模式为
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 / in options to continue with full prior context:
resumeresumepython
async for message in query(
prompt="Now find all callers of that function",
options=ClaudeAgentOptions(resume=session_id),
):
...在选项中传递 / ,即可携带完整历史上下文继续会话:
resumeresumepython
async for message in query(
prompt="Now find all callers of that function",
options=ClaudeAgentOptions(resume=session_id),
):
...Fork a session
分支会话
Set / to branch without modifying the original:
fork_session=TrueforkSession: truepython
undefined设置 / ,可在不修改原始会话的情况下创建分支:
fork_session=TrueforkSession: truepython
undefinedExplore 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 . List them explicitly in to restrict access:
mcp__{server_name}__{tool_name}allowed_toolspython
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_toolspython
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 / to give Claude a persona or project-specific context:
system_promptsystemPromptpython
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.
通过设置 / 为Claude赋予角色或提供项目特定上下文:
system_promptsystemPromptpython
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 for read-only analysis
Bash - Verify tool set is sufficient before launching; a missing tool causes the agent to stall
- Include in the parent's
Taskwhen defining subagentsallowed_tools
- 仅授予任务所需的工具——只读分析场景无需工具
Bash - 在启动前验证工具集是否足够;缺少工具会导致代理停滞
- 定义子代理时,需在父代理的中包含
allowed_toolsTask
Prompts
提示词
- Write prompts as specific task instructions, not open-ended descriptions
- Name files explicitly when they are the target (vs
"Review auth.py")"Review some code" - Use explicit subagent invocation when precision matters: )
"Use the code-reviewer agent to..."
- 将提示词编写为具体的任务指令,而非开放式描述
- 当文件为目标时,明确指定文件名(如“审核auth.py”而非“审核一些代码”)
- 当需要高精度时,显式调用子代理:如“使用代码审核代理来……”
Error handling
错误处理
- Always handle with
ResultMessage— never assume successsubtype == "error" - Catch exceptions around the loop, not inside it
async for - Avoid bare in hook callbacks; a swallowed exception can silently halt the agent
except
- 始终处理的
subtype == "error"——不要默认任务会成功ResultMessage - 在循环外部捕获异常,而非内部
async for - 在钩子回调中避免使用裸;被吞掉的异常可能会导致代理静默停止
except
Security
安全
- Never use in production systems with user-supplied prompts
bypassPermissions - Use hooks to block access to sensitive paths (
PreToolUse,.env, secrets)/etc - 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 setting
cleanupPeriodDays
- 如果工作流跨多个进程运行,需持久化存储会话ID
- 探索替代方案时使用分支会话,避免丢失良好的基线
- 子代理的记录会单独保存;可通过设置进行清理
cleanupPeriodDays
Performance
性能
- Prefer streaming () over collecting all messages; it shows progress and allows early exit
async for - Use subagents to parallelise independent tasks (security scan + style check simultaneously)
- Use mode first for expensive or irreversible operations — review before executing
plan
- 优先使用流式处理()而非收集所有消息;流式处理可展示进度并支持提前退出
async for - 使用子代理并行处理独立任务(如同时进行安全扫描和风格检查)
- 对于昂贵或不可逆的操作,先使用模式——执行前先审核计划
plan
Additional Resources
额外资源
- — Lifecycle hooks: blocking tools, modifying inputs, audit logging
references/hooks.md - — Defining, invoking, and resuming subagents; parallelisation patterns
references/subagents.md - — Building in-process MCP tools with
references/custom-tools.mdcreateSdkMcpServer
- — 生命周期钩子:阻止工具、修改输入、审计日志
references/hooks.md - — 定义、调用和恢复子代理;并行化模式
references/subagents.md - — 使用
references/custom-tools.md构建进程内MCP工具createSdkMcpServer