Claude Agent SDK 与 OpenRouter Agent SDK 对照:循环放在哪一层、谁管工具谁管路由

2026-08-18

手上有个要自己规划步骤、自己调工具的活儿,选择无非两条:自己写那个「模型说要调工具 → 你去执行 → 把结果塞回去 → 再问一遍」的循环,或者找一个已经把循环写好的库。Claude Code 和 OpenRouter 各自都有一个叫 Agent SDK 的东西,名字撞得厉害,但两边文档对「这个库替你接管到哪一层」的表述完全不同。

这篇只做一件事:把两边文档里写明的边界摆在一起,看看差异在什么场景下会咬到你。两个产品都闭源,我们没有源码、也没有跑过,所以下面每一条都注明是谁的文档写的;文档里没写的地方,我会直接说没依据、不比。

一、先分清「循环」跑在谁的进程里

Claude Code 官方文档的 Agent SDK 概览页开头有一张对照表,第一行就是「要构建 agent 但不想自己实现 tool loop」,答案是 Agent SDK,理由写的是「A library that runs the agent loop in your own process, in Python or TypeScript」。同一张表还把另外三条路划清了:终端交互用 CLI;自己实现 tool loop 是 Client SDK 的事;不想自己管 sandbox 与会话基础设施的长任务走 Managed Agents,文档写明那是一个独立产品,由 Anthropic 来跑 agent 和 sandbox。

有意思的是同一份文档的《How the agent loop works》页还写了另一句:两个 SDK(TypeScript 和 Python)都捆绑了一个 native Claude Code binary,所以大多数安装不需要另外装 Claude Code。把这两句放一起读,能确认的事实是:循环跑在你的进程里,而这个库分发时带了一个原生二进制。它内部怎么分工,文档没有说明这一点,我们也不去猜——但对部署有实际影响的一点是明确的:装这个 SDK 不等于加一个纯 JS 或纯 Python 依赖,你的容器镜像里会多一个原生二进制。

OpenRouter 官方文档的 Agent SDK 概览页给的是另一种描述。包名是 @openrouter/agent,循环的入口是一个方法 callModel。文档把它的行为写得很直白:发消息给模型;如果模型返回 tool call 就自动执行;把 tool 结果追加进对话;重复,直到命中停止条件或者不再有 tool call。这一侧没有「捆绑二进制」这类说明,文档只写明安装 @openrouter/agent 会一并带上 Client SDKs,两个包也可以各自独立使用。

一句话对照:Claude Code 侧是「把 Claude Code 当库用」,OpenRouter 侧是「一个方法调用里跑完多步推理」。

二、谁管工具:一边默认给满,一边默认给空

这是两边差得最开的一处,也最容易在选型时被跳过。

Claude Code 文档的 agent loop 页列了 SDK 自带的内置工具,分成六类(这是那张表的行数,我数过):文件操作 Read/Edit/Write,搜索 Glob/Grep,执行 Bash,Web 的 WebSearch/WebFetch,发现类的 ToolSearch,编排类的 Agent/Skill/AskUserQuestion/TaskCreate/TaskUpdate。文档还注明,在拿不到任务追踪工具的那些模型上,TaskCreateTaskUpdate 需要你显式开启。也就是说这一侧的默认状态是「工具已经在了」,你的工作是做减法:allowed_tools/allowedTools 自动批准列出的工具,disallowed_tools/disallowedTools 无条件拦掉,permission_mode/permissionMode 决定整体要多少人工介入——那张模式表列了六档,从 "default""bypassPermissions"

OpenRouter 这一侧,文档描述的工具来源只有一处:你自己定义。tool() helper 接收 name、description、用 Zod 写的 inputSchema 和一个 execute 函数,文档写明 SDK 负责序列化、校验与 dispatch,概览页的示例是一个 get_weather 工具,execute 里直接返回一个写死的对象。我们在这两页里没有读到任何「SDK 自带工具」的清单或开关——需要说明的是,这是「文档里没写」,不等于「一定没有」,但对着文档做选型时,你能依据的就是:读文件、跑命令这类能力在这一侧要由你自己实现,边界也由你自己承担。

MCP 两边都有。OpenRouter 文档写明远程 MCP server 的工具可以直接进 callModel;Claude Code 文档除了支持 MCP,还写明 tool search 默认会把 MCP 的 tool schema 延后加载、按需载入,并说明在不支持的模型和某些平台上会退回到一次性全量加载。后面这条延迟加载的机制,我们在 OpenRouter 这两页文档里没有找到对应说明,不比。

三、循环怎么停

Claude Code 文档给的是选项字段:max_turns/maxTurnsmax_budget_usd/maxBudgetUsd,两者的默认都写作 No limit(这是文档写明的默认值,随版本可能变动)。有个容易读错的细节文档专门点了:max_turns 只数带工具调用的那些 turn。它举的例子是一个四 turn 的会话,前三 turn 有工具调用、最后一 turn 是纯文本回答;把上限设成 2,会在编辑那一步之前停住。文档还写明预算上限覆盖 subagent 的花费,一旦触顶,再 spawn subagent 会以 Budget limit reached 失败,并且这套上限执行行为要求 Claude Code v2.1.217 或更高版本。

OpenRouter 文档给的是另一种形状:stopWhen 收一个数组,数组元素是组合子,文档点名的有 stepCountIshasToolCallmaxCost 三个,并写明「and more」。也就是说这一侧的停止条件不是几个固定字段,而是一组可以往里加的谓词,写法是 stopWhen: [stepCountIs(...), maxCost(...)] 这样把若干条件并排放进数组。文档示例里给了具体阈值,那只是示例取值、不是推荐值,本文不抄——步数上限和花费上限该由你自己的场景和预算决定,抄一个数字进来对你没有任何帮助。

差别不在「能不能限次数、能不能限花费」——这两件事两边都能做——而在扩展形状:一边是固定的选项名,一边是一个谓词列表。至于 hasToolCall 具体按什么规则判定,我们读的这两页只给了名字没有展开,本文不替它下定义;Claude Code 这两页文档里也没有找到与之直接对应的选项。Claude Code 那边能在循环里插手的位置是 hooks,文档写明 PreToolUse 钩子拒掉一个工具调用可以短路掉这次执行,Claude 会收到一条拒绝消息。这两者不是一回事,各记各的账。

四、循环结束以后,结果从哪儿拿

Claude Code 侧是迭代一条消息流。文档写明五个核心消息类型:SystemMessage(用 subtype 区分 "init""compact_boundary" 等)、AssistantMessageUserMessageStreamEvent(只在开启部分消息时才有)、ResultMessage。判断任务到底怎么结束的,是 ResultMessage.subtype,文档列了五种取值:successerror_max_turnserror_max_budget_usderror_during_executionerror_max_structured_output_retries,并且明确说 result 字段只在 success 上存在,读之前必须先看 subtype。文档还提醒,结果消息之后可能还会有少量尾随系统事件,所以要把流迭代完,不要拿到 result 就 break。

OpenRouter 侧是另一种取法:callModel 返回一个 ModelResult 对象,上面挂着多个消费入口——getText()getResponse()getTextStream()getReasoningStream()getItemsStream()getFullResponsesStream(),以及工具侧的 getToolCalls()getToolCallsStream()getToolStream()。文档说明它建在 OpenRouter 的 Responses API 之上,用的是结构化 item(messages、tool calls、reasoning),并且这套流架构支持并发消费者。

这处差异很实在:一边要你写 for await 加类型分支,把整条生命周期看完;另一边可以只调 getText() 拿最终文本,需要细节再取别的流。要接可观测面板的话,前者天然给出阶段划分,后者给的是按需订阅。

五、模型这一层,也就是「谁管路由」

Claude Code 文档写明:不设 model 就用 Claude Code 的默认,默认值取决于你的认证方式与订阅;要固定就显式设成某个模型 ID。文档里这条选项是「pin 一个模型」的语义,我们没有在这两页里读到跨供应商切换的说明。

OpenRouter 侧,modelcallModel 的一个参数,示例里传的是形如 anthropic/claude-sonnet-4openai/gpt-5-nano 的 slug——这些只是官方文档当时的示例值,平台上有哪些模型随时在变,不要当清单用。概览页还写明有 Dynamic Parameters,可以在轮次之间根据上下文改 model、temperature 或 tools,另外写明支持与 OpenAI chat、Anthropic Claude 的消息格式互转。至于跨供应商的路由策略细节,不在我们读的这两页里,本文不展开。

所以「谁管路由」的答案是:一侧的模型选择是会话级的固定项,另一侧做成了每次调用的参数、且文档写明能在轮次间改。

六、几个我不比的维度

  • 上下文压缩:Claude Code 文档写了自动 compaction、compact_boundary 消息、PreCompact hook,以及把长期规则写进 CLAUDE.md(每次请求重新注入)而不是写进初始提示。OpenRouter 这两页只写了「SDK 跨轮次跟踪 messages、tool results 与 context」,自动压缩这类机制没有对应说明,不比。
  • 人工审批:Claude Code 有 permission_modecanUseTool 回调这一整套。OpenRouter 侧只能确认文档里有一页 Lifecycle Hooks,描述是能观察和控制 tools、prompts、approvals、sessions 与 model calls;具体档位与规则不在我们读的这两页里,不比。
  • 子任务隔离:Claude Code 文档写明每个 subagent 从干净对话开始、只把最终回复作为工具结果回传父级。OpenRouter 这两页没有对应说明,不比。

七、倒推:你的处境落在哪一边

  1. 要在代码仓库里改代码 → Claude Code 侧的内置工具就是那套文件、搜索、执行工具,不用自己实现;OpenRouter 侧这些要你自己写 execute,边界也归你。
  2. 工具全是你自己的业务接口 → 两边都要自己定义,这时决定因素不是工具集,而是语言和你想要的定义方式。
  3. 调用方不是 TypeScript → Claude Code 文档写明 SDK 只有 Python 与 TypeScript 两种,其他语言可以把 CLI 当子进程跑(用 -p--output-format json)来驱动同一个循环;OpenRouter 的对照表写明 Agent SDK 只有 TypeScript,Client SDKs 才覆盖 TypeScript、Python、Go,而 Client SDKs 按文档描述是不带 agent 循环的。这一条经常是最先把选项砍掉一半的那条。
  4. 要在多个模型之间切 → OpenRouter 侧文档明确支持在轮次间改 model;Claude Code 侧文档写的是 pin 一个模型 ID。
  5. 任务很长、上下文会顶到上限 → 只有 Claude Code 侧有成文的压缩与 subagent 机制可依据,另一侧没依据。

八、Windows 与 Linux/macOS

先说清楚:OpenRouter 文档给出的安装命令是 npm install @openrouter/agent(另外列了 pnpm、yarn、bun、deno 的等价写法),文档本身没有分平台给不同的安装命令——包管理器命令跨平台一致是通用常识,不是这两家文档写明的内容,这里只是提醒你别去找「Windows 专用安装命令」。文档里能核到的平台差异只有一处:Claude Code 文档写明 "bypassPermissions" 模式在 Unix 上以 root 身份运行时不可用,且在 TypeScript SDK 里还需要在 options 里设 allowDangerouslySkipPermissions: true;Windows 上的对应限制,文档没有说明这一点。

密钥两边示例都走环境变量(OpenRouter 示例里读的是 process.env.OPENROUTER_API_KEY)。Windows 下 PowerShell 与 CMD 设置环境变量的写法跟 Linux/macOS 的 export 不同,这属于通用做法、不是这两家文档的内容,本文不展开;代码里用 <YOUR_API_KEY> 这类占位,别把真实密钥提交进仓库。

还有一句得说在前面:这两个 SDK 都会在你的机器上执行工具、跑 shell、读写你的仓库。文档写明的权限选项是能核到的部分,但「配了某个模式就安全」这种结论文档没有给,我们也不给。上面涉及字段与选项的组合读法,是按官方文档中的字段语义组合的示例,未经实测,以官方文档与 API 的实际响应为准;两边迭代都快,选项名与默认值随版本变动。


本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。 该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。 该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。 本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。

本文涉及的另一方内容依据其官方文档整理(OpenRouter:openrouter.ai/docs)。 双方均为闭源商业产品,本文只对照各方公开写明的机制,不推断实现,也不对产品做优劣排名

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。