SDK 形态对照:Claude Agent SDK 与 Cursor 的 SDK / Bridge 各自解决什么

2026-08-18

把编码 agent 塞进自己的程序里,通常是这么开始的:CI 上想要一个自动修 lint 的 job,或者内部工单系统想要一个能读仓库、改代码、开 PR 的 worker。到了选型这一步就会发现,两边文档对「SDK」这个词的定义都不一样。

下面按五个岔口走一遍,每一步只用两边文档都白纸黑字写明的东西。一方查不到的维度,直接说不比。

岔口一:agent loop 跑在谁的进程里

Claude Code 官方文档《Agent SDK overview》页开篇给了一张四行的对照表,把四样东西分开摆:Agent SDK 是「在你自己的进程里跑 agent loop 的库」;Claude Code CLI 是终端交互界面,为日常交互而做;Client SDK 是直连 Anthropic API、tool loop 由你自己实现;Managed Agents 是托管 REST API,文档写明它是 a separate product from the Agent SDK,由 Anthropic 来跑 agent 和 sandbox。四行各对应一种处境,SDK 只占其中一行。

Cursor 官方文档《Cursor TypeScript SDK》页的开篇表是另一种切法:一个接口包住两个 runtime。Local 是「在你的 Node 进程里内联跑 agent loop,文件来自磁盘」,Cloud 是「在隔离 VM 里跑,仓库被 clone 进去,VM 由 Cursor 运行」。选哪个取决于你给 Agent.create() 传的是 local 还是 cloud 这个键,两者共用同一个 CURSOR_API_KEY。文档还专门加了一段澄清:Local 说的是 agent loop 和文件访问在本地,不是模型在本地,两种模式的推理都走 Cursor 托管的模型。

这一层的判断很直接。Cursor 文档给 cloud 列了三种适用情形:调用方手上没有那个仓库、你想并行跑很多 agent、运行要能活过调用方断连。如果你正好是这三种之一,Cursor 侧在同一个 SDK 里就有对应形态;Claude 这边的对应能力在 Agent SDK 之外——overview 页把「跑长时间或异步 agent、又不想自己管 sandbox 和 session 基础设施」那一行指向了 Managed Agents,并明说那是另一个产品。同一个包里有没有这一档,是两边最结构性的差别。

顺带一个细节:Cursor 的 agent ID 前缀直接暴露 runtime,local 是 agent-<uuid>,cloud 是 bc-<uuid>Agent.resume() 靠前缀自动判断走哪条路。

岔口二:你的服务既不是 TS 也不是 Python

两边的第一方语言完全一样:TypeScript 和 Python。差别全在「其它语言怎么办」。

Claude Code 文档的回答是一句话:SDK 只以 Python 和 TypeScript 库的形式提供,要在别的语言里驱动同一个 agent loop,就把 CLI 当子进程跑,带 -p--output-format json。跨语言这条路是进程加 JSON 流,没有单独的协议层。

Cursor 的回答是一个独立组件:SDK Bridge。文档描述它是「一个内嵌了 TypeScript SDK 的本地小服务器,用一套稳定的 Connect/protobuf 协议把同样的 agent 表面暴露出来」。你的 adapter 负责 spawn cursor-sdk-bridge 二进制,或者连到平台上已经跑着的那个;bridge 绑一个回环 HTTP/1.1 端口,提供 sdk.v1 服务。这里有个坑文档专门点名了:传统的 gRPC over HTTP/2 连不上,必须用 Connect 客户端,或者直接发带 protobuf / JSON body 的 POST

sdk.v1 契约由七个 proto 文件组成(按文档那张表数过):agent 服务、cursor 服务(身份、模型、仓库)、bridge 控制服务、自定义工具回调服务、store 回调服务、共享消息、结构化错误。其中两个回调服务(自定义工具回调、store 回调)在表里被标为由你的 adapter 托管——bridge 反过来调你,用来跑用户定义的工具和自定义 store。调用方向不是单向的。

认证也是两把钥匙:Cursor API key 设在 options.api_key 上并导出到 bridge 进程环境里,另加一个 bridge bearer token,在 ready-line 握手时按进程生成,之后每个 RPC(包括流)都要带 Authorization: Bearer <token>,bridge 默认监听 127.0.0.1

还有一句必须照实标:Cursor 文档写明它只发布和支持 sdk.v1 协议与 bridge 二进制,其它语言的 adapter 不是第一方 SDK,版本、支持和安全审查归你自己。拿这条路做生产系统前,这句话该先给负责人看一遍。

Windows 这一侧

两边文档都提到了 Windows,但提的是不同的东西,别混。

Cursor 的 bridge 发行归档里,二进制是 bin/cursor-sdk-bridge,文档写明在 Windows 上是 .exe 结尾;平台组合用 darwinlinuxwin32x64arm64,其中 Windows 只有 x64。ARM 的 Windows 机器在这条路上没有现成归档。

Claude Agent SDK 这边,Windows 出现在「编译成单文件可执行程序」那一节。SDK 平时把 Claude Code 原生二进制作为可选依赖打包,但 bun build --compile 编出的单文件里 require.resolve 不工作,需要把平台二进制当文件资产嵌进去,用 extractFromBunfs() 解出真实路径再传给 pathToClaudeCodeExecutable。文档给了 Windows 的写法:二进制子路径是 claude.exe,例如 @anthropic-ai/claude-agent-sdk-win32-x64/claude.exe

至于 sandbox 在 Windows 上怎么落地——Cursor 的 sandbox 一节只点名了 Linux 的 bubblewrap 和 macOS 的 seatbelt,加上随包分发的 helper;Claude 这边写的是「sandbox 依赖平台支持,在 Linux 上依赖 bubblewrapsocat 这类工具」。两边都没有对 Windows 沙箱的正面说明,这一点我们没有依据,不比。

岔口三:代码里能改的到底是哪几个把手

这是最容易只看 README 就下结论的地方。两边给你的把手形状差得很远。

Claude Agent SDK 的核心是 query(),它返回的 Query 对象本身是个控制面,不只是消息流。摘几行和自动化直接相关的:

方法文档写明的作用
setPermissionMode(mode)改权限模式,仅 streaming input mode 可用
setModel(model?)改模型,仅 streaming input mode;传 undefined"default" 回落到会话默认
applyFlagSettings(settings)运行时把设置合并进会话的 flag settings 层
setMcpServers(servers)动态替换本会话的 MCP server 集合
getContextUsage()按类别、skill、工具拆解上下文占用
stopTask(taskId)按 ID 停掉后台任务

这张表只摘了和本篇对照直接相关的几行,Query 的完整方法表比这长得多。applyFlagSettings() 下面还有一条很实在的限制:只有部分 key 中途生效,permissionshooksagent 在下一轮生效,model 在当前轮生效,而 system prompt 类选项中途改不动——调用会成功,但会话仍用启动时解析的值,要换只能开新会话。这种「调用成功但没生效」的坑,不翻文档查不出来。另外 setMaxThinkingTokens() 已被文档标为 deprecated,改用 thinking 选项。

权限这一块落差最明显。Claude 侧的 canUseTool 回调,文档定位得很清楚:它是交互式权限提示的 SDK 替代品,只在权限评估流程落到「提示」这一步时才被调用。已经被 allowedTools、settings 里的 allow 规则,或者 acceptEdits / bypassPermissions 这类模式放行的调用,压根不会进这个回调。想拦住每一次工具调用,文档让你改用 PreToolUse hook。这个区别相当反直觉,写成守卫函数却发现有一批调用根本没进来,多半就是踩在这里。

Cursor 在对应位置上给的是另一种答案。《Cursor TypeScript SDK》页 Hooks 一节写明:hooks 只有文件形式,没有编程式回调,并给了理由(文档自述)——hooks 是项目策略边界,不是 per-run 的旋钮。本地要放 .cursor/hooks.json,云端要把它和脚本一起提交进 cloud.repos 指定的仓库。

那 Cursor 在代码里能改什么?文档列得也具体:

  • tools 白名单与 disallowedTools 黑名单,deny 优先;两者只对 local agent 生效,且不持久化在 agent 上,Agent.resume() 时要重新传
  • local.customTools:把你自己的函数直接给 agent,SDK 会注册成一个名叫 custom-user-tools 的 MCP server;同样只支持 local,传给 cloud agent 抛 ConfigurationError
  • local.sandboxOptions.enabledlocal.autoReview,后者文档明说是 best-effort 的便利功能、不是安全边界
  • 每次 send() 可以带 onDelta / onStep 回调,拿比 SDKMessage 更细的 InteractionUpdate

所以这一岔口的判断是:如果合规要求是「每一次 shell 调用都要过我写的那段代码」,Claude 侧有进程内的 hook 回调和 canUseTool 承接;Cursor 侧的等价物在文件里,得随仓库走。 反过来,如果你的策略本来就该跟着仓库走、还要在云端 VM 里生效,Cursor 的文件式 hooks 正好落在这个位置——文档写明 SDK 创建的 cloud agent 会自动加载仓库里的 project hooks。

// Load only project settings, ignore user and local
const result = query({
  prompt: "Run CI checks",
  options: {
    settingSources: ["project"] // Only .claude/settings.json
  }
});
// Read-only agent: only these tools are offered.
const reader = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  tools: ["read", "grep", "glob", "ls"],
  local: { cwd: process.cwd() },
});

以上两段均原样取自各自官方文档的示例,未经实测,以官方文档与 API 的实际响应为准。第二段里的模型标识只是官方文档当时的示例值,平台上有哪些模型随时在变,不要当清单用。

岔口四:默认是放行还是拦

两边的默认都不是「默认安全」,这点得先说清。

Cursor 文档在 Quick start 底下直接挂了提醒:默认的 local agent 会不问就执行 shell、edit、write 等工具调用,headless 模式下没有 human-in-the-loop 提示;要设卡就配 hooks(如 beforeShellExecutionpreToolUse),或者打开 local.sandboxOptions.enabled: true。sandbox 一节写明默认是 { enabled: false },理由是文档自述的:headless 跑没有人来批准,默认开沙箱要么静默挡掉合法调用,要么需要一个不适合脚本形态的回调。打开后的约束写在文档里:写入限制在 local.cwd 和少量允许路径、工作区外的读被挡、出站网络默认拒绝,要放行就在工作区放 .cursor/sandbox.json 列出允许的 host。

Claude 侧对应的两个开关是 permissionModesandboxpermissionMode 默认 'default',类型里一共六档:defaultacceptEditsbypassPermissionsplandontAskautosandbox 默认 undefinedSandboxSettings.enabled 默认 false;一旦开了 enabled: true,还有个 failIfUnavailable 默认为 true,意思是沙箱起不来就在启动时停住,想退回不带沙箱执行得显式设成 false。文档另外警告:allowUnixSockets 放行 /var/run/docker.sock 这类 socket,等于通过 Docker API 拿到宿主机权限,绕开沙箱隔离。

以上都是文档写明的默认值,随版本可能变动,也不是「你用起来会怎样」的保证。开了沙箱不等于安全,两边文档自己都没这么说。

岔口五:磁盘上那些配置要不要读

最后一个容易吃亏的地方:SDK 跑起来到底继承了多少本机配置。

Claude 侧是 settingSources,三个取值 user / project / local,分别对应 ~/.claude/settings.json.claude/settings.json.claude/settings.local.json。省略时与 CLI 一致,三层都加载;传 [] 一层都不读。要让 CLAUDE.md 被读进来,文档给的做法是把 project 列进去。但 endpoint-managed policy 不受这个选项控制,照样加载。

还有一条最容易先入为主的:systemPrompt 的默认值是 undefined,也就是最小提示词,而不是 Claude Code 那一套。要拿 Claude Code 的系统提示,得显式传 { type: 'preset', preset: 'claude_code' }。以为「装了 SDK 就等于把 Claude Code 嵌进来了」的,多半会在这里发现行为对不上。

Cursor 侧是 local.settingSources,六个取值:projectuserteammdmpluginsall(最后一个是前五个的简写)。不传时文档写明只加载 inline 定义的 MCP server(其余磁盘层不读)。更要记住的是:这个字段对 cloud agent 不生效,cloud 永远加载 project / team / plugins。同一段代码从 local 切到 cloud,配置来源会变,这条在文档的 Known limitations 里又重复列了一遍。

没有依据、不比的部分

  • 成本口径:Cursor 给了 TokenUsage 字段表和 agent.getUsage(),Claude 侧有 maxBudgetUsd 这个选项存在,但两边的计量口径与准确性说明在本篇没有引用的页面上,不比。
  • hook 事件粒度:Claude 侧的 hook 事件类型在本篇引用的参考页里就有一长串,Cursor 的事件清单在另一页,本篇没读,不比。
  • 稳定性、速度、生成质量:我们没有跑过任何一边,全篇不涉及。
  • 照实标一句:Cursor 文档写明 Team Admin API key 尚不支持,artifact 下载对 local agent 未实现。

压成几条 if

  • 要在自己的进程里跑 agent loop,而且要在代码里逐次拦工具调用 → Claude Agent SDK 的 canUseTool 加 hooks 回调是文档写明的承接点
  • 要托管、要并行、要活过断连,还想留在同一个 SDK 里 → Cursor 的 cloud runtime;Claude 侧的对应形态是另一个产品
  • 服务是 Go / Rust / Java / C# → Cursor 走 SDK Bridge(但 adapter 非第一方);Claude 走 CLI 子进程加 --output-format json
  • 策略要跟着仓库走、还要在云端生效 → Cursor 的文件式 hooks
  • 要一个可复现的干净环境、不吃本机配置 → 两边都有开关(settingSources: [] 与不传 local.settingSources),但 Cursor 的 cloud 是例外

两边都在高频迭代,上面每一个字段名、默认值和限制条件都可能随版本变,落地前请以各自官方文档最新内容为准。


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

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

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

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