Claude Agent SDK 深度解析:给 Agent 一台电脑,再给它一个可验证的循环
Claude Agent SDK 深度解析:给 Agent 一台电脑,再给它一个可验证的循环
大多数 Agent 框架在教模型"调用工具",这个 SDK 的思路是先给它一台电脑。
Anthropic 在 2025 年 9 月 29 日发了一篇官方博客《Building agents with the Claude Agent SDK》,核心信息一句话:Claude Code SDK 正式改名为 Claude Agent SDK。
改名不是营销动作,而是一次"承认现实":Claude Code 本来是为 Anthropic 内部开发者提效做的编码工具,结果他们自己开始拿它做深度研究、视频生成、笔记整理——官方原话说它"已经开始驱动我们几乎所有主要的 Agent 循环"。既然底层这套 harness 能跑的不只是编码任务,名字就不该再限制它。
这篇把博客里的设计原则、最佳实践,以及 Python SDK 的实际用法串起来讲清楚。
本文提纲
- 为什么改名:harness 比应用更重要
- 核心设计原则:给 Agent 一台电脑
- Agent loop:收集上下文 → 采取行动 → 验证工作
- 收集上下文:四件武器与它们的取舍
- 采取行动:工具、脚本、代码生成与 MCP
- 验证工作:规则、视觉反馈与 LLM as judge
- 测试与改进:四个诊断问题
- 落到代码:Python SDK 上手
- 选型与注意事项
为什么改名:harness 比应用更重要
博客里给的解释很直接:Claude Code 的设计前提是Claude 需要程序员日常用的那些工具——在代码库里找到合适的文件、读写编辑、跑 lint、执行、调试,然后迭代到成功。
关键发现是:一旦有了这些工具,它就不只能写代码。 给它跑 bash、编辑文件、创建文件、搜索文件的能力之后,它可以读 CSV、搜网页、做可视化、解读指标——也就是说,"会写代码 + 有一台电脑"本身就构成了通用 Agent 的底座。
所以改名反映的是分层:Claude Code 是应用,Claude Agent SDK 是驱动它的那套 harness。官方把它总结成一句设计原则——给你的 Agent 一台电脑,让它像人一样工作。
他们列出的典型场景也印证了这一点:
- 金融 Agent:理解持仓与目标,接外部 API、存数据、写代码做计算;
- 个人助理 Agent:订行程、管日历、约会议、写简报,跨应用跟踪上下文;
- 客服 Agent:处理高歧义请求,查用户数据、连外部 API、回消息、该升级给人时升级;
- 深度研究 Agent:在大规模文档里搜索、跨文件交叉验证、产出详细报告。
Agent loop:收集上下文 → 采取行动 → 验证工作
这是全文最有价值的一个框架。官方观察到 Claude Code 内部反复出现同一个反馈循环:
gather context → take action → verify work → repeat
他们把这三段拆成了"该给 Agent 配什么能力"的清单,并且全程用一个邮件 Agent 举例(比如让它读历史邮件、起草回复)。这个框架的好处是:当你发现 Agent 不好用时,可以按阶段定位缺什么——是它拿不到信息(gather),还是没有合适的手段(act),还是无从判断自己做得好不好(verify)。
收集上下文:四件武器与它们的取舍
一、Agentic search 与文件系统
官方有个挺妙的说法:文件系统代表"可以被拉进模型上下文的信息",而 Agent 的文件夹和文件结构,本身就是一种上下文工程。
具体怎么工作?当 Claude 遇到大文件(日志、用户上传的文件),它会用 grep、tail 这类 bash 脚本自己决定怎么把内容装进上下文,而不是无脑全读。所以对邮件 Agent,把历史邮件放进一个 Conversations 文件夹,就等于给了它一个可检索的语料库。
二、Semantic search(语义检索)
官方的态度很值得注意,几乎是罕见的"劝你别急着上向量":语义检索通常更快,但更不准确、更难维护、更不透明——它要切块、embedding、按向量检索概念。
结论是:先从 agentic search 开始,只有当你确实需要更快的结果或更大的召回变化时,再加语义检索。
三、Subagents(子 Agent)
SDK 默认支持子 Agent,官方给了两个理由,都说到点子上:
- 并行化:同时开多个子 Agent 处理不同任务;
- 上下文管理:子 Agent 使用独立的上下文窗口,只把相关信息回传给编排者,而不是把整个上下文倒回去。
第二个理由才是关键:它天生适合"要翻大量信息、但其中绝大多数没用"的任务。 邮件 Agent 可以派出多个搜索子 Agent 并行查不同关键词,每个只返回相关片段,而不是整封邮件线程。
四、Compaction(压缩)
长任务必然撞上上下文上限。SDK 的 compact 功能会在接近上限时自动摘要前面的消息,它构建在 Claude Code 的 /compact 命令之上。这不是可选项——Agent 跑得越久,上下文维护越关键。
采取行动:工具、脚本、代码生成与 MCP
工具:设计成"主要动作"
官方提醒了一句容易被忽略的话:工具在上下文窗口里非常显眼,是 Claude 决定如何完成任务时首先考虑的动作。 所以你要有意识地设计工具,最大化上下文效率。
原则是:工具应该是你希望 Agent 采取的主要动作。 对邮件 Agent 来说,就是 fetchInbox、searchEmails 这类最高频的动作。工具设计的具体方法论,官方指向另一篇博客《Writing effective tools for agents》——那是配套阅读。
Bash 与脚本:通用兜底
Bash 是"用电脑干活"的通用工具。博客举的例子很实用:用户的重要信息可能在附件里,Claude 可以写代码把 PDF 下载下来、转成文本、再在里面搜索——一条临时拼出来的链路,不需要事先准备工具。
代码生成:被低估的行动方式
这一段我觉得是全文最值得抄进自己系统设计的部分:
代码是精确的、可组合的、可无限复用的,因此是需要可靠执行复杂操作的 Agent 的理想输出。
官方的例子:Claude.ai 的文件创建功能完全依赖代码生成——Claude 写 Python 脚本来生成 Excel、PowerPoint、Word 文档,从而保证格式一致和复杂功能。放在邮件 Agent 上,就是"让用户能对收件邮件设定规则",而这需要写代码在事件上运行。
一个值得自问的问题:我的任务里,哪些部分表达成代码会更可靠? 很多时候这个问题的答案会打开新的能力。
MCP:标准化的外部集成
MCP(Model Context Protocol)提供标准化的外部服务集成,自动处理认证和 API 调用,所以接 Slack、GitHub、Google Drive、Asana 都不需要自己写集成、不用管 OAuth。邮件 Agent 因此可以直接调 search_slack_messages 或 get_asana_tasks。生态越大,你越能"专注于 Agent 行为本身"。
验证工作:规则、视觉反馈与 LLM as judge
官方对这一段的价值判断很明确:能检查并改进自己输出的 Agent,本质上更可靠——它们在错误累积之前抓住错误,跑偏时自我纠正,并在迭代中变好。
关键是给 Claude 具体的评估方式。三种:
一、定义规则(最好的反馈)
最好的反馈形式,是为输出定义清晰的规则,然后说明哪条规则没过、为什么。
代码 lint 是规则反馈的绝佳例子,而且反馈越深入越好:官方特别指出,生成 TypeScript 再 lint,通常比生成纯 JavaScript 更好,因为它给你多出好几层反馈。
落到邮件场景:检查收件人地址是否合法(不合法就报 error)、用户是否曾给这个人发过邮件(符合就报 warning)。
二、视觉反馈
做视觉类任务(UI 生成、测试)时,把截图或渲染结果喂回模型很有效。比如发送 HTML 格式邮件时,截图后让模型自己核对四个维度:
- 布局:元素位置对不对、间距合不合适;
- 样式:颜色、字体、格式是否符合预期;
- 内容层级:信息顺序和强调是否正确;
- 响应式:看起来有没有挤坏(不过单张截图的视口信息有限)。
配一个 Playwright 之类的 MCP server,就能把这个视觉反馈循环自动化:截图、多视口、甚至测试交互元素。
三、LLM as judge
用另一个模型按模糊规则给输出打分。官方对它的评价很坦率:方法不够稳健,延迟代价还很大,但如果你就是愿意为一点提升付出代价,它有用。邮件 Agent 的用法是:派一个子 Agent 专门评审草稿的语气,看是否贴合用户过往的沟通风格。
三种方式其实构成一个可靠性梯度:规则 > 视觉 > 判官,越靠前越确定、越便宜。
测试与改进:四个诊断问题
跑了几轮 agent loop 之后,官方建议认真看输出——尤其是失败的案例,然后"设身处地"问一句:它有没有拿到干这件事该有的工具?
他们给了四个诊断问题,每一个都指向一类不同的修法:
| 症状 | 可能的根因与修法 |
|---|---|
| Agent 误解任务 | 可能缺关键信息——能不能改搜索 API 的结构,让它更容易找到该知道的东西 |
| Agent 反复失败 | 能不能在工具调用里加一条正式规则,用来识别并修复这个失败 |
| Agent 修不好自己的错 | 能不能给它更有用或更有创意的工具,换一条路解决问题 |
| Agent 性能随功能增加而波动 | 基于真实用户用法建一个有代表性的测试集,做程序化评估(eval) |
最后一条尤其重要:没有 eval 集,你只能靠手感判断"这次改动是不是让 Agent 变笨了"。
落到代码:Python SDK 上手
博客讲了"为什么"和"怎么想",具体怎么用要回到 SDK。Python 包名是 claude-agent-sdk:
pip install claude-agent-sdk
一个细节挺贴心:Claude Code CLI 会随包自动捆绑,不需要单独安装;想用系统安装或指定版本,可以在选项里给 cli_path。前置要求是 Python 3.10+。
单次查询:query()
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
async def main():
options = ClaudeAgentOptions(
system_prompt="You are a helpful assistant",
max_turns=1,
)
async for message in query(prompt="Tell me a joke", options=options):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
anyio.run(main)
query() 返回一个 AsyncIterator,消息类型分 AssistantMessage / UserMessage / SystemMessage / ResultMessage,内容块分 TextBlock / ToolUseBlock / ToolResultBlock。
权限:先搞清楚 allowed_tools 的语义
这是最容易搞错的一点,README 专门强调了:allowed_tools 是"自动批准清单",不是"可用工具白名单"。 列进去的工具会被自动批准,没列进去的会落到 permission_mode 和 can_use_tool decision;它不会把工具从 Claude 的工具集里移除。要禁用某个工具,得用 disallowed_tools。
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"], # 这些自动批准
permission_mode="acceptEdits", # 自动接受文件编辑
cwd="/path/to/project",
)
需要更细的控制时,用权限回调——它拿到工具名、输入和上下文,返回 PermissionResultAllow 或 PermissionResultDeny,还能改写输入:
async def my_permission_callback(tool_name, input_data, context):
if tool_name in ["Read", "Glob", "Grep"]:
return PermissionResultAllow()
if tool_name in ["Write", "Edit", "MultiEdit"]:
file_path = input_data.get("file_path", "")
if file_path.startswith("/etc/") or file_path.startswith("/usr/"):
return PermissionResultDeny(message=f"Cannot write to system directory: {file_path}")
return PermissionResultAllow()
这就是"给 Agent 一台电脑"必须配的另一半:电脑的边界由你定义。
双向会话:ClaudeSDKClient
query() 适合一次性的问答;需要多轮交互时用 ClaudeSDKClient。它的额外价值在于:只有它支持自定义工具与 hooks,而且这两者都可以直接写成 Python 函数。
async with ClaudeSDKClient(options=options) as client:
await client.query("Greet Alice")
async for msg in client.receive_response():
print(msg)
自定义工具:进程内的 MCP server
这是这套 SDK 里最有工程味的设计。自定义工具通过进程内 MCP server 实现——不需要像常规 MCP 那样起独立进程:
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient
@tool("greet", "Greet a user", {"name": str})
async def greet_user(args):
return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
server = create_sdk_mcp_server(name="my-tools", version="1.0.0", tools=[greet_user])
options = ClaudeAgentOptions(
mcp_servers={"tools": server},
allowed_tools=["mcp__tools__greet"], # 预批准,避免权限提示
)
注意工具名的命名空间规则:mcp__<server名>__<工具名>。官方列的好处也很实在:不用管子进程、没有 IPC 开销、单进程部署、同进程调试、类型安全。而且进程内 server 和外部 MCP server 可以混用,mcp_servers 里同时放两种都行。
Hooks:由"应用"而不是 Claude 调用的拦截点
README 里对这个概念的界定很精确:hook 是 Claude Code 这个"应用"(不是 Claude)在 Agent 循环的特定位置调用的 Python 函数,用于提供确定性的处理和自动反馈。
async def check_bash_command(input_data, tool_use_id, context):
if input_data["tool_name"] != "Bash":
return {}
command = input_data["tool_input"].get("command", "")
for pattern in ["foo.sh"]:
if pattern in command:
return {"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": f"Command contains invalid pattern: {pattern}",
}}
return {}
options = ClaudeAgentOptions(
allowed_tools=["Bash"],
hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[check_bash_command])]},
)
这提供了权限清单做不到的能力:基于命令内容做细粒度判断,而不是基于工具名。
子 Agent:程序化定义
博客里说子 Agent 用于并行和上下文隔离,Python SDK 里可以直接声明:
from claude_agent_sdk import AgentDefinition, ClaudeAgentOptions, query
options = ClaudeAgentOptions(
agents={
"code-reviewer": AgentDefinition(
description="Reviews code for best practices and potential issues",
prompt="You are a code reviewer. Analyze code for bugs, performance issues, ...",
tools=["Read", "Grep"],
model="sonnet",
),
},
)
async for message in query(
prompt="Use the code-reviewer agent to review the code in src/...",
options=options,
):
...
子 Agent 有自己的 prompt、tools 和 model——用便宜模型 + 只读工具做审查,是很典型的省钱配置。
成本与错误
ResultMessage.total_cost_usd 能拿到本次运行的费用,仓库里还有 max_budget_usd.py 示例做预算上限。错误类型分了层:ClaudeSDKError 是基类,往下有 CLINotFoundError(没装 CLI)、CLIConnectionError、ProcessError、ResultError(运行以错误结果结束,异常上带 subtype / terminal_reason / api_error_status)、CLIJSONDecodeError,按类型分别处理比抓一个大异常再猜要靠谱得多。
选型与注意事项
它适合什么:你需要一个能用电脑干活的通用 Agent——读写文件、跑命令、写代码做计算、连外部服务,而且要能被人审查和约束。博客里那四类场景(金融、个人助理、客服、深度研究)都落在这个范围里。
用之前要接受的三件事:
- 它给的是"一台电脑",权限边界就是你的责任。
allowed_tools的语义(自动批准 vs 禁用)、permission_mode、can_use_tool回调、hooks,这几层要真的配起来,而不是全开。 - 验证环节最容易被跳过,也最决定上限。 规则 > 视觉 > 判官这个梯度不是可选项——没有 lint、没有截图回灌、没有 eval 集,Agent 就只能靠模型自觉。
- 迁移时注意改名成本。 从 Claude Code SDK(< 0.1.0)升级要做
ClaudeCodeOptions→ClaudeAgentOptions的改名、系统提示词配置合并、settings 隔离,新增了程序化子 Agent 与会话 fork 等能力,CHANGELOG.md里有完整清单。
另外补两个生态数字:截至目前,Python SDK 仓库 8,216 stars,TypeScript SDK 1,781 stars——Python 是主战场,但两边的核心概念(query / options / 自定义工具 / hooks / 子 Agent)是对齐的。
参考链接
- 官方博客:Building agents with the Claude Agent SDK — 本文主要来源,2025-09-29
- Claude Agent SDK 文档(Python) — SDK 官方文档入口
- Agent SDK 总览 — 与其他 Claude 工具的分工
- Agent loop — 循环与生命周期
- Custom tools / Hooks / Permissions — 三块最常配的能力
- Sessions / Session storage — 会话与持久化
- MCP / Skills / Plugins — 扩展方式
- Cost tracking / Observability — 成本与可观测性
- Hosting / Secure deployment — 部署与安全
- GitHub: claude-agent-sdk-python — 8,216 stars,含 hooks / 子 Agent / 自定义工具 / 会话存储示例
- GitHub: claude-agent-sdk-typescript — TypeScript 版本
- Claude Code 可用工具列表 — Read / Write / Edit / Bash 等基础工具
你的 Agent 现在卡在"收集上下文""采取行动"还是"验证工作"哪一段?评论区聊聊,觉得这套框架有用就点个赞。
作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top
本文首发于 AI人工智能时代,转载请注明出处。

浙公网安备 33010602011771号