Claude Agent SDK 实战:把 Claude Code 同款运行时装进你的应用(hooks + 进程内 MCP + 权限)
你可能用过 Claude Code 写代码,但有没有想过:把驱动它的那套「生产级 Agent 循环」直接装进你自己的后端服务?Claude Agent SDK 干的就是这事——它把 Claude Code 的运行时封装成库,带来 file 访问、shell 工具、子 Agent、以及已经 hardened 过的权限系统。本教程教你用 hooks 拦截 Agent 循环关键点、用 in-process MCP 免子进程注册自定义工具、用权限 allowlist 收紧边界。
先搞懂:Agent SDK 和 Claude Code 的关系
用一句话理解:Claude Code 是装好壳的产品,Claude Agent SDK 是它拆出来的引擎。你不用自己写 Agent loop,直接用 Anthropic 在生产环境打磨过的那一套。
| 能力 | SDK 给你什么 |
|---|---|
| Agent 循环 | 现成的生产级 runtime,含文件/shell/子 Agent |
| Hooks | 在循环特定点拦截(前/后置处理、审批) |
| In-process MCP | 同进程定义工具,无需起子进程 |
| 权限 allowlist | 细粒度工具/命令白名单 |
它不是「又一个聊天封装」。最大价值是权限与可靠性——这些在 Claude Code 里被真实攻击面打磨过。自己从零写一套等量级的安全 Agent 循环,成本极高。
Step 1:安装并初始化
Python 与 TypeScript 都支持,这里以 Python 为例:
pip install claude-agent-sdk
# 设置 API Key(Anthropic 控制台获取)
export ANTHROPIC_API_KEY=sk-ant-xxxxxxxx
# 最简启动:跑一句话任务
from claude_agent_sdk import ClaudeAgent
agent = ClaudeAgent()
result = agent.run("列出当前目录下的 .py 文件并说明各自作用")
Step 2:用 in-process MCP 注册自定义工具
传统 MCP 要起一个独立进程;in-process MCP 让你在同一进程里直接定义工具,启动更快、调试更方便:
from claude_agent_sdk import ClaudeAgent, tool
@tool("query_db", "按 SQL 查询内部数据库")
def query_db(sql: str) -> str:
# 你的真实查询逻辑
return db.execute(sql)
agent = ClaudeAgent(tools=[query_db])
# Agent 现在能直接调用 query_db,无需额外进程
工具即能力,也是风险面。凡是注册的工具,Agent 都可能调用。敏感操作(删库、发邮件)务必配合 Step 4 的权限 allowlist 和 hooks 审批。
Step 3:用 Hooks 在循环关键点拦截
Hooks 能在 Agent 循环的特定点触发你的函数,比如每次调用工具前先记录或拦截:
from claude_agent_sdk import ClaudeAgent, hook
@hook("PreToolUse")
def guard(tool_name, input):
if tool_name == "Bash" and "rm -rf" in input.get("command", ""):
return {"decision": "block", "reason": "禁止危险删除命令"}
return {"decision": "allow"}
agent = ClaudeAgent(hooks=[guard])
Step 4:用权限 allowlist 收紧边界
默认权限可能过宽。生产环境用 allowlist 白名单化:
agent = ClaudeAgent(
permission_allowlist={
"Bash": ["ls *", "cat *", "python *"], # 只允许这几类
"Read": ["src/**", "docs/**"], # 只能读这些目录
"Write": ["tmp/**"], # 只能写临时区
}
)
最小权限原则。宁可多配几次,也别一开始就放开 `Bash: *`。Agent 出事,十有八九是权限给太宽。
Step 5:把 Agent 嵌进后端服务
from fastapi import FastAPI
from claude_agent_sdk import ClaudeAgent
app = FastAPI()
agent = ClaudeAgent(hooks=[guard], permission_allowlist=ALLOW)
@app.post("/agent")
async def run(req: dict):
result = agent.run(req["prompt"])
return {"output": result.text}
Step 6:用子 Agent 拆分复杂任务
复杂任务让主 Agent 派发子 Agent,各自独立上下文,互不污染:
result = agent.run(
"重构 src/ 下所有模块,先让子 Agent 逐个分析依赖,再汇总改",
subagents=["analyzer", "refactor"],
)
Step 7:上线前的 checklist
1. 权限 allowlist 已白名单化(无 Bash: *)
2. 危险工具(删/发/付)已用 hooks 拦截或要求人审批
3. 所有工具调用有审计日志(PostToolUse 记一笔)
4. 子 Agent 上下文隔离,不共享敏感状态
5. API Key 走环境变量,不进代码仓库
常见问题速查
| 你遇到的现象 | 大概率原因 & 解决 |
|---|---|
| 工具没被调用 | @tool 的 description 太模糊,或没传进 tools=[] |
| 命令被莫名拦截 | allowlist 没覆盖该模式,或 hooks 返回了 block |
| 子 Agent 不返回 | 子 Agent 权限比主 Agent 更窄,放宽对应 allow |
| 想接非 Claude 模型 | SDK 绑定 Anthropic 运行时,换模型需用 OpenAI Agents SDK |