Agent SDK
用 @anthropic-ai/claude-agent-sdk 在自己代码里跑 Claude Code 同款循环。
Claude Agent SDK 是 Anthropic 官方发布的包,作用可以一句话说清:把 Claude Code 那套 agent loop 内核抽出来,让你的程序也能调用。终端里 claude 命令背后跑的工具循环、上下文压缩、subagent 调度、MCP 连接、权限决策,SDK 里全都有,只是把用户界面换成了函数调用。
如果你之前接触过 OpenAI 的 Assistants API 或者 LangChain 那种 agent 框架,Agent SDK 大致上占同一个生态位——都是把"让 LLM 自主用工具解决问题"这套循环封装好交给你。区别是 Agent SDK 深度绑定 Claude Code 生态,你在 CLI 里辛苦攒下的 skills、commands、agents、hooks 配置一行代码不改就能被 SDK 复用,这是它相比通用框架最实在的好处。
SDK 和 CLI 是什么关系
一个直接的比喻:CLI 是给人敲键盘用的前台,SDK 是给程序调用的后台。两者共享同一个 agent 引擎,所以你在 CLI 里配的 CLAUDE.md、.claude/skills/、.claude/commands/、.claude/agents/ 这些约定,SDK 都能读,跑起来行为是一致的。
区别在于 SDK 拿到的是一个结构化的消息流,而不是终端里那种边打字边渲染的界面。你调用 query(...),SDK 返回一个异步迭代器,一条一条把 Claude 生成的消息(文本、tool_use、tool_result、system 事件、最终 result)推给你,你自己决定怎么处理。
这套结构化流是 SDK 相比直接调 API 最大的优势。你不用自己维护 tool 循环、不用自己写权限判定、也不用自己拼上下文,只关心"用户想要什么"和"结果怎么用",中间那一堆脏活 SDK 全接了。
安装
TypeScript 用 npm:
npm install @anthropic-ai/claude-agent-sdkPython 有两种主流方式,推荐用 uv:
uv init
uv add claude-agent-sdk或者传统 venv:
python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdkWindows PowerShell 里激活虚拟环境是 .venv\Scripts\Activate.ps1,遇到执行策略拒绝时先 Set-ExecutionPolicy -Scope Process RemoteSigned。
装完之后设置 API key:
export ANTHROPIC_API_KEY=sk-ant-xxxxx除了直连 Anthropic,SDK 也支持云厂商托管:Amazon Bedrock 走 CLAUDE_CODE_USE_BEDROCK=1,Google Vertex 走 CLAUDE_CODE_USE_VERTEX=1,Azure Foundry 走 CLAUDE_CODE_USE_FOUNDRY=1,各自再配好厂商凭证即可。
最小示例
Python 版本,一段 8 行的代码就能跑起来:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
async for message in query(
prompt="列一下当前目录有哪些文件",
options=ClaudeAgentOptions(allowed_tools=["Bash", "Glob"]),
):
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: "列一下当前目录有哪些文件",
options: { allowedTools: ["Bash", "Glob"] },
})) {
if ("result" in message) console.log(message.result);
}这两段代码等价于你在终端里打开 claude 然后输入那句提问,只不过输出被你程序捕获而不是渲染在屏幕上。SDK 会自动加载当前目录的 CLAUDE.md、.claude/settings.json,处理工具调用循环,最后把结果推给 async for 循环。
消息类型
query() 迭代出来的 message 有多种类型:SystemMessage(会话开始、上下文压缩等系统事件)、AssistantMessage(模型生成的一轮回复,可能包含文本块或 tool_use 块)、UserMessage(工具返回的 tool_result)、ResultMessage(这次任务的最终结果)。写业务代码时最常用的是过滤 ResultMessage 拿最终答案,或者对 AssistantMessage 里的 text 做流式渲染。
Node 和 Python 该选哪个
两个语言版本的能力完全对齐,选哪个纯看你的技术栈。Node 版本的优势在于跟前端工具链、Serverless 部署(Vercel、Cloudflare Workers)粘合更自然,异步语法更贴近 API 特性。Python 版本的优势在于数据处理生态(pandas、numpy)和 AI 领域大量现成的工具库能直接引用。写脚本、和其他 LLM 框架混用,Python 更顺手;做 SaaS 后端、加进现有 Web 服务,Node 更省事。
常用配置项
ClaudeAgentOptions(或 TS 里的 options 对象)是控制这次 agent 行为的核心开关,几个最常用的字段:
allowed_tools/allowedTools:允许 Claude 调用的内置工具白名单,比如Read、Write、Edit、Bash、Glob、Grep、Agent。不写就是允许全部内置工具。system_prompt/systemPrompt:覆盖或追加系统提示词,往里塞项目背景、身份约束、输出格式。model:指定模型,比如claude-opus-4-7、claude-sonnet-5、claude-haiku-4-5-20251001。省略走默认。max_turns/maxTurns:agent loop 最多跑几轮,超了就停。防止死循环烧钱的兜底。permission_mode/permissionMode:权限模式,比如acceptEdits表示自动接受文件修改,适合无人值守。hooks:在PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、UserPromptSubmit这些时机插自定义回调。agents:注册 subagent 类型,供主 loop 通过Agent工具派发独立任务。mcp_servers/mcpServers:连接外部 MCP server,比如给它接一个 playwright 或者你自研的内部工具网关。resume:传上一次会话的session_id,接着上次的上下文继续跑。
中等复杂例子:日志分析定时脚本
假设你想每天早上自动分析昨天的 nginx 错误日志,把 500 错误的模式总结成 markdown 存到 reports/ 目录。用 SDK 加 cron(或 Windows 计划任务)就够了。
import asyncio
from datetime import date, timedelta
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher
async def audit_hook(input_data, tool_use_id, context):
# 每次工具调用记录一行审计,方便后期排查
tool = input_data.get("tool_name", "?")
print(f"[audit] {tool} at {tool_use_id}")
return {}
async def main():
yesterday = (date.today() - timedelta(days=1)).isoformat()
prompt = f"""
读取 /var/log/nginx/error.log,筛选日期为 {yesterday} 的 500 错误。
按 URL 模式分组,统计出现次数最多的前 5 类。
将结果写入 reports/{yesterday}.md,格式为 markdown 表格。
"""
async for message in query(
prompt=prompt,
options=ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash", "Grep"],
model="claude-sonnet-5",
permission_mode="acceptEdits",
max_turns=20,
hooks={
"PreToolUse": [HookMatcher(matcher="*", hooks=[audit_hook])],
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())这段脚本的几个要点:permission_mode="acceptEdits" 让它无人值守;max_turns=20 防止陷入无限循环;PreToolUse hook 把每次工具调用打印出来,事后能查是谁干的。丢进 cron 每天 06:00 跑一遍,报告就自动出来了。
生产落地注意
无人值守跑 Claude Code 有几条硬红线要守住:一是权限最小化,allowed_tools 里只放这次任务真正需要的工具,不要一股脑给全部;二是把结果落盘到你能审计的位置,别让它随便写系统关键路径;三是加上超时和 max_turns,防止一次意外的 prompt 让它跑到明天;四是订阅告警,一旦脚本失败你要能第一时间知道。
Hook 的常见用法
上面例子里用到的 hook 机制不只是打日志。几个常见的落地场景值得单独说:
- PreToolUse:在工具真正执行前拦截。可以做参数校验(不许 Bash 删
/)、可以做二次确认、可以直接返回一个deny阻止执行。这是把安全规则从 CLAUDE.md 提示词层面下沉到代码层面的关键机制。 - PostToolUse:工具跑完记录审计日志、上报指标、触发下游 webhook。上文的 audit_hook 就是这一类。
- SessionStart / SessionEnd:会话级别的生命周期钩子,可以在开始时预热缓存、结束时刷新指标或者关闭连接池。
- UserPromptSubmit:用户输入进来之前拦一道,用来做敏感词检查、把简写扩展成完整问题、或者根据当前项目动态注入上下文。
- Stop:模型主动结束一次回合时触发,适合把中间产物落盘。
Subagent 和 MCP 也能在 SDK 里注册
Agent SDK 完整继承了 Claude Code 的 subagent 和 MCP 机制,写法上一目了然。注册一个代码评审 subagent:
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
options = ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="专业代码评审员,看质量和安全",
prompt="分析代码质量,指出可读性、正确性、安全问题",
tools=["Read", "Glob", "Grep"],
)
},
)主 loop 只要在提示词里说"用 code-reviewer 评审这份代码",SDK 就会自动派出子 agent 独立跑一轮。这一套跟你在 .claude/agents/ 里定义子 agent 的效果一致,区别只是入口一个是文件一个是代码。
MCP 也一样,mcp_servers 字段直接传一个 dict:
options = ClaudeAgentOptions(
mcp_servers={
"playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}
}
)Claude 就能通过 mcp__playwright__* 系列工具去驱动浏览器。
Session 恢复
SDK 支持会话恢复,用于连续的多次对话。第一次调用时捕获 session_id,下一次把它塞进 resume:
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage
session_id = None
async for message in query(
prompt="先读一下认证模块",
options=ClaudeAgentOptions(allowed_tools=["Read", "Glob"]),
):
if isinstance(message, SystemMessage) and message.subtype == "init":
session_id = message.data["session_id"]
async for message in query(
prompt="现在找出所有调用它的地方",
options=ClaudeAgentOptions(resume=session_id),
):
if isinstance(message, ResultMessage):
print(message.result)第二次调用不用重新解释"它"是谁,因为整个上下文还在。这个能力对于做交互式 agent 服务、或者让脚本分阶段推进任务都很关键。
什么时候选 Agent SDK
选 SDK 而不是自己撸 Messages API 的 tool 循环,标准很简单:你要让 Claude 自主用工具解决多步问题。SDK 已经把工具循环、错误重试、上下文压缩、subagent 调度、MCP 集成、hook 机制全都封装好了,你只管写业务逻辑。
反过来如果你只是想调一次模型拿一段文本回来(翻译、摘要、分类),不涉及工具,那用底层的 Messages API 更轻。下一节讲 Messages API 时会给出这两种选择的对照。