·SDK 与工具
如何用 Claude Agent SDK 把 Claude Code 的 Agent 循环嵌入你自己的程序——安装、最小异步示例、通过 MCP 接自定义工具、用工具限制和 hooks 控制循环、并行 subagent 扇出式多 Agent 协作 + hooks 驱动的审计轨迹,外加 Agent 循环失控的六种反模式与一套评估迭代方法。
用 Claude Agent SDK 搭建自主工作流
Claude Code 是一个很棒的交互式工具,但一旦你想在真实产品里用一个 Agent——一条给失败测试分流分类的 CI 流水线、一个处理工单的客服机器人、一个读仓库并写报告的研究助手——你就需要同样的 Agent 循环以可编程方式提供。这正是 Claude Agent SDK 提供的:驱动 Claude Code 的那一套工具、Agent 循环和上下文管理,以 Python 和 TypeScript 库的形式暴露出来。本指南涵盖安装、一个最小可运行示例、如何接入自定义工具、如何控制 Agent 循环,以及在生产中经得起检验的模式。
TL;DR
- Agent SDK = Claude Code 同一套 agent 循环的可编程封装
- Python:
pip install claude-agent-sdk;TypeScript:npm install @anthropic-ai/claude-agent-sdk- 核心 API:
query()异步生成器,迭代收到的消息(助手文本 / 工具调用 / 工具结果)ClaudeAgentOptions控制运行:工具白名单、工作目录、权限模式、模型- 2026 现状:subagent + MCP server 都是 Agent SDK 的一等公民
Agent SDK 是什么
Agent SDK 以库的形式,提供 Claude Code 交互式提供的那些能力。它为你的平台绑定了一个原生的 Claude Code 二进制,所以背后跑的是同一个久经考验的 Agent 循环——而不是重新实现。这点很重要,因为你继承了工具实现(Read、Write、Bash、Grep 等)、上下文管理行为和权限模型,而不需要重建任何东西。
SDK 推荐用于 CI/CD 流水线、自定义应用和生产自动化。交互式开发和一次性任务,用 Claude Code CLI 本身更合适。把 SDK 理解成「把 Claude Code 嵌进你自己程序」的那条路。
它以两种语言提供一等支持:
- Python ——
pip install claude-agent-sdk(或uv add claude-agent-sdk) - TypeScript ——
npm install @anthropic-ai/claude-agent-sdk
对其他语言,官方文档的做法是用 -p 标志和 --output-format json 以编程方式运行 Claude Code CLI,再用你所用语言解析 JSON 流。
安装与认证
把 Python SDK 装进一个使用 Python 3.10 及以上版本的项目:
pip install claude-agent-sdk
认证沿用 Claude Code:SDK 用你的 ANTHROPIC_API_KEY 环境变量(或你已登录 Claude Code 时所用的同一套认证)。在运行程序前设好 key:
export ANTHROPIC_API_KEY="sk-ant-..."
你还需要机器上能用 Claude Code CLI,因为 SDK 在背后驱动它。在一台全新的 CI 机器上,安装 SDK 并确保 CLI 在 PATH 上就是全部准备;在已经跑 Claude Code 的开发机上,通常你什么都不缺。
一个最小的 Agent
SDK 暴露一个异步的 query 函数,把消息流式回传给你。下面是最小可用的程序——它让 Agent 列出当前目录下的文件,并允许 Bash 和 Glob 工具,这样它才能真干活:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
async for message in query(
prompt="What files are in this directory? Summarize the project structure.",
options=ClaudeAgentOptions(allowed_tools=["Bash", "Glob"]),
):
# 每条 message 是 Agent 运行里的一个事件:助手文本、工具调用、
# 工具结果,以及最终结果。.result 属性标记本次运行的最终助手消息。
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
几点值得注意:
query(...)是一个异步生成器。 你迭代它,对到来的消息做出反应。这是流式接口——你能实时看到工具调用和结果,而不只是最终答案。ClaudeAgentOptions控制本次运行。allowed_tools是最重要的旋钮:它限制 Agent 能做什么,作用和交互式 Claude Code 里的权限规则一样。从窄开始,随着你建立信任逐步放宽。- Agent 循环是隐式的。 你不需要自己写「调模型、解析工具调用、执行、回填结果」的循环——SDK 替你跑。你的代码只是对流做反应。
TypeScript 版本形态相同:对一个 query() 调用做异步迭代,选项里包含允许的工具和其他设置。
自定义工具与 MCP
真实工作流需要内置之外的工具。Agent SDK 继承了 Claude Code 的 MCP 支持,所以你可以像在 .mcp.json 里那样连任何 MCP 服务器。在 SDK 读取的配置里定义你的服务器,或通过选项传入服务器定义,Agent 就能用同样的工具使用循环调用你的自定义工具。
这就是 Agent SDK 和更广阔 MCP 生态之间的桥梁:把一个工具写成 MCP 服务器(TypeScript 用 @modelcontextprotocol/sdk,Python 用 Python MCP SDK),它就同时对交互式 Claude Code 和你写的任何 Agent SDK 程序可用。这种可移植性是把自定义能力以 MCP 服务器而非临时函数暴露的主要原因。
控制循环
自主性很强大,但在生产里你通常想要护栏。Agent SDK 提供了几种把 Agent 拴住的办法:
- 限制工具集。 单一最有效的控制。一个只能读和 grep 的 Agent,构造上就无法改变状态。只有当任务真需要时才授予写工具。
- 设定工作目录和权限模式。 像交互式 Claude Code 一样,SDK 尊重权限模式。对自动化运行,预先批准任务正好需要的工具和命令模式,这样不会有交互式提示阻塞运行。
- 给运行设上限。 给轮数或墙上时钟设上限,这样困惑的 Agent 不会无限循环。长跑的 Agent 会漂移,这是一个真实的失败模式;上限把它变成一个可重试的错误。
- 用 hooks 做策略。 SDK 在生命周期事件上支持 hooks,所以你可以确定性地阻止危险工具调用或校验输出——和交互式 Claude Code 一样的 PreToolUse/PostToolUse 模型。
- 流式并观察。 因为
query是个生成器,你可以把每次工具调用和结果实时记进审计轨迹。对任何生产 Agent,这种可观测性不是可选项——它是事后唯一能回答「Agent 做了什么?」的办法。
一个真实场景:PR 分流
为了让这具体一点,下面是一个真实工作流的形态——给失败的 CI 构建分流分类。Agent 读取失败测试输出、看相关源码、发一条总结可能原因的评论。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def triage(failing_test_log: str, repo_dir: str):
prompt = f"""
A CI build is failing. Here is the test output:
<failing_log>
{failing_test_log}
</failing_log>
Investigate the likely cause: read the failing test, read the source it
exercises, and write a 3-5 sentence summary of the probable root cause and
the file:line where the fix likely belongs. Do not modify any files.
"""
async for message in query(
prompt=prompt,
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob"],
cwd=repo_dir,
),
):
if hasattr(message, "result"):
return message.result
return ""
# 在 CI 步骤里:读日志、调 triage()、把结果作为评论发出去。
让它在生产中安全的那些决策:工具集是只读的(Read、Grep、Glob——没有 Bash、没有 Write),所以 Agent 字面上无法改变任何东西。工作目录钉死在检出的仓库上。输出是有边界的总结,不是自由代码。这就是模式:窄工具、钉死范围、结构化输出、任何真实改动都人在环里。
什么时候用 SDK、CLI、还是裸 API 调用
三个相关工具,三种不同适配:
- Claude Code CLI —— 交互式开发、终端里的一次性任务。人在驱动时最佳。
- Claude Agent SDK —— 生产自动化、自定义应用、CI/CD。你想把完整 Agent 循环(工具、上下文管理全套)嵌入自己程序时最佳。
- 裸 Claude API(
anthropicSDK) —— 你需要对消息、工具使用和模型调用本身的直接控制,且愿意自建 Agent 循环。适合不匹配 Claude Code 循环的自定义设计。
一条有用的规则:如果你的第一反应是「我希望 Claude Code 能自动做 X」,就用 Agent SDK。如果你的第一反应是「我想用这一组确切的消息和工具调模型」,就用裸 API。
生产注意事项
Agent 无人值守运行后,有几点很重要:
- 幂等性。 Agent 会被重试。确保你工具的副作用是幂等的,或者给它加守卫,这样重试不会重复应用一个改动。
- 成本监控。 每次 Agent 运行都烧 token,而 Agent 式运行比单次调用贵。给 token 用量加监控并设预算告警。失控的 Agent 也是失控的账单。
- 密钥。 当心你通过工具结果或文件读暴露给 Agent 的东西。一个有广泛读权限的 Agent 可能把密钥泄进它的输出。应用和交互式 Claude Code 里一样的 deny 规则。
- 确定性边界。 Agent 是非确定性的。把判断类活儿(分流分类、总结、探索)交给它,把确定性逻辑留在普通代码里。别让 Agent 决定要不要部署——让它为人或规则收集信息。
- 评估。 发布前,用一组固定输入跑 Agent 并抓取输出。当你改提示词、工具或模型时,重跑并对比。没有这步,Agent 质量会悄无声息地漂移。
Subagent 编排与多 Agent 协作
Agent SDK 暴露的不只是单 Agent 循环——它也让你在同一个进程里起多个并行 subagent 做扇出式研究。这是 Claude Code 交互模式下你也能用的能力,但 SDK 让你编程化编排它们:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def fan_out_research(topics: list[str]) -> list[str]:
# 每个 subagent 跑自己的 query,互相独立、上下文隔离
subagents = [
query(
prompt=f"调研 {topic} 在 2026 年的最佳实践。返回 3-5 条要点。",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "WebSearch"],
permission_mode="bypassPermissions",
),
)
for topic in topics
]
# gather 拿到所有 subagent 的完整流,再逐个迭代
streams = await asyncio.gather(*subagents, return_exceptions=True)
results = []
for stream in streams:
if isinstance(stream, Exception):
continue
async for message in stream:
if hasattr(message, "result"):
results.append(message.result)
return results
# 主线程拿到的只是 3 份浓缩报告——subagent 读的所有网页、源码
# 一丁点都不会污染主上下文
关键模式:(1) 每个 subagent 自己的 context window(默认独立,不会和主线程串);(2) permission_mode="bypassPermissions" 在 SDK 里是安全默认——因为 subagent 没有交互能力,自动化任务必须绕过提示;(3) asyncio.gather(..., return_exceptions=True) 同时拉起所有 subagent 等到全部完成,任意一个抛异常不会拖垮其他——真正的回报是 token:主线程只在最后看到 3 段总结,每个 subagent 内部的几千 token 上下文不占主线程预算。
Hooks 集成与审计轨迹
SDK 把 Claude Code 的 hooks 模型继承了下来——你可以在 PreToolUse、PostToolUse、Stop 等事件上挂脚本,用确定性逻辑给 Agent 加护栏 + 事后审计:
import json, logging
from claude_agent_sdk import query, ClaudeAgentOptions
audit = logging.getLogger("agent.audit")
async def logged_query(prompt: str):
async for message in query(
prompt=prompt,
options=ClaudeAgentOptions(
allowed_tools=["Bash", "Read", "Write"],
hooks={
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
# 阻断任何 rm -rf 调用
"command": "python3 .claude/hooks/block_rm.py",
}],
}],
},
),
):
# 流式记录每个事件——这是审计轨迹
audit.info(json.dumps({
"type": type(message).__name__,
"data": getattr(message, "data", None),
}))
if hasattr(message, "result"):
yield message.result
实战用法:(1) 确定性安全护栏——用 PreToolUse hook 阻断 rm -rf、curl | sh、敏感路径写;(2) 审计日志——把每个工具调用和结果写到结构化日志(JSON),CI 失败时直接读;(3) 质量门——PostToolUse hook 跑 ruff / tsc / 测试,发现错就把反馈回 Agent 让它自己修。模式:把"这事绝不能出错"放进 hook,把"这事需要判断"留给 Agent——两者职责分明。
常见坑与反模式:Agent 循环失控的六种写法
「生产注意事项」讲的是原则,这一节讲现场——六种反复出现的写法,共同特征是 demo 里好好的,跑久了必然出事。
坑 1:不设 max_turns。 现象:agent 在两个工具之间来回倒手(A 的输出喂 B、B 的结果又喂回 A),烧穿预算才停。原因:循环没有终止条件,模型感知不到「再来一轮」有成本。修法:max_turns 设上限、max_budget_usd 设美元兜底(各旋钮的语义见 Agent SDK 深度实战),并在每轮检查任务是否真的在推进。
坑 2:工具描述写成 API 文档。 现象:模型传错参数,或该调用时不调用。原因:工具 description 是给模型看的使用说明,不是给程序看的签名注释——模型不知道 id: string 该填什么。修法:description 写清「什么时候用、参数示例、失败时会发生什么」,再用 JSON Schema 的 enum / pattern 兜住参数形状。
坑 3:工具错误被吞进异常栈。 现象:同一个失败动作反复重试直到 max_turns。原因:工具抛异常后你只写了日志,没把错误作为 tool_result 回传——模型根本不知道上次已经失败了。修法:catch 一切异常,把结构化错误(错误码 + 建议)作为 tool_result 返回,让 agent 决定换路径还是终止。
坑 4:工具结果原样返回大文件。 现象:两三轮后上下文爆掉,成本飙升,模型开始「忘记」任务。原因:5000 行日志全文进了上下文。修法:在工具层做摘要或截断——返回前 N 行加一句「完整文件在 path」,让 agent 按需再读。
坑 5:什么都用 subagent。 现象:单步任务也被编排出三层嵌套,延迟翻倍、成本翻倍。原因:subagent 的价值是上下文隔离,不是并行装饰。修法:单个工具能完成的任务不开 subagent——编排的复杂度必须买得到东西(隔离、并行、专一上下文),编排模式见下方「Subagent 编排与多 Agent 协作」一节。
坑 6:重试没有退避与上限。 现象:上游 5xx 后 agent 硬重试,把一次故障放大成雪崩。修法:指数退避 + 次数上限 + 失败降级路径(换模型 / 跳过 / 告警人工)。
评估与迭代:怎么知道你的 agent 变好了
「生产注意事项」里评估只有一行,值得展开成一整套——agent 的回归比 prompt 的回归更隐蔽:工具改一个参数、模型升一个版本,成功率的滑坡不会报错,只会让结果悄悄变差。
金标准任务集。 攒 10-20 个端到端任务(输入 + 期望结果 + 判定规则),每次改动后全量重跑。与 prompt 评估不同,agent 的判定往往不是字符串比对——写判定脚本(结果 JSON 的字段断言、最终文件 diff、数据库状态),或用模型判卷但给显式 rubric。
三类指标分开看。 任务成功率(结果对不对)、工具效率(完成用了几次调用、有没有绕路)、单位成本(每次任务的 token 与美元)。一次改动经常是拿成功率换成本——三个数字一起看才知道是不是赚了。
trace 回放。 失败任务逐 trace 复盘:模型在哪一步走错、工具返回了什么误导信息。把每个工具调用与结果写进结构化日志(见下方 Hooks 集成),回放才有据可查。
一次只改一个变量。 与提示词迭代同一纪律:改工具就别同时改 prompt,换模型就别同时换工具集。多变量齐动,归因纯属猜谜。
回归集随故障增长。 每个线上 bad case 沉淀为新金标准任务。半年后这套任务集就是 agent 系统的资产负债表——换人维护也不会漂移。
常见问题
什么是 Claude Agent SDK,它和 Claude Code 有什么不同?
Claude Agent SDK 把驱动 Claude Code 的那套 Agent 循环、工具和上下文管理,以 Python 和 TypeScript 库的形式暴露出来。Claude Code 是你在终端运行的交互式 CLI;Agent SDK 是你嵌入自己程序用于 CI/CD、自定义应用和生产自动化的东西。背后 SDK 驱动的是一个内置的 Claude Code 二进制,所以你继承的是同一套久经考验的行为。
怎么安装 Claude Agent SDK?
用 pip install claude-agent-sdk(Python 3.10 及以上)或 uv add claude-agent-sdk 装 Python SDK,用 npm install @anthropic-ai/claude-agent-sdk 装 TypeScript SDK。你还需要机器上能用 Claude Code CLI,并设好 ANTHROPIC_API_KEY 环境变量。其他语言请用 -p 标志加 --output-format json 以编程方式运行 Claude Code CLI。
怎么控制 Agent 能用哪些工具?
通过 ClaudeAgentOptions(或其 TypeScript 等价物)传一个 allowed_tools 列表。限制工具集是让 Agent 安全最有效的单一手段——一个只能 Read 和 Grep 的 Agent 构造上就无法改变状态。只有当任务真需要时才授予写工具或 shell 工具,并配合权限模式和 hooks 一起做策略。
我该用 Agent SDK,还是直接调 Claude API?
想把你程序里整套 Claude Code Agent 循环(工具、上下文管理全套)嵌入而不重建时,用 Agent SDK。想直接控制消息和工具使用、且愿意自建 Agent 循环时,用裸 Claude API(anthropic SDK)。经验法则:如果你希望 Claude Code 能自动做某事,就用 Agent SDK;如果你想用确切的一组消息调模型,就用裸 API。
Agent SDK 能并行跑多个 subagent 吗?
能。SDK 让你在同一个进程里用 asyncio.gather(*queries, return_exceptions=True) 起多个 query() 调用,每个跑自己的 subagent,互相上下文隔离。典型模式是扇出式研究:3 个 subagent 同时调研不同方向,主线程只在最后拿回 3 段浓缩报告——中间所有上下文不占主线程预算。配合:permission_mode="bypassPermissions" 在 SDK 里是安全默认(subagent 没有交互能力),用 allowed_tools 给每个 subagent 限制到最小够用集合。
怎么给 Agent SDK 加审计日志和确定性护栏?
用 ClaudeAgentOptions.hooks 接 Claude Code 的 hooks 系统——PreToolUse 阻断危险工具调用(rm -rf、敏感路径写)、PostToolUse 跑 linter 把错误反馈回 Agent、Stop 触发通知。审计:async for message in query(...) 让你拿到每个事件(助手文本、工具调用、工具结果),写到结构化日志(JSON)。生产模式:「绝不能错」放 hook(确定性逻辑),「需要判断」放 Agent(概率性逻辑)——两者职责分明、互不干扰。
官方参考资料
- Claude Agent SDK 概览
- Claude Agent SDK — Python(anthropics/claude-agent-sdk-python)
- Claude Code 文档
- Model Context Protocol
- Anthropic 工程博客
本文基于截至 2026 年 7 月的公开信息,相关 API 可能演进。