跳至主要内容

Cursor SDK 教程:使用 TypeScript 运行编码代理

使用 Cursor SDK 运行本地代理,然后运行云端代理,在 GitHub 仓库中修复一个小错误并打开拉取请求。
· 12分钟 阅读

使用 AI 探索

Cursor 于 2026 年 4 月下旬发布了其 TypeScript SDK 公测版。该包以 @cursor/sdk 的形式发布,可在脚本、CI 任务和后端服务等 Node 环境中运行。

与在编辑器中使用 Cursor 的主要区别在于任务的触发位置。不再是您自己打开聊天并输入提示,而是由您的代码创建代理、发送任务、流式接收事件、等待结果并处理错误。

在本教程中,我们将完成 SDK 的安装、运行本地快速上手,然后构建一个主项目:一个在云端修复 GitHub 仓库中的错误并打开拉取请求的代理。为了便于观察 SDK 的流程,我特意将错误设置得很小。随后,我们将介绍在复用该模式前所需的扩展点和安全检查。云端项目配套有一个示例仓库,包含启动脚本与目标项目。

SDK 仍处于公测阶段,如要在长期项目中复用本文代码,请先查阅官方文档。

什么是 Cursor SDK?

Cursor SDK 是一个 TypeScript 包 @cursor/sdk,可让您在代码中创建并运行 Cursor 代理。它提供对以下内容的访问:

  • 本地与云端的代理运行。
  • Cursor 的代码库工具,包括索引、搜索、grep、MCP 服务器、技能、钩子和子代理。
  • 您 Cursor 账户可用的模型,包括Composer 2、GPT-5.5 和 Claude。

SDK 使用与 Cursor IDE、CLI 和 Web 应用相同的代理系统,不同在于您通过 TypeScript 调用它。

何时使用 SDK

SDK 适合那些应由代码发起、而不是由人在编辑器中输入的任务。我会在以下场景使用它:CI 任务让代理检查失败的测试、Webhook 为 Bug 修复创建分支、或内部工具从表单运行固定的代理任务。

SDK 与 Cursor 应用的对比

SDK 是使用 Cursor 代理的另一种方式,与 Cursor IDE 和 cursor agent CLI 并列。

编辑器对话用 IDE。终端提示用 CLI。当需要由 TypeScript 代码创建代理、发送任务并处理结果时,用 SDK。如上所述,CLI 不支持外部提供商密钥;SDK 同样仅通过 Cursor API 密钥进行认证。

Cursor SDK 的组成

在编写代码前,先了解 SDK 暴露的几个对象和运行时选项会更有帮助。

Diagram showing Cursor SDK code routing to local Node, Cursor cloud VM, or user managed VM, all sharing the same agent tools and model layer.

Cursor SDK 在三种运行时下的架构。图片作者自制。

三种运行时

SDK 支持在三个位置运行代理。

运行时 

作用

适用场景

本地 

在您的 Node 进程中内联运行代理,从磁盘读取文件

开发脚本、针对工作树的 CI 检查、快速迭代

Cursor 云端

在 Cursor 托管的隔离 VM 中运行,并克隆您的仓库

并行代理、更长任务、断开后仍可继续的运行

自建云端

形态与云端一致,但使用您自己的 VM 和网络

需要让代码、机密和构建产物留在内部环境的团队

本文将使用本地与 Cursor 云端。上表中的自建云端主要面向企业版方案。通过传入的配置键即可切换 SDK 代码:local 或 cloud。

运行时、工具与模型

一次运行由三部分构成。运行时决定执行位置。代理工具包括索引、搜索、MCP 工具调用、技能、钩子与子代理。模型通过 model: { id: "composer-2" } 或您账户可用的其他 ID 选择。

这些都在代理配置中设置。

Agent 与 Run

SDK 中的两个主要对象是 Agent 和 Run。Agent 保存会话状态、工作区配置与模型设置。Run 则是发送给该代理的一次提示,具有独立的流、状态、结果和取消句柄。

这种区分很重要,因为云端代理强制每个代理同一时间只允许一个活动的运行。如果您在第一个仍在进行时发送第二个提示,API 会返回 409 agent_busy。要并行运行任务,应创建多个代理,而不是在同一个代理上创建多个运行。

流式事件

每次运行都通过 run.stream() 暴露一个事件流,这是一个异步迭代器。每个事件都有 type 字段。在当前公测版中,SDK 会发出 system、user、assistant、tool_call、thinking、status、request 和 task 事件。目前没有记录在案的 connection:reconnecting 事件;重连由 SDK 内部处理。

若需更底层的更新,agent.send() 也接受 onDelta 和 onStep 回调。

设置 Cursor SDK

所需仅为 Node、TypeScript 和一个 Cursor API 密钥。

先决条件

您需要:

  • Node.js 22 或更高版本。该包正式支持 Node 18 或更高版本,但 Node 22 与官方示例一致,并支持用于加载 --env-file 的 .env 标志。

  • 用于云端代理的 Cursor Pro($20/月)或更高方案账户。

  • 基础的 TypeScript 知识。

  • tsx 以免编译即可运行 TypeScript。

安装 SDK 与 TypeScript 工具:

安装 SDK

在一个全新文件夹中:

npm init -y
npm install @cursor/sdk
npm install --save-dev typescript tsx @types/node

在 package.json 中添加 "type": "module" 以使用 ESM 导入。然后添加支持顶层 await 和显式异步释放的 tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022", "ESNext.Disposable"],
    "strict": true,
    "esModuleInterop": true
  }
}

获取 Cursor API 密钥

该密钥最初在 cursor.com/dashboard/cloud-agents 下生成,但现已迁移至 cursor.com/dashboard/integrations。若某指南仍指向“Cloud Agents”,请改到 Integrations。

Cursor dashboard Integrations page with the User API Keys section highlighted and a Generate button visible.

在 Integrations 中生成用户 API 密钥。图片作者自制。

在那里生成用户 API 密钥并将其保存为 CURSOR_API_KEY:

echo 'CURSOR_API_KEY=crsr_your_key_here' > .env

将 .env 加入 .gitignore。SDK 直接读取 process.env;它不会为您加载 .env 文件。

项目结构

文件夹布局:package.json、tsconfig.json、.env,以及用于脚本的 src/。需要时添加 .cursor/ 文件夹以放置钩子、技能与子代理。

您的第一个本地 Cursor 代理

第一个示例故意保持精简。它创建一个本地代理,发送一个提示,流式输出响应,最后释放代理。

创建本地代理

创建 src/01-quickstart.ts:

import { Agent, type SDKMessage } from "@cursor/sdk";

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});

Agent.create() 会在代理开始工作前返回一个句柄。 local: { cwd: process.cwd() } 将代理指向当前工作目录。SDK 支持异步释放;在教程代码中,我更倾向使用显式的 finally 块,以避免 await using 的版本兼容问题。

发送提示并流式输出响应

发送提示会返回一个 Run 对象,拥有自己的流与状态。此示例在 for await 循环中读取流,并仅打印助手文本。

try {
  const run = await agent.send(
    `Write a terminal-friendly summary for a screenshot.

Output exactly:
Local agent summary
- Purpose: demonstrates a local Cursor SDK agent.
- Key files: src/01-quickstart.ts, package.json, tsconfig.json.
- SDK action: creates an agent and streams assistant text.

Rules:
Print exactly those three bullets.
No Markdown bold.
No extra explanation.`,
  );

  for await (const event of run.stream()) {
    if (event.type !== "assistant") continue;
    for (const block of event.message.content) {
      if (block.type === "text") {
        process.stdout.write(block.text);
      }
    }
  }

  const result = await run.wait();
  const duration = result.durationMs === undefined ? "" : `duration=${result.durationMs}ms`;
  console.log(`\n[done] status=${result.status}${duration}`);
} finally {
  await agent[Symbol.asyncDispose]();
}

代理会发出多种事件类型,包括 thinking、tool_call 和 status。本例仅筛选可见答案的 assistant 文本。event.message.content 有类型定义并可用于流式处理,但它是分块的,且可能包含工具调用。若您只需最终文本,可跳过流,待 run.wait() 后读取 result.result。durationMs 是公开但可选的,因此示例将其按可选处理。

处理错误

SDK 会抛出继承自 CursorAgentError 的类型化错误。常见情形包括 AuthenticationError(密钥错误)、ConfigurationError(模型 ID 无效)、RateLimitError、IntegrationNotConnectedError 和 NetworkError。

import { CursorAgentError } from "@cursor/sdk";

try {
  // ... agent code
} catch (error) {
  if (error instanceof CursorAgentError) {
    console.error([${error.code ?? "unknown"}] ${error.message});
    if (error.isRetryable) {
      console.error("Retryable. Try again in a moment.");
    }
  } else {
    throw error;
  }
}

isRetryable 标志是您的重试逻辑应当检查的。网络错误与限流可重试;配置错误与认证错误不可重试。

运行示例

保存文件,使用 Node 的 .env 加载器与 tsx 运行:

node --env-file=.env --import tsx/esm src/01-quickstart.ts

--env-file=.env 标志会在脚本启动前加载 CURSOR_API_KEY 。脚本应打印助手文本,然后是一行状态尾注。若出现认证错误,请检查 .env ,并确认密钥来自 Integrations 控制台生成。

从本地代理流式获取事件。视频作者自制。

构建云端错误修复代理

下一个示例从本地文件夹切换到在 Cursor 云端克隆的 GitHub 仓库。任务仍然很小:修复一个失败的认证测试并打开拉取请求。

何时选择云端

云端代理运行在 Cursor 管理的 VM 中。它们会克隆仓库、设置开发环境,并在您的本地脚本退出后继续运行。完成后,它们可以推送分支并打开拉取请求。代价是与本地小型运行相比,启动时间更长且令牌消耗更高。

通过 SDK 启动的云端运行。视频作者自制。

云端运行工作过程中会出现在 Cursor Web 与桌面版的代理窗口中。SDK 云端代理默认从列表中过滤。在 Cursor Web 中使用 Filter > Source > SDK。在桌面代理窗口中,使用侧栏页脚: Show > SDK。如果您有 bc- 开头的代理 ID,也可直接在 https://cursor.com/agents/bc-... 或通过桌面端深链打开。一个简易的规则是:满足以下任一条件就使用云端:

  • 任务可能超过本地脚本会话时长。
  • 您期望输出为 PR 或分支,而非仅文本。
  • 您想对同一仓库并行运行多个代理。
  • 代理需要在隔离环境中运行代码(测试、构建)。

对于简短的本地检查,请使用本地运行时。

配置代理

云端配置将 local 键替换为 cloud 键。您列出要克隆的仓库,可选固定起始分支,并设置运行结束时 Cursor 是否应打开 PR。

import { Agent, CursorAgentError } from "@cursor/sdk";

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  name: "Cloud bug fixer",
  model: { id: "composer-2" },
  cloud: {
    repos: [
      { url: "https://github.com/your-org/your-repo", startingRef: "main" },
    ],
    autoCreatePR: true,
  },
});

console.log(Started cloud agent ${agent.agentId});

repos 是一个数组,但云端 v1 目前每个代理仅支持单个仓库。startingRef 指定代理的起始分支或提交。 autoCreatePR: true 会在运行结束时请求 Cursor 打开拉取请求。但 GitHub 权限、集成状态、空 Diff 或仓库规则等仍可能只生成分支而非 PR。

要让代理克隆仓库,您的 Cursor 账号需完成 GitHub 集成连接。若未连接,SDK 会返回 IntegrationNotConnectedError,并包含 helpUrl 字段。

发送任务并在稍后重连

下面的模式会发送任务,然后通过 Agent.getRun() 等待结果。这样即使原脚本退出,另一个进程也能在稍后重连。

const run = await agent.send(
  "Find the failing test in the auth module, fix the bug, and add a regression test.",
);
console.log(Run ${run.id} in progress.);

const handle = await Agent.getRun(run.id, {
  runtime: "cloud",
  agentId: agent.agentId,
  apiKey: process.env.CURSOR_API_KEY!,
});

const result = await handle.wait();

const branch = result.git?.branches?.[0];
console.log(Status: ${result.status});
if (branch?.prUrl) {
  console.log(PR: ${branch.prUrl});
} else if (branch?.branch) {
  console.log(Branch: ${branch.branch});
}

您可以流式查看运行的实时输出,但当您只需要结果时,wait() 已足够。若创建了 PR,其 URL 会返回在 result.git?.branches[0]?.prUrl;云端 v1 尚不支持多仓库,因此索引 0 即为要检查的分支。若没有 PR URL,请查看 branch?.branch 并手动打开 PR。若计划稍后重新连接,请保留 run.id 与 agent.agentId。

来自云端代理的 GitHub PR。视频作者自制。

至此,像审阅其他代码变更那样审查该拉取请求即可。

本地与云端一览

两种运行时使用相同的 SDK,但 表现不同。

能力

本地

云端

运行位置

您的 Node 进程

Cursor 管理的 VM

文件访问

您的磁盘

仅克隆的仓库

断线后继续

否

是

打开 PR

否

是(权限允许时)

返回制品

否

是(15 分钟预签名 URL)

适用

迭代、在检出上进行 CI

更长任务、并行运行、PR 输出

快速检查用本地运行。需要分支、PR 或制品时用云端运行。

其他示例

错误修复示例使用了 SDK 的主流程:创建代理、发送任务、等待结果并审查输出。Cursor 的 cookbook 在更大型示例中展示了相同的 SDK 调用:

  • agent-kanban 列出云端代理,按状态或仓库分组,并预览制品。

  • coding-agent-cli 将本地与云端代理封装为终端工具。

  • app-builder 从聊天界面运行本地代理,并预览生成的 React 代码。

有一处细节需要理清:制品处理。制品仅在云端运行中可用。本地代理适合文本输出与快速检查。云端代理适合需要文件、分支或 PR 作为输出的任务。

MCP、技能、钩子与子代理

SDK 可以读取与 Cursor 在 IDE 中使用的相同项目代理配置。错误修复示例并未用到全部能力,但在代理开始在真实仓库工作后,这些部分就很重要。

MCP 服务器

如前所述,MCP 服务器将代理连接到外部工具。您可以在 Agent.create() 中内联传入,或在 .cursor/mcp.json 中定义。若在 agent.send() 中再次传入 mcpServers,该次运行会使用 send() 中的服务器而非 Agent.create() 中的。托管工具使用 HTTP MCP 服务器;与代理同侧运行的工具使用 stdio MCP 服务器。

技能

技能是放在 .cursor/skills/ 下的 Markdown 文件,向代理提供项目级指引,如测试框架选择、API 约定或发布规则。将其用于应适用于仓库中每次运行的指导。

钩子

钩子位于 .cursor/hooks.json,在代理循环的特定时点运行。常见用途包括文件修改后的格式化、以及在执行前阻止破坏性的 shell 命令。对于安全钩子,采用失败即阻断的策略,以便钩子失效时阻止操作。

子代理

子代理是主代理可调用以聚焦完成特定工作的命名代理,如代码评审或测试编写。在 .cursor/agents/*.md 中定义,或在 Agent.create({ agents: { ... } }) 中内联定义。云端代理会从检出的仓库加载项目子代理。本地代理若要读取项目 .cursor/ 配置,需要 local.settingSources: ["project"] 。请保持每个子代理职责聚焦。

安全检查

在代理接触真实仓库前,先设定好边界。这一步不应跳过。

  • 严格限定权限范围。代理可以读取文件、运行命令并使用您暴露给它们的任何凭据。为代理提供仓库范围的访问,而非宽泛的服务凭据。

  • 不要在提示中包含机密。提示可能出现在会话记录中。使用环境变量存放 CURSOR_API_KEY 及其他令牌,并记住 stdio MCP 的 env 值会传入服务器执行的运行时。

  • 要求人工审查。如果云端代理可以打开 PR,分支保护应在合并前要求人工评审。除非仓库风险很低,否则不要将 autoCreatePR: true 与自动合并结合使用。

  • 关注成本与模型选择。SDK 的使用会消耗 Cursor 的基于令牌的用量池。如前所述,Composer 2 是编码任务的一个模型选项;若需查看您的账户可用的模型 ID,请调用 Cursor.models.list()。

  • 记录运行。 run.conversation() 返回代理轮次的结构化视图。对可能需要调试或审计的运行进行存档。

结语

本文涵盖了 npm install @cursor/sdk、本地快速上手、一个可打开拉取请求的云端代理,以及用于控制仓库代理行为的主要扩展点。

当需要由代码启动并管理代理时,请使用 SDK。若任务仅是编辑器内的对话,通常使用 Cursor 应用即可。

作为对比,我们关于 Claude Agent SDK 和 OpenAI Agents SDK 的指南介绍了其他生态中的代理 API。

Khalid Abdelaty

作者

Khalid Abdelaty

我是一名数据工程师兼社区建设者,专注于数据管道、云端与 AI 工具链,同时为 DataCamp 和新兴开发者撰写实用且高影响力的教程。

常见问题

Cursor SDK 是否支持 Python 或其他语言?

目前没有官方支持。公测阶段的 SDK 仅支持 TypeScript;Python 用户应直接调用 Cloud Agents 的 REST API。

我能在免费 Hobby 方案中使用 SDK 吗?

本地代理可以,在免费层的限速与用量上限内。云端代理不可以;它们需要 Pro 或更高方案。

如何取消耗时过长的运行?

调用 run.cancel()。状态会变为 cancelled,实时流中止,run.wait() 将以已取消的结果解析。

如果 SDK 没有编程式回调,钩子应该如何配合?

钩子是仓库策略,而非每个脚本的逻辑。将共享规则放在 .cursor/hooks.json 中;将围绕 agent.send() 或 run.wait() 的运行特定逻辑保留在您的 TypeScript 代码里。

SDK 是否已准备好用于生产?

先用于低风险任务。SDK 接口仍处于公测阶段。请固定 @cursor/sdk 版本、收紧机密范围、要求评审,并预期在全面可用前 API 仍会变动。

主题