11 Claude Agent SDK 对比

QuibblerAgentQuibblerAgent 2026-11-13 约 17 分钟 10 次阅读

手写 Agent 的零件已经齐全,现在请出官方选手。本文是「从零手写 Agent」系列第 11 篇:认识 Claude Agent SDK——Claude Code 整套打包成库——并拿它与手写版逐项对账,看清框架替你做了什么、没替你做什么。

本文按"Agent SDK 是什么 → 逐项对账 → 事件流与权限 → 子 Agent 对照 → 选型 → 总结"组织。

1、Agent SDK 是什么

系列前十篇用的 anthropic 库是 API 客户端:请求、响应、流式事件,循环要自己写。Agent SDK 是另一层东西:Claude Code 的完整 harness 打包成库——安装后一个 query() 函数发进提示词,内部的 Agent 循环、内置工具(读写文件、执行命令、搜索、联网检索)、子 Agent、上下文压缩全部开箱即用。二者不是竞争关系,而是抽象层级不同:API 客户端给你零件,Agent SDK 给你整台机器。

上手的第一步是安装:

pip install claude-agent-sdk

解读:它是独立的包,与 anthropic 库分开安装、分开使用。核心用法大致如下:

from claude_agent_sdk import ClaudeAgentOptions, query

options = ClaudeAgentOptions(
    system_prompt="你是代码调研助手,回答要引用文件和行号。",
    allowed_tools=["Read", "Glob", "Grep"],   # 内置工具按名启用
    max_turns=10,                             # 与手写版安全阀同名同义
)
async for message in query(prompt=task, options=options):
    ...   # 每条消息一个事件:文本、工具调用、工具结果

解读:参数与手写版一一对应不是巧合——max_turns、系统提示词、工具白名单,正是系列第 5、6 篇手写过的那些旋钮。安装与配置细节以官方 Agent SDK 文档为准,源码与更多示例见 claude-agent-sdk-python 仓库。

1.1、query 循环的体感

query() 返回一个异步迭代器,宿主程序的工作从"写循环"变成"订阅循环"。把三类消息接住的最小骨架如下:

import asyncio
from claude_agent_sdk import (
    ClaudeAgentOptions, AssistantMessage, ResultMessage, UserMessage, query,
)

async def main():
    options = ClaudeAgentOptions(max_turns=10)    # 与手写版同名同义的阀
    async for message in query(prompt=task, options=options):
        if isinstance(message, AssistantMessage):   # 模型说话或点菜
            for block in message.content:           # text 与 tool_use 块
                ...
        elif isinstance(message, UserMessage):      # 工具结果上菜
            ...
        elif isinstance(message, ResultMessage):    # 收工账单
            print(message.num_turns, message.total_cost_usd)

asyncio.run(main())

解读:三类消息恰好对应手写版 verbose 日志的三种行——助手消息是"说话与点菜",用户消息是"上菜",ResultMessage 是手写版没有的"收工账单":轮数、耗时、总花费一次结清。系列第 5 篇的那个循环没有消失,它搬进了 SDK 内部;你的视角从灶台换到了出餐口,从此只管接菜。

2、逐项对账

把系列第 4 至 8 篇的手写零件与官方版本放在一起,对账表如下:

手写实现 Agent SDK 对应 感悟
while stop_reason 循环 query 内置循环 同一个心脏
工具说明书加真函数表 内置工具加 MCP 接入 它自带手脚
max_turns 安全阀 max_turns 选项 一模一样
摘要压缩与存档 自动压缩与会话管理 手写版是裸机版
子 Agent 派工工具 内置子任务机制 同一动机:上下文隔离
路径白名单拒单 权限模式与确认流 拒单权做成了产品
verbose 过程打印 完整事件流订阅 可观测性产品化

解读:对账后的正确心情是两句并存——"原来我写的就是这个",以及"原来产品化还差这么多"。第一句说明手写没有白费:框架每一层你都拆得开、修得动;第二句说明框架的价值在工程包裹层,不在"更聪明"。

2.1、心脏对照

对账表第一行值得展开成代码。手写版的心脏(系列第 5 篇原文节选)如下:

for turn in range(1, self.max_turns + 1):
    response = self.client.messages.create(          # 调用模型
        model=self.model, max_tokens=2048,
        tools=self.tools_spec, messages=self.history)
    self.history.append({"role": "assistant",
                         "content": [b.model_dump() for b in response.content]})
    if response.stop_reason != "tool_use":           # 心脏判断
        return "".join(b.text for b in response.content if b.type == "text")
    results = [self._execute(call) for call in tool_calls]
    self.history.append({"role": "user", "content": results})   # 回填结果

解读:五行代码在 Agent SDK 里每一行都有下落——messages.create 变成 harness 内部的模型调用,两处 history.append 变成会话管理,stop_reason 判断变成内置循环的退出条件,_execute 变成内置工具执行器。对照的价值在确认边界:SDK 替你执行了这五行,但没有替你理解这五行;哪一层出问题该去哪里排查,只有亲手写过的人才心里有数。

2.2、安全阀对照

第 5 篇给循环装了两道阀:max_turns 管轮数、max_tokens 管嘴长,篇末还预告"生产系统会加总花费上限"。官方版的对应物如下:

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep", "Glob", "Agent"],
    max_turns=30,          # 第一道阀:轮数上限,原名原义
    max_budget_usd=5.0,    # 第二道阀:整次任务总花费,美元计价
)

解读:max_turns 一字不改地进了产品;max_budget_usd 就是当年那句预告的落地——触到上限时任务以 error_max_budget_usd 的子类型收场,连子 Agent 的开销也一并计入总账。手写版当年只说"原理相同",官方版演示了原理兑现成一个参数需要多少工程:花费估算、跨进程聚合、超限即熔断,一样都不能少。

3、事件流与权限

Agent SDK 的输出是应用层事件流:每条助手文本、每次工具调用、每个工具结果都是一个可订阅事件。一次调研任务的事件序列形态如下:

[user]      调研 miniagent 项目的工具执行位置
[assistant] 文本:我来看看相关文件
[assistant] 工具调用:Read("miniagent/agent.py")
[user]      工具结果:文件内容……
[assistant] 文本:结论:run 方法内层循环,附代码引用

解读:这个节奏与手写版的 verbose 日志完全同构——说话、点菜、上菜、收工,系列第 5 篇的循环在官方 harness 里原样重现,只是每一步都成了可订阅、可拦截、可持久化的事件。

3.1、事件与 SSE 碎片

它与系列第 3 篇的 SSE 事件流的关系值得辨清:SSE 是传输层的增量碎片(一段段文字增量),Agent SDK 的事件是应用层的完整消息(一次工具调用、一条结果),后者由前者拼装而成——你在第 3 篇亲手写过那个拼装函数。

分层的红利在两个方向兑现。向上,应用层事件可以直接落库:一次任务的完整轨迹就是一份可回放的审计日志,也是第 10 篇评估框架梦寐以求的数据源——评测 Agent 时不再只有输入输出两端,中间每一步决策都可检验。向下,断流重连与增量拼接这些传输细节被 harness 收走,宿主程序一行都不用写。手写版把两个方向都留给你,SDK 把它们都做成了默认项。

3.2、权限回调实测

权限系统是官方版最值得学的工程化设计。手写版的路径白名单是"厨房拒单"的函数级实现;Agent SDK 把它升级为权限模式体系:敏感操作触发确认流,回调接口让宿主程序接管放行决定。模型可以请求执行命令,但执行与否由权限层裁决——安全模型从"写死的函数"进化为"可配置的策略"。

以拦危险命令为例,权限回调的本体如下:

from claude_agent_sdk import (
    ClaudeAgentOptions, PermissionResultAllow, PermissionResultDeny,
)

async def gate(tool_name, tool_input, context):
    if tool_name == "Bash":
        cmd = tool_input.get("command", "")
        if cmd.startswith(("rm ", "git push")):    # 破坏性命令拒单
            return PermissionResultDeny(
                updatedInput=tool_input,
                message="宿主程序拒绝:破坏性命令")
    return PermissionResultAllow(updatedInput=tool_input)   # 其余放行

options = ClaudeAgentOptions(can_use_tool=gate)

解读:回调收到工具名、入参与上下文,返回放行或拒绝,拒绝时还可附一句说明——模型读到"破坏性命令"的理由会自己改道,这正是第 6 篇"拒单信息要回传给模型"的产品化形态。位置上有个关键事实:权限链依次经过钩子、拒绝规则、询问规则、权限模式、允许清单,全都没拦下的调用才会到达 can_use_tool——allowed_tools 白名单放行过的工具根本不会进回调。手写版的拒单逻辑住在执行器里,是唯一的检查点;官方版把它拆成一条流水线,你在每一层都能插手。

4、子 Agent 对照

第 8 篇用三十行实现了"会创建 Agent 的工具";Agent SDK 把同一件事做成 agents 参数加 AgentDefinition 声明:

from claude_agent_sdk import AgentDefinition, ClaudeAgentOptions

reviewer = AgentDefinition(
    description="代码审查专员,质量与安全审查找它。",   # 主 Agent 靠这句派工
    prompt="你是代码审查专员,只读不写,结论必须给文件与行号。",
    tools=["Read", "Grep", "Glob"],        # 只发只读工具
)

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep", "Glob", "Agent"],   # Agent 即派工工具
    agents={"code-reviewer": reviewer},
)

解读:description 字段是"描述是工具的唯一 UI"那条原则的再兑现——主 Agent 派不派工、派给谁,全凭这一句自然语言匹配;tools 字段把第 8 篇"给子 Agent 单独配工具表"做成了声明。两版的逐项对照如下:

手写子 Agent(第 8 篇) Agent SDK 对应 同与不同
delegate_task 里新建实例 AgentDefinition 声明 运行时造人对在册登记
派工工具写进说明书 内置 Agent 工具 派工入口成了标配
子实例独立 history 子会话独立上下文 过程垃圾同样不进主线
只回传结论文本 只回传最终报告 隔离动机一字不差
返回值手拼 token 账单 花费自动计入总账 成本可见成了默认
深度上限手写注入 嵌套与并发数有默认上限 第 8 篇铁律成了配置

解读:两版最深的一致仍是那句"多 Agent 的本质是垃圾桶隔离";最大的差异在定位——手写版的子 Agent 是运行时现造的临时工,AgentDefinition 是登记在册的正式岗位,后者天然可审计、可复用,前者胜在随心所欲。

5、选型判断

同一个调研任务两边各跑一遍的定性结论:小项目上答案质量相当——毕竟同一个模型在干活;token 与延迟上手写版反而更省,因为内置工具说明书体量可观,起跑线成本高出一截;框架真正的护城河是权限、会话、压缩、生态这些长跑保障。

由此得出选型直觉:快速原型、特殊控制流、学习原理,手写轻装上阵;标准编码与文件任务、要工程保障和生态,框架登场。两条路不是二选一,理解框架每一层之后,你随时可以在手写版与框架版之间搬运设计。

成本构成值得拆开看。手写版起跑时只带系统提示词加几个工具说明书;Agent SDK 起跑时背上的是 Claude Code 完整系统提示词与一整套内置工具说明书,首轮请求的固定开销高出一截,内置工具越全差距越大。省钱的姿势不是卸框架,而是收权限:allowed_tools 收得越紧,说明书体量与风险敞口同步收敛。

控制力也没有想象中失去得多。事件流让你看见每一步,权限回调让你拦住每一步,钩子让你在步骤之间插程序——三者组合,多数"必须手写"的控制诉求其实能在框架内拿回。真正的分水岭只剩一条:要不要改循环本身。当你的控制流与官方 harness 冲突(自定义退出条件、每轮强制人工审核这类需求),手写版才是唯一选项。

6、总结

Agent SDK 是 harness 级产品:循环、工具、安全、会话全部内置,手写版的所有零件都能在它身上找到对应物;框架的价值在工程包裹层,选型看任务规模与控制力需求。对完成本系列手写部分的读者,建议把对账表里每一行都亲手验证一遍——跑通事件流、触发一次权限确认,验证过的认知才归你。最后一篇请出 LangGraph,用"图"重写同一个 Agent,为整个系列收官。SDK 生态详见 Claude Code 文档。

相关推荐

获取系统SDK版本、判断手机ROM
精选Code

获取系统SDK版本、判断手机ROM

Build获取系统SDK版本Android中部分API的使用,需要在特定的SDK版本之后才能使用,因此在兼容老版本SDK的时候,经常需要判断API的版本。各种Android版本的对应关系参考《Android各版本对应的SDK版本》判断手机ROM有时候需要判断手机系统的ROM,检测ROM是MIUI、EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件(关于build.p

4.3k
AndroidStudio中各种中文乱码问题
精选Code

AndroidStudio中各种中文乱码问题

AndroidStudio中各种中文乱码问题1、编译Java错误信息乱码在出现这个Annotation processors must be explicitly declared now...问题的时候,正好也发现AndroidStudio Build Output错误信息都乱码。经常遇到各种问题,习惯了,现在遇到的问题,都是以后的答案。 1.1、修改项目build.gradle(无效)在整个p

2.8k
Multi-Agent 详解:多智能体协作架构与实践
精选Agent

Multi-Agent 详解:多智能体协作架构与实践

一个智能体配上一套工具,已经能完成相当多任务。但让它同时“当产品经理、写后端、跑测试、做代码评审”,很快就会露馅:上下文里塞满了互相干扰的指令,十几件工具的清单来回切换,任务做到一半忘了开头。解法看起来很自然——像人类团队一样分工:让多个智能体各司其职,由一个协调者调度,这就是 Multi-Agent(多智能体)系统。它也是 2026 年智能体工程里讨论度最高、误用率也最高的架构。本文按“架构模式…

144