《Cursor文檔》-Cursor TypeScript SDK

@cursor/sdk 包讓你可以從自己的代碼中調用 Cursor 的智能體。現在,原本運行在 Cursor IDE、CLI 和網頁端 app 中的同一智能體,也可以通過 TypeScript 腳本調用。在 Cursor 中運行 /sdk 技能即可快速入門。

Cookbook

Cursor
Cookbook
提供端到端示例:包括 SDK
快速開始
app-builder 原型工具、面向雲端
代理的 看板,以及 編程智能體
CLI
。這些示例可作爲構建 CI 自動修復機器人、缺陷分診 worker、代碼評審流程、嵌入產品的智能體和編排器的良好起點。

概覽

SDK 通過統一接口封裝本地和雲端運行時。無論智能體在何處運行,編寫的代碼都相同。

運行時 功能 適用場景
本地 在 Node 進程中以內聯方式運行智能體循環。文件直接從磁盤讀取。 針對工作樹運行的開發腳本和 CI 檢查。
雲端 (由 Cursor 託管) 在已克隆倉庫的隔離 VM 中運行。VM 由 Cursor 運行。 調用方沒有倉庫、需要並行運行多個智能體,或需要在調用方斷開連接後繼續運行時。

本地指本地智能體循環,而非本地模型

“本地”描述的是智能體循環和文件系統訪問的運行位置,而不是
模型的運行位置。兩種模式下,所有推理均通過 Cursor 託管的模型進行。
本地模式會將文件保留在你的機器上;雲端模式則在
Cursor 環境中運行。無論哪種情況,模型本身均由託管服務提供。

運行時由傳遞給 Agent.create() 的鍵 (localcloud) 決定。兩種運行時都使用相同的 CURSOR_API_KEY

如需瞭解 REST API,請參閱 Cloud Agents API。如需瞭解其他語言,請參閱 SDK Bridge

身份驗證

創建智能體前,請設置 CURSOR_API_KEY (或傳入 apiKey) 。對於尚未預配密鑰的交互式主機,Cursor.auth.login() 會通過瀏覽器登錄簽發並存儲密鑰。

SDK 支持將用戶 API 密鑰和服務賬戶 API 密鑰用於本地和雲端運行。暫不支持團隊 Admin API 密鑰。

export CURSOR_API_KEY="your-key"

用量與計費

SDK 運行與 IDE 和 Cloud Agents 運行適用相同的定價、請求池和隱私模式規則。費用會顯示在團隊的用量儀表盤中,並帶有 SDK 標籤。

服務賬戶 API 密鑰的費用將計入擁有該服務賬戶的團隊。用戶 API 密鑰的費用將計入對應用戶的方案。

如需在代碼中讀取每次運行的 token 數量,請參閱 Token 用量。如需獲取某個智能體運行的已計費用量和美元費用,請參閱 Agent.getUsage()

核心概念

概念 描述
智能體 持久化容器,包含對話狀態、工作區配置和設置,可跨多個提示詞持續存在。
運行 一次提示詞提交,擁有獨立的流、狀態、結果和取消操作。
SDKMessage 運行期間發出的標準化流事件,在所有運行時中具有相同結構。

安裝

npm install @cursor/sdk

包名以 @ 開頭。npm 上不存在不帶 @cursor/sdk

運行時支持

SDK 要求 Node.js 22.13 或更高版本。它提供按平臺劃分的 @cursor/sdk-<os>-<arch> 二進制文件,用於沙盒隔離和 ripgrep,因此這是一個以 Node 爲主的包。

導入 @cursor/sdk 時不會立即加載本地智能體棧。本地執行器會在首次本地 acquire 時加載,因此僅使用雲端功能或類型的用戶無需承擔本地導入開銷。進程中的第一個本地智能體會產生一次性導入開銷,之後模塊會保持緩存。

@cursor/sdk 發佈自包含的 .d.ts 文件,因此無需拉取未發佈的工作區包即可解析類型。升級後,請重新運行類型檢查。TurnEndedUpdate 等流類型會解析爲實際類型,而不是 any

單文件捆綁包和編譯型可執行文件

@cursor/sdk/bundled 是 SDK 的自包含單文件構建,提供與 @cursor/sdk 相同的公共 API。當你的應用以單個文件形式發佈時,請使用它:通過 bun build --compile 生成的獨立二進制可執行文件,或由 esbuild 生成的單文件捆綁包。

默認構建會在運行時按需加載部分模塊。單文件捆綁器無法跟蹤這些加載,因此編譯後的應用在首次調用 Agent.create() 時會失敗,並報出類似 Cannot find module './986.js' 的錯誤。打包入口將所有內容放入一個文件中,因此捆綁器會預先嵌入整個 SDK。

入口 內容
@cursor/sdk/bundled @cursor/sdk 導出的全部內容。
@cursor/sdk/bundled/sqlite SqliteLocalAgentStore,與 @cursor/sdk/sqlite 相同。
import { Agent } from "@cursor/sdk/bundled";

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

像平常一樣使用 Bun 編譯:

bun build --compile main.ts --outfile my-agent

以下幾點需要注意:

  • 打包入口在 Bun 上運行,包括通過 bun build --compile 生成的可執行文件。它們也可在 Node 上加載,但 SQLite 存儲在該環境中不可用,因此默認的本地智能體存儲會回退到 JSONL。不以單文件形式發佈的 Node 應用應繼續導入 @cursor/sdk
  • **zod@bufbuild/protobuf@connectrpc/* 包會從你自行安裝的依賴中解析。**它們隨 @cursor/sdk 提供,打包工具會嵌入一份共享副本,因此傳遞給自定義工具的 Zod schema 能繼續正常工作。
  • **原生二進制文件不能包含在 JavaScript bundle 中。**沙盒隔離和內置 ripgrep 由各平臺對應的 @cursor/sdk-<os>-<arch> 包提供。請將 node_modules/@cursor/sdk-<os>-<arch>/ 放在編譯後的可執行文件旁,SDK 會在那裏找到它。否則,搜索會回退到 PATH 中的 rg,啓用 sandboxOptions 則會拋出 ConfigurationError

打包入口的類型解析方式與 @cursor/sdk 相同。無需更改 TypeScript 配置。

快速開始

最快的入門方式:讓本地智能體針對當前工作樹運行,並即時接收事件流。有關雲端設置,請參閱下方的創建智能體

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

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

const run = await agent.send("Summarize what this repository does");

for await (const event of run.stream()) {
  console.log(event);
}

每個事件都是可區分的 SDKMessage流式傳輸介紹瞭如何提取助手文本、處理工具調用,以及通過 await using 清理資源。有關一次性提示詞 (創建、運行、釋放資源) ,請參閱 Agent.prompt()

快速開始會自動批准工具調用

默認本地智能體會執行工具調用 (shell、編輯、寫入等) ,無需
請求批准;無界面模式下不會提示人工介入。若要控制工具調用,請配置
鉤子 (如 beforeShellExecution
preToolUse) ,或通過 local.sandboxOptions.enabled: true 運行。

創建智能體

function Agent.create(options: AgentOptions): Promise<SDKAgent>;

Agent.create() 會驗證選項,並立即返回句柄。傳入 localcloud 以選擇運行時。

// 本地智能體
const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  local: { cwd: "/path/to/repo" },
});

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

agent.agentId 會立即賦值。本地智能體的 ID 爲 agent-<uuid>;雲端代理的 ID 爲 bc-<uuid>

SDK 啓動的雲端代理不會顯示在默認智能體列表中。要在 Cursor Web 或 Cursor 窗口中
查看它們,請點擊 篩選 > 來源 > SDK

無代碼倉庫的雲端代理

雲端代理可在不含代碼倉庫的空 VM 上運行。傳入 cloud 並將 repos 列表留空,或者完全省略 repos。省略 cloud 則會選擇本地運行時。

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  cloud: { repos: [] },
});

const run = await agent.send(
  "Research the top 3 TypeScript testing frameworks and summarize."
);
console.log((await run.wait()).result);

必須爲您的賬戶或團隊啓用無倉庫智能體。代碼倉庫範圍的 API 密鑰無法創建此類智能體;請改用不受限制的服務賬戶密鑰或用戶 API 密鑰。

會話環境變量

對於雲端代理,當運行需要短期憑證或其他僅供該智能體使用的值時,請傳入 cloud.envVars

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  cloud: {
    repos: [{ url: "https://github.com/your-org/your-repo" }],
    envVars: {
      STAGING_API_TOKEN: process.env.STAGING_API_TOKEN!,
    },
  },
});

這些值會在靜態存儲時加密,注入雲端代理的 shell,並在刪除智能體時一併刪除。envVars 不能與調用方提供的 agentId 同時使用;請省略 agentId,並從 agent.agentId 讀取服務器簽發的 ID。變量名不能以 CURSOR_ 開頭。

對於僅需在單次運行期間存在的值,請改用 agent.send() 傳遞。請參閱單次運行的環境變量

智能體元數據

使用 cloud.metadata 爲雲端代理添加自定義 string 標籤。這些標籤會隨智能體持久保存,並可通過 Agent.get()Agent.list()SDKAgentInfo.metadata 返回。這些標籤不同於 VM 內的
智能體元數據 API;該 API 會在 VM 內提供當前
運行的 ID、所有者、輪次和工作區。

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  cloud: {
    repos: [{ url: "https://github.com/your-org/your-repo" }],
    metadata: {
      end_user_id: "user-123",
      ticket_id: "ENG-456",
    },
  },
});

模型參數

使用 model.params 傳遞模型專屬選項,例如 reasoning effort。參數 ID 和取值因模型而異。使用 Cursor.models.list() 查看您的賬戶支持哪些參數和預設變體。

對於舊版按請求計費方案,如果所選模型需要,Cursor 會自動啓用 Max Mode

Composer 2 會重新路由至 Composer 2.5

Composer 2 已停止服務。仍傳遞 composer-2
composer-2-fast 的 SDK 請求會在認證時重新路由至 Composer 2.5,因此現有
腳本可繼續運行。如果您依賴 composer-2-fast 變體,請確認
快速模式的行爲仍符合您的預期。

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: {
    id: "composer-2.5",
    params: [{ id: "fast", value: "true" }],
  },
  local: { cwd: process.cwd() },
});

Cursor Router

Cursor Router 會爲每個 Auto 請求選擇模型。在 SDK 中,Router 是帶有 optimize_for 參數的 auto-smart 模型。它適用於 Teams 和企業版。企業版管理員必須先爲團隊啓用 Router,auto-smart 纔會出現在目錄中。

Cursor SDK 是智能體 SDK,而非獨立的模型推理或聊天補全 API。Router 會爲能理解工作區、調用工具、運行命令和編輯文件的 Cursor 智能體運行選擇模型。Cursor 目前未提供可用於任意模型調用的原始 Router 端點文檔。

選擇 Cost、Balance 或 Intelligence

傳入 auto-smart,並顯式設置 optimize_for

產品標籤 SDK 值
Cost cost
Balance balanced
Intelligence intelligence

產品文案中使用 Balancebalanced 僅用作 SDK 傳輸值。

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

await using agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: {
    id: "auto-smart",
    params: [{ id: "optimize_for", value: "balanced" }],
  },
  local: { cwd: process.cwd() },
});

const run = await agent.send("Find and fix the failing authentication test");
const result = await run.wait();

console.log(result.status);
console.log(result.requestId);

始終傳遞 optimize_for。請勿省略該字段,也不要傳遞舊版 default 值;通過目錄發現是受支持的合約。

在模型目錄中查找 Router

Cursor.models.list() 會返回當前 API 密鑰的賬戶和團隊可用的模型、參數定義及預設變體。Router 可用時,Cursor Router 會顯示爲 auto-smart。團隊管理員可以禁用 Router,或限制成員可選擇的優化模式。

在硬編碼選擇之前,應以目錄爲準:

import { Cursor, type ModelSelection } from "@cursor/sdk";

const models = await Cursor.models.list();
const router = models.find((model) => model.id === "auto-smart");
const optimizeFor = router?.parameters?.find(
  (parameter) => parameter.id === "optimize_for",
);

if (!router || !optimizeFor) {
  throw new Error(
    "Cursor Router is not available for this API key. Verify that Router is enabled for the key's team.",
  );
}

const requestedMode = "balanced";
const allowedValues = new Set(
  optimizeFor.values.map(({ value }) => value),
);

if (!allowedValues.has(requestedMode)) {
  throw new Error(
    `Router mode "${requestedMode}" is not enabled for this team.`,
  );
}

const model: ModelSelection = {
  id: router.id,
  params: [{ id: optimizeFor.id, value: requestedMode }],
};

按運行切換模式

agent.send() 中覆蓋模型,以更改某次運行的 Router 模式:

const run = await agent.send("Handle this complex migration", {
  model: {
    id: "auto-smart",
    params: [{ id: "optimize_for", value: "intelligence" }],
  },
});

單次運行的模型覆蓋會持續生效。後續發送時若未指定覆蓋,仍會使用新的模型選擇。參閱單次運行模型覆蓋

模型 ID:auto-smartautodefault

選擇 含義
搭配 optimize_for 使用 auto-smart Cursor Router。需要 Cost、Balance 或 Intelligence 時使用。
{ id: "auto" } 當目錄中沒有指定模型時,由服務器選擇的 Auto 回退方案。如需顯式指定 Router 模式,優先使用 auto-smart
省略 optimize_for 或傳入 default 不受支持的 Router 合約。請始終查詢允許的值,並傳入 costbalancedintelligence

計費與路由用量池

  • 所有 Auto 模式均按每個請求所路由模型的標價計費。
  • 底層模型可能因請求而異。需要進行可復現的比較時,請優先使用固定的模型 ID。
  • 企業版模型允許列表決定路由用量池。屏蔽必需模型可能會禁用 Router。

有關當前費率和路由用量池,請參閱 Cursor RouterAuto 模式

Router 缺失的疑難排查

如果找不到 auto-smart,或優化模式被拒絕:

  1. 調用 Cursor.models.list()
  2. 確認結果中包含 auto-smart
  3. 確認 optimize_for 包含所需的值 (costbalancedintelligence) 。
  4. 確認與 API 密鑰關聯的團隊已啓用 Router。
  5. 如果您屬於多個團隊,請確認該密鑰在預期的團隊上下文中使用。
  6. 如果 Router 不可用或無法選擇有效的底層模型,請檢查團隊的模型訪問策略。

SDKAgent

Agent.create()Agent.resume() 返回的句柄。

interface SDKAgent {
  readonly agentId: string;
  readonly model: ModelSelection | undefined;

  send(message: string | SDKUserMessage, options?: SendOptions): Promise<Run>;
  close(): void;
  reload(): Promise<void>;
  [Symbol.asyncDispose](): Promise<void>;

  listArtifacts(): Promise<SDKArtifact[]>;
  downloadArtifact(path: string): Promise<Buffer>;
  getUsage(options?: GetUsageOptions): Promise<AgentUsage>;
}
成員 描述
agentId 穩定的智能體標識符。本地爲 agent-<uuid>,雲端爲 bc-<uuid>
model 當前模型選擇。每次成功調用 send({ model }) 後都會更新。在被設置前爲 undefined (包括調用方未傳入 model 的已恢復智能體) 。
send 使用給定提示詞啓動新的運行。返回 Run 句柄。
close 開始釋放資源,不等待完成。即發即棄。
reload 重新讀取文件系統配置 (鉤子、項目 MCP、子智能體) ,無需釋放資源。
[Symbol.asyncDispose] 異步釋放資源。與 await using 搭配使用以自動清理。
listArtifacts 列出智能體生成的文件 (僅限雲端;本地返回空) 。
downloadArtifact 按路徑下載文件 (僅限雲端;本地會拋出異常) 。
getUsage 獲取智能體的計費 token 用量和美元費用。

Agent.prompt()

function Agent.prompt(message: string, options?: AgentOptions): Promise<RunResult>;

一次性便捷方法:創建智能體、發送一條提示詞、等待運行完成後釋放資源。

const result = await Agent.prompt("What does the auth middleware do?", {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  local: { cwd: process.cwd() },
});

發送消息

每次調用 agent.send() 都會返回一個 Run。智能體會在多次運行之間保留對話上下文;一次運行對應處理一個提示詞的工作單元。

運行

type RunStatus = "running" | "finished" | "error" | "cancelled";
type RunOperation = "stream" | "wait" | "cancel" | "conversation";

interface Run {
  readonly id: string;
  readonly requestId?: string;
  readonly agentId: string;
  readonly status: RunStatus;
  readonly result?: string;
  readonly error?: RunError;
  readonly model?: ModelSelection;
  readonly durationMs?: number;
  readonly usage?: TokenUsage;
  readonly git?: RunGitInfo;
  readonly createdAt?: number;

  stream(): AsyncGenerator<SDKMessage, void>;
  wait(): Promise<RunResult>;
  cancel(): Promise<void>;
  conversation(): Promise<ConversationTurn[]>;

  supports(operation: RunOperation): boolean;
  unsupportedReason(operation: RunOperation): string | undefined;
  onDidChangeStatus(listener: (status: RunStatus) => void): () => void;
}

interface RunGitInfo {
  branches: Array<{ repoUrl: string; branch?: string; prUrl?: string }>;
}

interface RunError {
  message: string;
  code?: string;
}

interface TokenUsage {
  inputTokens: number;
  outputTokens: number;
  cacheReadTokens: number;
  cacheWriteTokens: number;
  totalTokens: number;
  reasoningTokens?: number;
}

interface RunResult {
  id: string;
  requestId?: string;
  status: "finished" | "error" | "cancelled";
  result?: string;
  error?: RunError;
  model?: ModelSelection;
  durationMs?: number;
  usage?: TokenUsage;
  git?: RunGitInfo;
}

流式傳輸

const run = await agent.send("Find the bug in src/auth.ts");

for await (const event of run.stream()) {
  switch (event.type) {
    case "assistant":
      for (const block of event.message.content) {
        if (block.type === "text") process.stdout.write(block.text);
      }
      break;
    case "thinking":
      process.stdout.write(event.text);
      break;
    case "tool_call":
      console.log(`[tool] ${event.name}: ${event.status}`);
      break;
    case "status":
      console.log(`[status] ${event.status}`);
      break;
  }
}

// 在同一智能體中繼續對話。上一次運行的對話狀態
// 會自動加載。
const run2 = await agent.send("Fix it and add a regression test");
await run2.wait();

要隨文本發送圖像:

const run = await agent.send({
  text: "What's in this screenshot?",
  images: [{ data: base64Png, mimeType: "image/png" }],
});

不使用流式傳輸時等待

const result = await run.wait();

console.log(result.status);      // "finished" | "error" | "cancelled"
console.log(result.result);      // 最終助手文本(如有)
console.log(result.error);       // 運行失敗時爲 { message, code? }
console.log(result.model);       // 本次運行使用的已解析 ModelSelection
console.log(result.durationMs);
console.log(result.usage);       // 累計 TokenUsage;不可用時爲 undefined
console.log(result.git);         // 在 Cloud 上爲 { branches: [{ repoUrl, branch?, prUrl? }] }

最終的助手文本以 string 形式存儲在 result.result 中。無需在 textmessagemessagescontent 字段中查找。如果需要按步驟獲取會話記錄,請調用 run.conversation(),以獲得結構化的 ConversationTurn[] 視圖:

const result = await run.wait();
const finalText = result.result ?? "";

const turns = await run.conversation();
const lastAssistant = turns
  .flatMap((t) => (t.type === "agentConversationTurn" ? t.turn.steps : []))
  .filter((s) => s.type === "assistantMessage")
  .at(-1);

console.log(lastAssistant?.message.text);

取消一次運行

await run.cancel();

取消運行。狀態將變爲 "cancelled",即時流將中止,正在進行的工具調用將停止,run.wait() 將以 status: "cancelled" 完成。部分輸出 (截至目前生成的助手文本) 會保留在 Run 對象中。

運行中的本地和雲端運行均支持取消;如果運行已結束,則此操作無效。

讀取運行狀態

console.log(run.status);  // "running" | "finished" | "error" | "cancelled"

const stop = run.onDidChangeStatus((status) => {
  console.log(`status changed to ${status}`);
});
// 調用 `stop()` 移除監聽器。

// 此次運行中累積對話的按輪次結構化視圖
const turns = await run.conversation();

run.conversation() 返回該運行的 ConversationTurn[] (包含步驟的智能體輪次,或包含命令和輸出的 shell 輪次) 。無需訂閱即時流,即可用它渲染或持久化該運行的結構化歷史記錄。

使用量

運行時提供使用量時,運行會報告該用量。運行期間可從 run.usage 讀取累計總量,調用 run.wait() 後可從 result.usage 讀取。兩者都包含所有報告用量的輪次彙總而成的 TokenUsage;如果沒有任何輪次報告用量,則兩者均爲 undefined (例如,已取消且從未完成任何輪次的運行,或不提供用量信息的運行時) 。

interface TokenUsage {
  inputTokens: number;
  outputTokens: number;
  cacheReadTokens: number;
  cacheWriteTokens: number;
  totalTokens: number;
  reasoningTokens?: number;
}
字段 描述
inputTokens 發送給模型的提示詞 token。
outputTokens 模型生成的 token。
cacheReadTokens 從提示詞緩存讀取的 token。
cacheWriteTokens 寫入提示詞緩存的 token。
totalTokens inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens。不包括 reasoningTokens
reasoningTokens 推理 token,是 outputTokens 的一部分。模型或運行時未報告時省略。
const result = await run.wait();

if (result.usage) {
  console.log(`total: ${result.usage.totalTokens}`);
  console.log(`in: ${result.usage.inputTokens}, out: ${result.usage.outputTokens}`);
  console.log(
    `cache read/write: ${result.usage.cacheReadTokens}/${result.usage.cacheWriteTokens}`
  );
} else {
  console.log("no usage reported for this run");
}

reasoningTokens 已計入 outputTokens,因此 totalTokens 不再重複計入,以避免重複計算。

如需獲取流式傳輸過程中每輪的用量數據,請處理 usage 流事件 (SDKUsageMessage)。它會在每個上報用量的輪次結束時觸發一次,並攜帶該輪的 TokenUsagerun.usageresult.usage 在整個運行過程中始終爲累計值。

for await (const event of run.stream()) {
  if (event.type === "usage") {
    console.log(`turn used ${event.usage.totalTokens} tokens`);
  }
}

令牌計數由運行時報告,不代表費用。要獲取智能體運行的已計費用量和美元費用,請調用 agent.getUsage()

使用 requestId 關聯 Run

每次調用 agent.send() 時,平臺都會生成一個 UUID,並通過 requestId 字段在 RunRunResult 中提供。使用它將腳本或 CI Run 與後端日誌、使用分析和支持線程關聯,而不要僅憑 agentId 猜測。

const run = await agent.send("Audit the auth middleware");
console.log(run.requestId); // 例如:"6e0d261c-86a2-4383-89f0-9162c1c10662"

const result = await run.wait();
logger.info({ requestId: result.requestId }, "run finished");

requestId 會隨運行一併持久化,因此可在內存、SQLite 和 JSONL 本地存儲之間往返傳遞;後端返回該值時,也會將其設置到雲端運行中。請將其與錯誤中的 error.requestId 一併記錄,以便同一標識符貫穿成功和失敗路徑。

單次運行模型覆蓋

傳遞給 agent.send()model 會覆蓋智能體在該次運行中的模型選擇,之後會持續生效:後續發送時若未指定覆蓋,將繼續使用新模型。若要切換回原來的模型,請傳遞另一個 model 覆蓋,或通過 agent.model 讀取當前選擇。

const run = await agent.send("Plan the refactor", {
  model: { id: "composer-2.5", params: [{ id: "fast", value: "true" }] },
});

console.log(agent.model);  // 發送成功後更新爲該覆蓋設置

run.modelresult.model 反映該次運行實際使用的模型選擇,且運行開始後不可更改。

單次運行的環境變量

雲端代理還可接收僅用於單次運行的環境變量。在 agent.send() 中傳入 cloud.envVars,這些值會注入智能體在該次運行中使用的 shell。運行結束後,它們會從 VM 中移除,下一次運行無法訪問。對於在輪次之間輪換的憑據,這種方式很合適,例如在讓智能體使用前剛剛簽發的短期部署令牌。

const run = await agent.send("Deploy the preview environment", {
  cloud: {
    envVars: {
      DEPLOY_TOKEN: await mintShortLivedToken(),
    },
  },
});

如果單次運行的變量與 Agent.create()cloud.envVars 中某個智能體範圍變量同名,該次運行會優先使用單次運行的值;下一次運行時則會恢復使用智能體範圍的值。

單次運行變量同樣適用於首次發送。SDK 會在創建智能體時一併傳遞這些變量,並將其作用範圍限定爲初始運行,因此不會持久保存在智能體中。與智能體範圍變量一樣,它們在靜態存儲時會加密,且名稱不能以 CURSOR_ 開頭。

單次運行的環境變量僅適用於雲端代理,且不適用於針對公開倉庫運行的智能體。對於本地智能體,智能體進程會繼承你自己的環境,因此請在調用 send() 前爲進程設置變量。

對話模式

傳入 mode: "plan"mode: "agent",控制運行是先探索並制定方案,還是直接實施更改。有關 Plan 模式在產品中的作用,請參閱 Plan 模式

Agent.create() 中設置 mode,以確定首次運行的模式。在後續的 agent.send() 調用中,省略 mode 可保留對話當前的模式;傳入 mode 則僅切換該次運行的模式。

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  mode: "plan",
  cloud: {
    repos: [{ url: "https://github.com/your-org/your-repo" }],
  },
});

await (await agent.send("Design the auth refactor")).wait();
await (await agent.send("Looks good, start building", { mode: "agent" })).wait();

流式獲取原始增量

run.stream() 會產生規範化的 SDKMessage 事件。若需獲取更底層的更新 (逐 token 文本、流式傳入的工具調用 args、思考增量、嵌套任務更新和步驟邊界) ,請向 send() 傳入 onDeltaonStep 回調:

const run = await agent.send("Refactor the utils module", {
  onDelta: ({ update }) => {
    if (update.type === "text-delta") process.stdout.write(update.text);
    if (update.type === "thinking-delta") process.stdout.write(update.text);
  },
  onStep: ({ step }) => {
    console.log(`[step] ${step.type}`);
  },
});

在處理下一次更新前,會先等待回調完成,因此你可以施加背壓。InteractionUpdate涵蓋text-deltathinking-deltathinking-completedtool-call-startedtool-call-completedtool-call-deltapartial-tool-calltoken-deltastep-startedstep-completedturn-ended,以及少量摘要和 shell 輸出增量。

單次發送選項

屬性 類型 描述
model ModelSelection 單次發送的模型覆蓋設置。若省略,則使用 agent.model。粘性:發送成功後會更新 agent.model
mode "agent" \| "plan" 單次發送的對話模式覆蓋設置。若在後續消息中省略,則保留對話當前的模式。
mcpServers Record<string, McpServerConfig> 內聯 MCP 服務器定義。會完全替換此次運行創建時配置的服務器。
onStep (args: { step }) => void \| Promise<void> 每個對話步驟完成後 (文本、思考或工具批次) 調用的回調。
onDelta (args: { update }) => void \| Promise<void> 每個原始 InteractionUpdate 的回調。
idempotencyKey string 可選的客戶端生成冪等鍵,用於此次發送。
cloud.envVars Record<string, string> 僅限雲端代理。爲此次運行注入單次運行的環境變量,運行結束後會移除。僅在此次運行中按名稱覆蓋智能體範圍內的 cloud.envVars
local.force boolean 僅限智能體。默認值爲 false。開始發送此消息前,使卡住的活躍運行過期。雲端會在服務器端返回 409 agent_busy,因此無需對應選項。
local.customTools Record<string, SDKCustomTool> 僅限智能體。此次運行的自定義工具。會替換該智能體創建時配置的 local.customTools,僅對此次運行生效。

接下來的三個部分詳細介紹 SDKMessageInteractionUpdateConversationTurn。首次閱讀時可快速瀏覽或跳過;恢復智能體將繼續正文。

流事件

run.stream() 產生的事件。可通過 type 區分。所有事件均包含 agent_idrun_id

type SDKMessage =
  | SDKSystemMessage
  | SDKUserMessageEvent
  | SDKAssistantMessage
  | SDKThinkingMessage
  | SDKToolUseMessage
  | SDKStatusMessage
  | SDKTaskMessage
  | {
      type: "request";
      agent_id: string;
      run_id: string;
      request_id: string;
    }
  | SDKUsageMessage;
type 描述 關鍵字段
"system" 初始化元數據。在運行開始時發出一次。 subtype? ("init"), model?, tools?
"user" 此次運行的用戶提示詞回顯。 message.content: TextBlock[]
"assistant" 模型文本輸出。 message.content: (TextBlock \| ToolUseBlock)[]
"thinking" 思考內容。 text, thinking_duration_ms?
"tool_call" 工具調用生命週期。開始時攜帶 args 發出,完成時再次攜帶 result 發出。 call_id, name, status, args?, result?, truncated?
"status" 雲端運行生命週期狀態變化。 status, message?
"task" 任務級里程碑和摘要。 status?, text?
"request" 等待用戶輸入或批准。 request_id
"usage" 每輪 token 使用量;運行時報告後,會在該輪結束時發出一次。 usage (TokenUsage)

流完成後,結果數據 (最終文本、模型、時長、累計 token 使用量、Git 元數據) 會保存在 Run 對象中。使用 run.wait() 讀取。

工具調用 schema 不穩定。 tool_call 事件中的 argsresult 負載反映各工具的內部結構,可能會隨工具演進而變化。工具名稱也可能被重命名或替換。請將 argsresult 視爲 unknown,並進行防禦性解析。事件信封 (typecall_idnamestatus) 是穩定的。

消息類型

interface SDKSystemMessage {
  type: "system";
  subtype?: "init";
  agent_id: string;
  run_id: string;
  model?: ModelSelection;
  tools?: string[];
}

interface SDKUserMessageEvent {
  type: "user";
  agent_id: string;
  run_id: string;
  message: { role: "user"; content: TextBlock[] };
}

interface SDKAssistantMessage {
  type: "assistant";
  agent_id: string;
  run_id: string;
  message: {
    role: "assistant";
    content: Array<TextBlock | ToolUseBlock>;
  };
}

interface SDKThinkingMessage {
  type: "thinking";
  agent_id: string;
  run_id: string;
  text: string;
  thinking_duration_ms?: number;
}

interface SDKToolUseMessage {
  type: "tool_call";
  agent_id: string;
  run_id: string;
  call_id: string;
  name: string;
  status: "running" | "completed" | "error";
  args?: unknown;
  result?: unknown;
  truncated?: { args?: boolean; result?: boolean };
}

interface SDKStatusMessage {
  type: "status";
  agent_id: string;
  run_id: string;
  status: "CREATING" | "RUNNING" | "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED";
  message?: string;
}

interface SDKTaskMessage {
  type: "task";
  agent_id: string;
  run_id: string;
  status?: string;
  text?: string;
}

interface SDKUsageMessage {
  type: "usage";
  agent_id: string;
  run_id: string;
  usage: TokenUsage;
}

interface TextBlock {
  type: "text";
  text: string;
}

interface ToolUseBlock {
  type: "tool_use";
  id: string;
  name: string;
  input: unknown;
}

大多數工具調用會發出兩次 SDKToolUseMessage:首次 status: "running",並填充 args;完成時再次發出,status: "completed" (或 "error") ,並填充 resulttruncated 標誌表示 SDK 是否因負載過大而截斷了 argsresult

SDKStatusMessage 涵蓋雲端的生命週期狀態轉換。CREATING 表示 VM 配置和倉庫克隆;RUNNING 表示智能體正在工作;其餘均爲終態。

每個報告使用量的輪次結束時,都會發出一次 SDKUsageMessage,其中包含該輪的 TokenUsage。跨輪次的累計總用量保存在 run.usageresult.usage 中。參閱 使用量

交互更新

InteractionUpdate 是傳遞給 agent.send()onDelta 回調的原始增量類型。與 SDKMessage 事件相比,更新粒度更細:文本按 token 流式傳輸,工具調用會隨着 args 的累積報告部分狀態,思考內容會即時傳入。

type InteractionUpdate =
  | TextDeltaUpdate
  | ThinkingDeltaUpdate
  | ThinkingCompletedUpdate
  | ToolCallStartedUpdate
  | ToolCallCompletedUpdate
  | ToolCallDeltaUpdate
  | PartialToolCallUpdate
  | TokenDeltaUpdate
  | StepStartedUpdate
  | StepCompletedUpdate
  | TurnEndedUpdate
  | UserMessageAppendedUpdate
  | SummaryUpdate
  | SummaryStartedUpdate
  | SummaryCompletedUpdate
  | ShellOutputDeltaUpdate;

更新類型

interface TextDeltaUpdate {
  type: "text-delta";
  text: string;
}

interface ThinkingDeltaUpdate {
  type: "thinking-delta";
  text: string;
}

interface ThinkingCompletedUpdate {
  type: "thinking-completed";
  thinkingDurationMs: number;
}

interface ToolCallStartedUpdate {
  type: "tool-call-started";
  callId: string;
  toolCall: ToolCall;
  modelCallId: string;
}

interface PartialToolCallUpdate {
  type: "partial-tool-call";
  callId: string;
  toolCall: ToolCall;
  modelCallId: string;
}

interface ToolCallCompletedUpdate {
  type: "tool-call-completed";
  callId: string;
  toolCall: ToolCall;
  modelCallId: string;
}

interface ToolCallDeltaUpdate {
  type: "tool-call-delta";
  callId: string;
  modelCallId: string;
  taskUpdate: NestedTaskUpdate;
}

type NestedTaskUpdate =
  | TextDeltaUpdate
  | ToolCallStartedUpdate
  | ToolCallCompletedUpdate
  | ThinkingDeltaUpdate
  | ThinkingCompletedUpdate
  | PartialToolCallUpdate
  | StepStartedUpdate
  | StepCompletedUpdate;

interface TokenDeltaUpdate {
  type: "token-delta";
  tokens: number;
}

interface StepStartedUpdate {
  type: "step-started";
  stepId: number;
}

interface StepCompletedUpdate {
  type: "step-completed";
  stepId: number;
  stepDurationMs: number;
}

interface TurnEndedUpdate {
  type: "turn-ended";
  usage?: {
    inputTokens: number;
    outputTokens: number;
    cacheReadTokens: number;
    cacheWriteTokens: number;
    reasoningTokens?: number;
  };
}

interface UserMessageAppendedUpdate {
  type: "user-message-appended";
  userMessage: UserMessage;
}

interface SummaryUpdate {
  type: "summary";
  summary: string;
}

interface SummaryStartedUpdate {
  type: "summary-started";
}

interface SummaryCompletedUpdate {
  type: "summary-completed";
}

interface ShellOutputDeltaUpdate {
  type: "shell-output-delta";
  event: Record<string, unknown>;
}

ToolCallDeltaUpdate 包含任務或子智能體工具調用中一層嵌套的交互更新。模型在提交工具調用前流式傳入參數時,會發出 PartialToolCallUpdate。適用於 SDKToolUseMessage.args 的穩定性免責聲明同樣適用於此處。

對話類型

運行中每輪對話的結構化視圖,由 run.conversation() 返回,並作爲 onStep 回調的參數傳入。

type ConversationTurn =
  | { type: "agentConversationTurn"; turn: AgentConversationTurn }
  | { type: "shellConversationTurn"; turn: ShellConversationTurn };

interface AgentConversationTurn {
  userMessage?: UserMessage;
  steps: ConversationStep[];
}

interface ShellConversationTurn {
  shellCommand?: ShellCommand;
  shellOutput?: ShellOutput;
}

type ConversationStep =
  | { type: "assistantMessage"; message: AssistantMessage }
  | { type: "toolCall"; message: ToolCall }
  | { type: "thinkingMessage"; message: ThinkingMessage };

interface AssistantMessage {
  text: string;
}

interface ThinkingMessage {
  text: string;
  thinkingDurationMs?: number;
}

interface UserMessage {
  text: string;
}

interface ShellCommand {
  command: string;
  workingDirectory?: string;
}

interface ShellOutput {
  stdout: string;
  stderr: string;
  exitCode: number;
}

ToolCall 是一個涵蓋所有內置工具 (shell、edit、read、write、glob、grep、ls、semSearch、mcp、task 等) 的可辨別聯合類型。其結構僅供內部使用;請參閱“Stream events”下的穩定性說明

恢復智能體會話

function Agent.resume(agentId: string, options?: Partial<AgentOptions>): Promise<SDKAgent>;

使用 Agent.resume() 通過 ID 重新連接到現有智能體。常見場景包括:重新連接之前啓動的長時間運行雲端代理,或在本地進程重新啓動後繼續對話。系統會根據 ID 前綴自動檢測運行環境 (bc- 表示雲端,其他表示本地) 。

await using agent = await Agent.resume("bc-abc123", {
  apiKey: process.env.CURSOR_API_KEY!,
});

const run = await agent.send("Also update the changelog");
await run.wait();

恢復時,除非再次傳入 model,否則 agent.modelundefined。內聯 mcpServers 不會在恢復後持久保留——它們通常包含機密信息,且僅存於內存中。恢復時請再次傳入,或者對於需要持續保留的服務器,使用基於文件的 MCP 配置 (.cursor/mcp.json + local.settingSources) 。

查看智能體和運行記錄

列出、獲取和重新加載歷史智能體。列表端點返回 { items, nextCursor? },支持基於遊標的分頁。

Agent.list()

function Agent.list(options?: ListAgentsOptions): Promise<ListResult<SDKAgentInfo>>;

type ListAgentsOptions = {
  limit?: number;
  cursor?: string;
} & (
  | { runtime?: undefined }
  | { runtime: "local"; cwd?: string; store?: LocalAgentStore }
  | {
      runtime: "cloud";
      prUrl?: string;
      includeArchived?: boolean;
      apiKey?: string;
    }
);
const { items, nextCursor } = await Agent.list({
  runtime: "local",
  cwd: process.cwd(),
});

Agent.get()

function Agent.get(agentId: string, options?: GetAgentOptions): Promise<SDKAgentInfo>;

interface GetAgentOptions {
  cwd?: string;       // 本地路由
  apiKey?: string;    // 雲端路由
  store?: LocalAgentStore;
}

運行時會根據智能體 ID 前綴自動判斷 (bc- → 雲端,否則爲本地) 。

Agent.listRuns()

function Agent.listRuns(agentId: string, options?: ListRunsOptions): Promise<ListResult<Run>>;

type ListRunsOptions = {
  limit?: number;
  cursor?: string;
} & (
  | { runtime?: "local"; cwd?: string; store?: LocalAgentStore }
  | { runtime: "cloud"; apiKey?: string }
);

Agent.getRun()

function Agent.getRun(runId: string, options?: GetRunOptions): Promise<Run>;

type GetRunOptions =
  | { runtime?: "local"; cwd?: string; store?: LocalAgentStore }
  | { runtime: "cloud"; agentId: string; apiKey?: string };

Cloud getRun 需要父級智能體的 agentId

Agent.cancelRun()

function Agent.cancelRun(runId: string, options?: GetRunOptions): Promise<void>;

當你有運行 ID 但沒有 Run 句柄時,取消該運行。

Agent.messages.list()

Agent.messages.list(
  agentId: string,
  options?: GetAgentMessagesOptions
): Promise<AgentMessage[]>;

interface GetAgentMessagesOptions {
  limit?: number;
  offset?: number;
  runtime?: "local";
  cwd?: string;
  store?: LocalAgentStore;
}

interface AgentMessage {
  type: "user" | "assistant";
  uuid: string;
  agent_id: string;
  message: unknown;
}

返回本地智能體中存儲的用戶和助手消息。

Agent.getUsage()

獲取智能體運行的計費使用量和美元費用。可通過 handle 調用;如果沒有 handle,也可通過 ID 靜態調用。雲端代理返回按運行細分的數據;智能體返回按輪次細分的數據。傳入 runId 可將結果限定爲單個條目:雲端代理使用 run-<uuid> 格式的運行 ID;智能體使用之前 getUsage().runs[].runId 中的 ID。

agent.getUsage(options?: GetUsageOptions): Promise<AgentUsage>;
function Agent.getUsage(
  agentId: string,
  options?: GetUsageOptions & { apiKey?: string }
): Promise<AgentUsage>;

interface GetUsageOptions {
  runId?: string;
}

interface AgentUsage {
  usage: TokenUsage;   // 在各個 `runs` 中彙總
  cost?: UsageCost;    // 在各個 `runs` 中彙總
  runs: RunUsage[];
}

interface RunUsage {
  runId: string;
  usage: TokenUsage;
  cost?: UsageCost;
}

interface UsageCost {
  rawCostCents: number;   // 未享受折扣的模型 token 成本;按請求計費的用量爲 0
  chargedCents: number;   // 實際收取的金額,已包含折扣和 Cursor Token 費用
}
const { usage, cost, runs } = await agent.getUsage();

console.log(`tokens: ${usage.totalTokens}`);
if (cost) {
  console.log(`charged: $${(cost.chargedCents / 100).toFixed(2)}`);
}
for (const run of runs) {
  console.log(run.runId, run.usage.totalTokens, run.cost?.chargedCents);
}

費用已包含折扣。一次運行結束後,費用可能需要片刻才能結算;在此之前不會顯示 cost。對於方案內用量、BYOK (自帶密鑰) 用量和信用額度授予的用量,chargedCents 均爲 0

這與 使用量 是不同的視圖:run.usage 顯示單次運行的即時 token 數量,而 getUsage() 則是智能體運行的計費記錄。

雲端代理生命週期

雲端代理會一直保留在你的團隊工作區中,直到你將其歸檔或刪除。Agent.list({ runtime: "cloud" }) 默認不顯示已歸檔的智能體;傳入 includeArchived: true 可查看它們。按 prUrl 篩選,可找到創建特定 PR 的智能體。

function Agent.archive(agentId: string, options?: AgentOperationOptions): Promise<void>;
function Agent.unarchive(agentId: string, options?: AgentOperationOptions): Promise<void>;
function Agent.delete(agentId: string, options?: AgentOperationOptions): Promise<void>;

interface AgentOperationOptions {
  cwd?: string;
  apiKey?: string;
  store?: LocalAgentStore;
}
await Agent.archive(agentId);     // 軟刪除;仍可讀取會話記錄
await Agent.unarchive(agentId);   // 恢復已歸檔的智能體
await Agent.delete(agentId);      // 永久刪除;後續讀取將返回 404

SDKAgentInfo

Agent.list()Agent.get() 返回的元數據類型。

type SDKAgentInfo = {
  agentId: string;
  name: string;
  summary: string;
  lastModified: number;
  status?: "running" | "finished" | "error";
  createdAt?: number;
  archived?: boolean;
} & (
  | { runtime?: undefined }
  | { runtime: "local"; cwd?: string }
  | {
      runtime: "cloud";
      env?: { type: "cloud" | "pool" | "machine"; name?: string };
      repos?: string[];
      metadata?: Record<string, string>;
    }
);

Cursor 命名空間

提供賬戶級讀取、目錄讀取和進程級 SDK 配置。讀取方法可接受 { apiKey };如未提供,則依次使用 CURSOR_API_KEY 和已保存的瀏覽器登錄

Cursor.auth

爲未預先配備 API 密鑰的主機提供交互式登錄。Cursor.auth.login() 會在瀏覽器中打開 Cursor 網站的登錄頁面,等待登錄完成後簽發用戶 API 密鑰 (默認有效期爲 90 天) ,並將其存儲在 ~/.cursor/sdk/auth.json 中。登錄後,Agent.create()Cursor.me() 和其他讀取操作無需 apiKeyCURSOR_API_KEY 即可使用。

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

await Cursor.auth.login();

const status = await Cursor.auth.status();
// { status: "已登錄", backendUrl, email?, apiKeyExpiresAtMs? }
// | { status: "已登出" }

await Cursor.auth.logout();
選項 描述
backendUrl API 基礎 URL。默認值依次爲 CURSOR_BACKEND_URL 和生產環境。
websiteUrl 瀏覽器登錄基礎 URL。默認值依次爲 CURSOR_WEBSITE_URL 和生產環境。
openBrowser true (默認值) 會在適當情況下打開系統瀏覽器;false 則絕不打開;也可傳入函數作爲自定義打開方式。在 SSH 會話中或設置了 NO_OPEN_BROWSER 時將跳過此操作。
onLoginUrl 等待前會使用登錄 URL 調用此函數,以便主機顯示該 URL。若省略此項且未打開瀏覽器,URL 會寫入 stderr。
signal 用於取消等待的 AbortSignal;隨後 login 會拋出 AuthenticationError
store 持久化保存憑據的位置。默認值爲 ~/.cursor/sdk/auth.json;傳入 null 則僅在結果中返回密鑰。
apiKeyName 儀表盤 API 密鑰列表中所簽發密鑰的顯示名稱。
apiKeyTtlMs 所簽發密鑰的有效期,單位爲毫秒。默認值爲 90 天。

Cursor.auth.login() 返回
{ apiKey, email?, apiKeyExpiresAtMs }。使用 FileCredentialStore
InMemoryCredentialStorelogin()status()
logout() 提供自定義 store

SDK 中所有位置的憑據解析順序:顯式指定的 apiKeyCURSOR_API_KEY、已存儲的登錄信息。本地存儲的登錄信息不會從已安裝的 Cursor app 中讀取憑據;其中僅保存由 Cursor.auth.login() 簽發的密鑰。

Cursor.configure()

function Cursor.configure(options: CursorConfigureOptions): void;

interface CursorConfigureOptions {
  local?: {
    store?: LocalAgentStore | null;
    useHttp1ForAgent?: boolean | null;
    workspaceScanCacheTtlMs?: number | null;
  };
}

爲後續 Agent.* 調用設置本地智能體的默認值。單次調用中指定的字段會覆蓋這些值;傳入 null 可清除先前設置的默認值。

選項 描述
local.store 調用未指定 local.store 時使用的默認本地智能體存儲。SQLite 後端可用時,SDK 使用基於磁盤的 SQLite;否則會回退到 JsonlLocalAgentStore
local.useHttp1ForAgent 強制本地智能體後端流使用帶 SSE 的 HTTP/1.1,而非 HTTP/2。在代理之後運行,或使用不支持 HTTP/2 的 fetch 棧時很有用。由於上游 HTTP/2 兼容性問題,Bun 默認使用 HTTP/1.1。
local.workspaceScanCacheTtlMs SDK 重用工作區掃描結果 (規則、技能、AGENTS.md、忽略文件) 的時長,單位爲毫秒。默認值爲 20 秒。對於僅在部署時變更的 checkout,可在長期運行的主機中提高此值;代價是時效性降低,因爲進程啓動後添加的規則可能在這段時間內不會被發現。CURSOR_RIPWALK_CACHE_TTL_MS 環境變量可設置相同的值。
import { Cursor, JsonlLocalAgentStore } from "@cursor/sdk";

Cursor.configure({
  local: {
    store: new JsonlLocalAgentStore("/var/lib/cursor-agents"),
    useHttp1ForAgent: true,
  },
});

Cursor.me()

function Cursor.me(options?: CursorRequestOptions): Promise<SDKUser>;

interface CursorRequestOptions {
  apiKey?: string;
}

interface SDKUser {
  apiKeyName: string;
  userId?: number;
  userEmail?: string;
  userFirstName?: string;
  userLastName?: string;
  createdAt: string;
}

Cursor.models.list()

function Cursor.models.list(options?: CursorRequestOptions): Promise<SDKModel[]>;

type SDKModel = ModelListItem;

interface ModelListItem {
  id: string;
  displayName: string;
  description?: string;
  aliases?: string[];
  parameters?: ModelParameterDefinition[];
  variants?: ModelVariant[];
}

interface ModelParameterDefinition {
  id: string;
  displayName?: string;
  values: Array<{ value: string; displayName?: string }>;
}

interface ModelVariant {
  params: ModelParameterValue[];
  displayName: string;
  description?: string;
  isDefault?: boolean;
}

在調用 Agent.create()agent.send() 前,使用 Cursor.models.list() 查詢有效的 model ID 及各模型支持的 params。參數因模型而異。常見參數包括推理 effort,以及 auto-smart 的 Cursor Router optimize_for

可用目錄因賬戶和團隊而異。只有 API 密鑰所屬團隊可使用 Router 時,Cursor Router 纔會以 auto-smart 形式顯示。請參閱 Cursor Router

const models = await Cursor.models.list();
const composer = models.find((model) => model.id === "composer-2.5");

console.log(composer?.parameters);
// [
//   {
//     id: "fast",
//     displayName: "快速",
//     values: [
//       { value: "false" },
//       { value: "true", displayName: "快速" },
//     ],
//   },
// ]

通過 model.params 傳入所選參數值。預設 variants 已包含有效的 params,因此可以將其複製到模型選擇中。

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: {
    id: "composer-2.5",
    params: [{ id: "fast", value: "true" }],
  },
  local: { cwd: process.cwd() },
});

最佳實踐

  • 動態獲取,不要硬編碼。 在啓動時 (或每個進程啓動一次) 調用 Cursor.models.list(),並緩存結果。隨着新模型上線,模型 ID 和參數結構可能發生變化。
  • 模型需要參數時,務必顯式傳入。 parameters 數組非空的模型屬於參數化模型。請傳入所需參數;否則,運行時會使用每個參數允許的第一個值,這可能不符合你的預期。對於 Cursor Router,始終顯式傳入 optimize_for
  • 按能力而非 ID 解析。 如果你需要的是“當前快速模式下的默認模型”,而不是某個特定模型,請按如下方式查找:
  const models = await Cursor.models.list();
  const composer = models.find((m) => m.id === "composer-2.5");
  const fast = composer?.parameters?.find((p) => p.id === "fast");
  const fastValue = fast?.values.find((v) => v.value === "true")?.value;

  const model = composer
    ? {
        id: composer.id,
        params: fastValue ? [{ id: "fast", value: fastValue }] : undefined,
      }
    : {
        id: "auto-smart",
        params: [{ id: "optimize_for", value: "balanced" }],
      };

當目標模型不可用時,優先顯式選擇 Router (auto-smart + optimize_for) 。只有在希望由服務器選擇 Auto,且不指定 Cost、Balance 或 Intelligence 時,纔回退到 { id: "auto" }

Cursor.repositories.list()

function Cursor.repositories.list(options?: CursorRequestOptions): Promise<SDKRepository[]>;

interface SDKRepository {
  url: string;
}

返回調用用戶所屬團隊已連接的 GitHub 倉庫。僅限 Cloud。

配置來源概覽

MCP 服務器、子智能體和鉤子都會從內聯選項和磁盤上的配置中解析。三者的優先級結構相同:每次發送時的內聯配置 > 創建時的內聯配置 > 項目文件 > 用戶文件 > 團隊 / 儀表盤配置。

功能 內聯選項 本地文件 (項目) 本地文件 (用戶) 雲端 / 儀表盤 優先級
MCP 服務器 Agent.create()agent.send() 中的 mcpServers .cursor/mcp.json (僅當 local.settingSources 包含 \"project\" 時加載) ~/.cursor/mcp.json (僅當包含 \"user\" 時加載) cursor.com/agents 配置的服務器 (僅限雲端) 發送 > 創建 > 插件 > 項目 > 用戶 (本地) ;發送 > 創建 > 儀表盤 (雲端)
子智能體 Agent.create() 中的 agents .cursor/agents/*.md (frontmatter:namedescriptionmodel?) 不適用 智能體針對克隆的倉庫運行時,雲端會加載相同的項目文件 內聯配置會覆蓋同名的文件配置
鉤子 無 — 僅支持文件配置 .cursor/hooks.json (+ 腳本) ~/.cursor/hooks.json 雲端運行項目鉤子。企業版方案還會運行團隊和企業管理的鉤子。 基於文件;項目配置會與用戶 / 團隊 / 企業配置分層,詳見 Hooks
配置來源 local.settingSources 用於選擇要加載的磁盤配置層 .cursor/ ~/.cursor/ 不適用 雲端始終加載 project / team / plugins,並忽略 local.settingSources

內聯值適合絕不應寫入磁盤的機密信息 (如單次運行的 API 密鑰、租戶範圍的 token) 。文件配置適合用於策略:鉤子尤其如此,它們屬於項目邊界,而非單次運行的控制項。

MCP 服務器

智能體可從多種來源獲取 MCP 服務器。最常見的方式是在 Agent.create()agent.send() 中內聯定義。也支持基於文件的配置和通過儀表盤管理的配置。

加載的內容

本地智能體最多可從五個來源加載服務器;如果名稱衝突,以最先匹配的來源爲準:

  1. agent.send() 中的 mcpServers。會完全替換該次運行創建時的服務器 (不合並) 。
  2. Agent.create() 中的 mcpServers。未提供單次發送覆蓋配置時使用。
  3. 插件服務器,前提是 local.settingSources 包含 "plugins"
  4. 來自 .cursor/mcp.json 的項目服務器,前提是 local.settingSources 包含 "project"
  5. 來自 ~/.cursor/mcp.json 的用戶服務器,前提是 local.settingSources 包含 "user"

未設置 local.settingSources 時,只會加載內聯服務器。如果本地 MCP 服務器需要通過 OAuth 登錄,SDK 無法提示你登錄。只有當你已在 Cursor app 中登錄過該服務器時才能使用;此時 SDK 會複用已保存的登錄憑據。

雲端代理從以下來源加載服務器:

  1. agent.send() 中的 mcpServers。會完全替換該次運行創建時的服務器 (不合並) 。
  2. Agent.create() 中的 mcpServers。未提供單次發送覆蓋配置時使用。
  3. 來自 cursor.com/agents 的用戶和團隊 MCP 服務器。

如果內聯服務器不包含 authheaders,且你之前已在 cursor.com/agents 授權該服務器 URL,使用個人 API token 認證的運行會自動複用這些 OAuth token。服務賬戶 API 密鑰無法回退使用用戶認證,因爲它們不與用戶關聯。

local.settingSources 不適用於雲端代理。

本地

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "auto" },
  local: { cwd: process.cwd() },
  mcpServers: {
    docs: {
      type: "http",
      url: "https://example.com/mcp",
      auth: {
        CLIENT_ID: "client-id",
        scopes: ["read", "write"],
      },
    },
    filesystem: {
      type: "stdio",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-filesystem", process.cwd()],
      cwd: process.cwd(),
    },
  },
});

雲端

雲端代理也可以直接接收已認證的 MCP 配置。當 Cursor 需要通過後端代理遠程 MCP 時,請使用 HTTP 認證。當服務器在雲端 VM 中運行,並從環境變量讀取憑據時,請使用 stdio env

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  cloud: {
    repos: [{ url: "https://github.com/your-org/your-repo", startingRef: "main" }],
  },
  mcpServers: {
    linear: {
      type: "http",
      url: "https://mcp.linear.app/sse",
      headers: {
        Authorization: `Bearer ${process.env.LINEAR_API_KEY!}`,
      },
    },
    figma: {
      type: "http",
      url: "https://api.figma.com/mcp",
      auth: {
        CLIENT_ID: process.env.FIGMA_CLIENT_ID!,
        CLIENT_SECRET: process.env.FIGMA_CLIENT_SECRET!,
        scopes: ["file_content:read"],
      },
    },
    github: {
      type: "stdio",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: {
        GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
      },
    },
  },
});

靜態 API 密鑰或 Bearer token 請使用 headers,Cursor 會在每次請求中原樣傳遞。受 OAuth 保護的服務器請使用 auth。在雲端,Cursor 會在服務端執行一次 OAuth 流程,並在多次運行間複用 token。在本地,SDK 無法打開瀏覽器讓您登錄;它只能複用您已通過 Cursor app 登錄獲取的 token。

  • HTTP headersauth 由 Cursor 後端處理。敏感字段會被脫敏,不會進入 VM。
  • Stdio env 值會傳入 VM,因爲服務器在其中運行。請將其視爲其他運行時機密信息一樣妥善處理。
  • 在 cursor.com/agents 上配置的 MCP 服務器,其 OAuth 始終按用戶區分,即使是團隊級服務器也是如此。

完整配置格式請參閱 MCP,雲端特定行爲請參閱 Cloud Agent capabilities

子智能體

定義由主智能體通過 Agent 工具啓動的具名子智能體,並以內聯方式傳入:

const agent = await Agent.create({
  model: { id: "composer-2.5" },
  apiKey: process.env.CURSOR_API_KEY!,
  local: { cwd: process.cwd() },
  agents: {
    "code-reviewer": {
      description: "Expert code reviewer for quality and security.",
      prompt: "Review code for bugs, security issues, and proven approaches.",
      model: "inherit",
    },
    "test-writer": {
      description: "Writes tests for code changes.",
      prompt: "Write comprehensive tests for the given code.",
    },
  },
});

同樣會識別已提交到倉庫 .cursor/agents/*.md 中的子智能體 (包含 namedescription 和可選的 model frontmatter) 。內聯定義會覆蓋同名的基於文件的定義。

嵌套子智能體

子智能體可在嵌套層級限制內啓動自己的子智能體。當子智能體使用 Agent 工具時,SDK 會爲其提供與父智能體相同的子智能體執行器,因此父智能體可以將任務委派給還能繼續委派的子智能體。每一層都可訪問同一組具名子智能體和自定義工具。頂層智能體及其直接子智能體可以啓動子智能體,但由子智能體啓動的子智能體無法再啓動下一級子智能體。

限制工具集

tools 將模型可用的內置工具限定爲允許列表中的工具;disallowedTools 會移除指定工具,保留其餘工具,包括在您的 SDK 版本發佈後添加到平臺的工具。目前兩者僅支持本地智能體,且都不會持久保存在智能體中:如需在後續運行中保持此限制,請在 Agent.resume() 中再次傳入。

// 只讀智能體:僅可使用這些工具。
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() },
});

// 除 shell 外的所有工具。
const noShell = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  disallowedTools: ["shell"],
  local: { cwd: process.cwd() },
});
  • tools: undefined (默認值) 爲所選模型提供標準工具集;tools: [] 不提供任何內置工具,因此模型只能返回文本響應。
  • 兩個字段都接受 ToolName 聯合類型:公開名稱 ("read""edit""task""webSearch"、……) 、能力羣組 "shell""mcp",以及原始 proto 工具名稱。未知名稱會在調用 Agent.create() / Agent.resume() 時拋出 ConfigurationError
  • 禁止項優先:要提供某個工具,該工具必須包含在 tools 中 (如已設置) ,且不在 disallowedTools 中。
  • 禁用 "mcp" 也會移除自定義工具。禁用 "task" 會阻止子智能體;否則子智能體會保留各自精選的工具集。

自定義工具

自定義工具讓你無需單獨搭建 MCP 服務器,即可向智能體公開自己的函數。通過 local.customTools 傳入這些工具後,SDK 會將其註冊爲名爲 custom-user-tools 的 MCP 服務器。智能體會通過與其他服務器相同的 MCP 路徑發現並調用它們。拒絕規則和 沙箱限額仍然適用,但自定義工具無需交互式批准,因此沙箱化Auto-review 模式運行會直接調用它們,不會提示。自定義工具也可供子智能體 (包括嵌套子智能體) 使用。

自定義工具僅適用於本地智能體。向雲端代理傳入 local.customTools 會拋出 ConfigurationError

const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  local: {
    cwd: process.cwd(),
    customTools: {
      get_deployment_status: {
        description: "Look up the current deployment status for a service.",
        inputSchema: {
          type: "object",
          properties: {
            service: { type: "string", description: "Service name" },
          },
          required: ["service"],
        },
        async execute({ service }) {
          const res = await fetch(`https://deploys.internal/api/${service}`);
          const body = await res.json();
          return `Service ${service} is ${body.status} (build ${body.build}).`;
        },
      },
    },
  },
});

await agent.send("Is the checkout service deployed yet?").then((r) => r.wait());

Agent.create() 中設置一次自定義工具,即可應用於每次運行;或者在單次 agent.send() 中傳入 local.customTools,以替換該次運行的自定義工具。

await agent.send("Roll forward if the canary is healthy", {
  local: {
    customTools: {
      promote_canary: {
        description: "Promote the current canary build to production.",
        async execute() {
          await promoteCanary();
          return { content: [{ type: "text", text: "Promoted." }] };
        },
      },
    },
  },
});

工具定義

interface SDKCustomTool {
  description?: string;
  inputSchema?: Record<string, SDKJsonValue>;
  execute: (
    args: Record<string, SDKJsonValue>,
    context: SDKCustomToolContext
  ) => SDKCustomToolResult | Promise<SDKCustomToolResult>;
}

interface SDKCustomToolContext {
  toolCallId?: string;
}
字段 描述
description 展示給模型,用於判斷何時調用該工具。默認值爲空 string。
inputSchema arguments 的 JSON Schema。默認值爲允許任意屬性的開放 object。
execute 您的 callback。接收解析後的 args 以及包含 toolCallIdcontext。在您的 process 中運行,因此可訪問您的代碼能訪問的任何內容。

工具結果

execute 可以返回普通 string、任意 JSON 值或結構化 envelope。map 的鍵是模型調用的工具名稱。

type SDKCustomToolResult =
  | string
  | SDKJsonValue
  | {
      content: SDKCustomToolContent[];
      isError?: boolean;
      structuredContent?: Record<string, SDKJsonValue>;
    };

type SDKCustomToolContent =
  | { type: "text"; text: string }
  | { type: "image"; data: string; mimeType?: string };
  • 純文本輸出請返回 string。
  • 返回任意 JSON 值即可將其作爲文本發回;對象還會填充 structuredContent
  • 如需完全控制,請返回 envelope:可混合文本和 base64 圖像 content,設置 isError: true 以報告失敗,或附加 structuredContent 供模型解析。execute 拋出異常也會作爲工具錯誤報告給智能體。

鉤子

鉤子僅支持基於文件的配置方式,不提供可編程的鉤子回調。鉤子是項目策略的邊界,而不是每次運行時可調節的選項。

  • 本地:.cursor/hooks.json 添加到傳遞給 local.cwd 的倉庫中,或添加 ~/.cursor/hooks.json 以配置用戶級鉤子。
  • 雲端:.cursor/hooks.json 及其腳本提交到 cloud.repos 中傳入的倉庫。由 SDK 創建的雲端代理會自動加載項目鉤子。在企業版方案中,它們還會運行團隊鉤子和企業級管理的鉤子。

有關配置格式,請參閱鉤子;有關雲端行爲,請參閱雲端代理鉤子支持

沙箱選項

默認情況下,本地智能體以 local.sandboxOptions.enabled: false 運行。智能體可讀取和寫入工作目錄、執行 shell 命令,並可不受限制地訪問網絡。無界面 SDK 運行沒有人工批准流程,因此默認啓用沙箱要麼會靜默阻止合法的工具調用,要麼需要不適用於腳本的回調。

啓用沙箱後,SDK 會限制每次 shell 工具調用以及由 shell 啓動的進程:

  • 文件系統 — 僅允許寫入工作目錄 (local.cwd) 和一小部分允許的路徑。禁止讀取工作區以外的內容。
  • Shell — 命令在平臺沙箱中運行 (Linux 上使用 bubblewrap,macOS 上使用 seatbelt,或使用隨附的 @cursor/sdk-<os>-<arch> 輔助程序) 。不允許執行特權操作。
  • 網絡 — 默認禁止出站網絡訪問。若要允許特定主機,請在工作區中添加 .cursor/sandbox.json,列出允許訪問的主機。如果存在,SDK 也會讀取位於 ~/.cursor/sandbox.json 的同一用戶級策略。
const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  local: {
    cwd: process.cwd(),
    sandboxOptions: { enabled: true },
  },
});

如果主機不支持沙箱 (例如較早版本的 Linux 未安裝 bubblewrap,或缺少輔助二進制文件) ,SDK 會拋出 ConfigurationError,並在消息中指出缺少的依賴項。禁用 sandboxOptions.enabled 或改用雲端模式運行即可恢復。

雲端運行始終在隔離的 VM 中執行,因此 sandboxOptions 不適用。

Auto-review 模式

默認情況下,本地智能體會不受限制地執行每個工具調用,因爲無頭運行時沒有人工進行批准。設置 local.autoReview: true 後,本地工具調用將改由 Auto-review 模式 模式處理。該模式使用與 IDE 相同的分類器,根據安全性以及各調用與運行意圖的匹配程度,允許或阻止 Shell、MCP 和 Fetch 調用。

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

Auto-review 模式 需要在已連接的後端啓用分類器;如果分類器不可用,運行將回退到默認行爲。由於無界面運行不支持交互式批准,分類器攔截的調用會被拒絕而非升級處理;智能體會收到攔截原因,並可嘗試其他方法。可通過工作區中的 permissions.json autoRun 塊引導分類器,方式與 IDE 相同。格式請參閱 permissions.json

Auto-review 模式 僅適用於本地智能體。雲端運行已在隔離的 VM 中執行。分類器是一項盡力而爲的便捷功能,並非安全邊界;如需嚴格控制,請結合使用 sandboxOptions允許列表

產物

列出並下載智能體工作區中的文件。

interface SDKArtifact {
  path: string;
  sizeBytes: number;
  updatedAt: string;
}
const artifacts: SDKArtifact[] = await agent.listArtifacts();

for (const artifact of artifacts) {
  console.log(artifact.path, artifact.sizeBytes);
}

const buffer = await agent.downloadArtifact(artifacts[0].path);

Artifact 支持因運行時而異。Local SDK agents 目前不返回任何 artifact,調用 downloadArtifact 時會拋出錯誤。

資源管理

使用完智能體後,務必將其釋放。最簡潔的方式是使用 await using

await using agent = await Agent.create({ /* ... */ });
// 退出代碼塊時會自動釋放

要顯式釋放資源:

await agent[Symbol.asyncDispose]();

agent.close() 是無需等待即可開始釋放資源的推薦方法。Symbol.asyncDispose 也可用 (await using 基於它實現) ,但對於不使用 await using 語法的代碼,應使用 close()agent.reload() 可在不釋放資源的情況下加載文件系統配置的更改 (鉤子、項目 MCP、子智能體) 。

智能體生命週期

預熱本地工作區

解析本地工作區 (規則、技能、MCP 服務器、忽略文件) 是本地智能體首次執行時最耗時的環節,在大型倉庫中甚至可能佔據絕大部分時間。默認情況下,這項開銷會計入首次 send() 調用。主機如果知道智能體將在何處運行,可以通過 prewarmLocalWorkspace() 提前完成這項工作:

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

const platform = await createAgentPlatform();
const release = await platform.prewarmLocalWorkspace({
  apiKey: process.env.CURSOR_API_KEY!,
  local: { cwd: "/srv/checkout", settingSources: ["project"] },
});

// 此工作區的首次 send() 會立即執行。

await release(); // 主機關閉時

傳入智能體將使用的同一組 AgentOptions;預熱僅對工作區選項相匹配的發送有效。主機關閉時,調用返回的 release 函數。

重新連接到現有智能體

Agent.resume(agentId) 會返回一個用於操作現有智能體的新句柄。系統會根據 ID 前綴自動識別運行時 (bc- 表示雲端,其他前綴表示本地) ,並從雲端 (雲端) 或本地檢查點存儲 (本地) 加載對話狀態。這可用於在進程重新啓動後繼續工作,或讓其他 worker 接手由另一個進程啓動的智能體。

const agent = await Agent.resume("bc-abc123", {
  apiKey: process.env.CURSOR_API_KEY!,
});

const run = await agent.send("Apply the suggested fix");
const result = await run.wait();

如果重新連接時該運行已在進行中,Agent.getRun(runId, { runtime: "cloud", agentId }) (或本地等效方法) 會返回一個 Run,可對其調用 stream()wait()cancel()

對話上下文

本地智能體會將對話狀態持久化到檢查點存儲中。默認使用主目錄下基於磁盤的 SQLite;也可通過 local.store 替換爲 JSONL 或自定義後端。每次調用 agent.send() 都會加載該智能體的最新檢查點並傳遞給模型,因此後續交互能獲得上一次運行結束時的相同上下文。該存儲在進程重新啓動後仍會保留,因此在全新的進程中調用 Agent.resume(agentId) 可以從上次結束的位置繼續。

雲端代理會在服務器端持久化狀態。從任何位置重新連接,都會返回同一對話。

以下幾種情況看似丟失了上下文,但其實並非如此:

  • 每次調用 Agent.create() 都會使用新的 agentId 創建一個全新的智能體。若要繼續現有對話,請在首次調用時獲取 agent.agentId,之後使用 Agent.resume(agentId)
  • Agent.prompt() 會一次性創建、運行並釋放智能體。不會有第二輪交互;這是其合約。
  • 內聯 mcpServers 不會在 Agent.resume() 後保留,因爲其中通常包含機密信息。恢復時請再次傳入,或使用基於文件的 MCP 配置。

調度器模式

調度器管理一個智能體池,並在任務到達時將其分配給相應的智能體。其模式很簡單:維護一個從 agentId 到長期存活的 SDKAgent 的映射,根據某個鍵 (用戶、倉庫、工單) 路由傳入的提示詞;如果進程重啓導致內存中的映射丟失,則從磁盤恢復並調用 Agent.resume()

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

const agents = new Map<string, SDKAgent>();

async function getAgent(key: string, savedId?: string): Promise<SDKAgent> {
  const existing = agents.get(key);
  if (existing) return existing;

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

  agents.set(key, agent);
  return agent;
}

async function handleMessage(key: string, prompt: string, savedId?: string) {
  const agent = await getAgent(key, savedId);
  const run = await agent.send(prompt);
  return run.wait();
}

雲端 SSE 流會在運行開始後的一段時間內保留積壓事件,因此向多個訂閱者提供流的調度器可讓每個訂閱者調用 run.stream(),而不會丟失先前的事件。對於運行時間特別長的雲端運行,調度器通常會將任務分發給 run.wait(),並讓需要結構化會話記錄的訂閱者輪詢 run.conversation()

本地智能體存儲

本地智能體會將智能體元數據、對話檢查點、運行記錄和運行事件持久化到磁盤,以便後續操作和 Agent.resume() 在進程重啓後仍可繼續執行。默認情況下,SQLite 後端可用時,SDK 會使用基於磁盤的 SQLite;否則回退到 JsonlLocalAgentStore。您可以通過 local.store 替換爲其他後端。

SDK 提供兩種後端,也支持您自定義後端:

存儲 導入 適用場景
SqliteLocalAgentStore @cursor/sdk/sqlite 工作區狀態根目錄下的基於磁盤的 SQLite。
JsonlLocalAgentStore @cursor/sdk 存儲在您指定目錄中的可移植換行分隔 JSON (NDJSON) 文件。便於查看、複製和 diff。
自定義 LocalAgentStore 您的代碼 可持久化到任意位置:內存、Redis、Postgres 或託管數據庫。實現該接口或組合子存儲。

雲端代理在服務器端持久化,因此 local.store 僅適用於本地智能體。

JSONL 存儲

JsonlLocalAgentStore 會在你指定的目錄中寫入四個 NDJSON 文件 (agents.ndjsonruns.ndjsonrun_events.ndjsoncheckpoints.ndjson) 。創建一個實例,並將其傳給 local.store

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

const store = new JsonlLocalAgentStore("/var/lib/cursor-agents");

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

Agent.resume() 以及本地列表和獲取 API (Agent.listAgent.getAgent.listRunsAgent.getRun) 中使用同一存儲實例,確保它們讀取相同的數據。

設置進程級默認值

爲避免在每次調用時都傳遞存儲,可通過 Cursor.configure() 一次性設置默認值。傳入 local.store 時,仍以該調用中指定的值爲準。

import { Cursor, JsonlLocalAgentStore } from "@cursor/sdk";

Cursor.configure({ local: { store: new JsonlLocalAgentStore("/var/lib/cursor-agents") } });

// 後續調用會使用已配置的存儲,除非自行傳入存儲。
const agent = await Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2.5" },
  local: { cwd: process.cwd() },
});

Cursor.configure({ local: { store: null } }) 傳入 store: null,即可清除先前設置的默認值,並恢復爲使用 SDK’s 默認本地存儲。

自定義存儲

如需將數據持久化到其他位置 (如共享的 Postgres、Redis,或供測試使用的內存映射) ,請實現 LocalAgentStore。它由四個子存儲組成,每個都是供 SDK 調用的小型 CRUD 接口:

interface LocalAgentStore {
  readonly agents: LocalAgentStoreAgents;         // 智能體元數據記錄
  readonly checkpoints: LocalAgentStoreCheckpoints; // 按內容尋址的對話 Blob
  readonly runs: LocalAgentStoreRuns;             // 運行記錄
  readonly runEvents: LocalAgentStoreRunEvents;   // 僅追加的運行事件日誌
}

直接實現該接口,或分別構建各個子存儲,再使用 composeLocalAgentStore 將其組合起來:

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

const store = composeLocalAgentStore({
  agents: myAgentsTable,
  checkpoints: myCheckpointBlobs,
  runs: myRunsTable,
  runEvents: myRunEventLog,
});

這些子存儲與默認的 SQLite 表相對應:agents 中每個智能體佔一行 (包含一個精簡的 latestCheckpoint.rootBlobId 指針) ,checkpoints 存儲這些指針所引用的按內容尋址的對話 blob,runs 中每次運行佔一行,runEvents 則是僅追加的流式日誌。目錄子存儲通過不透明的 cursor / nextCursor 實現分頁;運行事件日誌則通過排他性的 afterOffset / nextOffset 恢復。具體的數據結構請參閱導出的 LocalAgentStoreLocalAgentDocumentLocalAgentRunDocument 及相關類型。

配置參考

AgentOptions

屬性 類型 默認值 描述
model ModelSelection 本地必填;雲端會回退到服務器解析的默認值 要使用的模型。參見 ModelSelection
apiKey string CURSOR_API_KEY 環境變量 用戶 API 密鑰或服務賬戶密鑰。暫不支持團隊 Admin 密鑰。
name string 自動生成 供人閱讀的智能體名稱,在 Agent.list() / Agent.get() 中以 name 字段返回。
local LocalAgentOptions 本地智能體配置。參見 LocalAgentOptions
cloud CloudAgentOptions 雲端代理配置。
mcpServers Record<string, McpServerConfig> 內聯 MCP 服務器定義。
agents Record<string, AgentDefinition> 子智能體定義。
tools ToolName[] 默認工具集 限制工具集:僅向模型提供列出的內置工具。[] 表示不提供內置工具。僅適用於本地智能體。
disallowedTools ToolName[] 從工具集中移除工具;其他工具仍可用。與 tools 一起使用時,以拒絕爲準。僅適用於本地智能體。
agentId string 自動生成 持久化智能體 ID。傳入此值可在多次調用間保持 ID 穩定。
idempotencyKey string 雲端自動生成 可選的客戶端生成冪等性密鑰。
mode "agent" \| "plan" "agent" 智能體首次運行時的初始對話模式。參見對話模式

LocalAgentOptions

本地智能體的配置,通過 Agent.create()local 參數傳入。也可作爲獨立類型導出,供 Partial<LocalAgentOptions> 使用。

屬性 類型 默認值 描述
cwd string 默認 shell 的主工作目錄,並用於確定智能體存儲的作用域。
dirs string[] 用於多根工作區的其他工作區文件夾。與 cwd 合併 (去除重複項) ,以便從每個路徑加載規則、技能和工作區上下文。
settingSources SettingSource[] 要加載的全局設置層:"project""user""team""mdm""plugins""all"
sandboxOptions { enabled: boolean } { enabled: false } 沙箱配置。
autoReview boolean false 通過 Auto-review 模式處理本地工具調用。
customTools Record<string, SDKCustomTool> custom-user-tools MCP 服務器形式公開的自定義工具
store LocalAgentStore SDK 默認存儲 用於持久化的本地智能體存儲
enableAgentRetries boolean true 爲本地智能體運行啓用傳輸錯誤和停滯時的自動重試。設爲 false 可在首次失敗時直接顯示傳輸錯誤。

CloudAgentOptions

屬性 類型 默認值 描述
env { type: "cloud"; name?: string } \| { type: "pool"; name?: string } \| { type: "machine"; name?: string } { type: "cloud" } 執行環境目標。cloud 使用 Cursor 託管的 VM;設置 name 可使用已保存的 Cursor 託管環境。poolmachine 會路由到您運行的自託管 worker。若要創建工作區爲空且不含倉庫的智能體,請省略 repos 並保留 env 的默認值。已命名的 Cursor 託管環境與顯式指定的 repos 互斥。
repos Array<{ url: string; startingRef?: string; prUrl?: string }> 要克隆到 VM 的倉庫。單倉庫智能體傳入一個條目,多倉庫智能體最多可傳入 20 個條目。對於無倉庫智能體,請省略此項或傳入 []。與 Cursor 託管環境中指定的 env.name 互斥。傳入 prUrl 可將智能體關聯到現有 PR。
workOnCurrentBranch boolean false 將提交推送到現有分支,而不是新分支。
autoCreatePR boolean false 運行完成時創建 PR。
openAsCursorGithubApp boolean 服務賬戶密鑰爲 true,用戶密鑰爲 false 以 Cursor GitHub App 的身份而非 API 密鑰所有者的身份創建 PR。解析後的值會在創建、獲取和列出時返回。
skipReviewerRequest boolean false 不請求將調用用戶添加爲 PR 審閱人。
envVars Record<string, string> 雲端代理的會話範圍環境變量。
metadata Record<string, string> 由調用方擁有、持久保存在雲端代理上的 string 標籤。請參閱智能體元數據

AgentDefinition

屬性 類型 默認值 描述
description string 必填 此子智能體的使用時機。會顯示給父智能體,以便其瞭解何時生成該子智能體。
prompt string 必填 子智能體的系統提示詞。
model ModelSelection \| "inherit" "inherit" 模型覆蓋。傳入 "inherit" 以使用父智能體的模型選擇。
mcpServers Array<string \| Record<string, McpServerConfig>> 此子智能體可用的 MCP 服務器。名稱引用父智能體 mcpServers 中的服務器。

ModelSelection

interface ModelSelection {
  id: string;
  params?: ModelParameterValue[];
}

interface ModelParameterValue {
  id: string;
  value: string;
}

id 是模型標識符 (例如 "composer-2.5""auto-smart") 。params 用於指定模型專屬參數,例如 reasoning effort 或 Router 的 optimize_for。使用 Cursor.models.list() 查找您的賬戶可用的有效 id、參數定義和預設變體。有關 Router 的選擇合約,請參閱 Cursor Router

McpServerConfig

type McpServerConfig =
  // stdio
  | {
      type?: "stdio";
      command: string;
      args?: string[];
      env?: Record<string, string>;
      cwd?: string;       // 僅限本地;雲端不支持此字段
    }
  // HTTP / SSE
  | {
      type?: "http" | "sse";
      url: string;
      headers?: Record<string, string>;   // 原樣傳遞;可在此處使用 Authorization
      auth?: {
        CLIENT_ID: string;
        CLIENT_SECRET?: string;
        scopes?: string[];
      };
    };

對於在雲端運行的 HTTP 服務器,headersauth 由 Cursor 後端處理。敏感字段會在 VM 接收到之前被脫敏。對於在雲端運行的 stdio 服務器,env 值會傳入 VM (請將其視爲運行時機密信息) 。

SDK用戶消息

interface SDKUserMessage {
  text: string;
  images?: SDKImage[];
}

agent.send() 消息參數的結構化格式。可用於在發送文本時附帶圖像。

SDKImage

type SDKImage =
  | { url: string; dimension?: SDKImageDimension }
  | { data: string; mimeType: string; dimension?: SDKImageDimension };

interface SDKImageDimension {
  width: number;
  height: number;
}

傳入遠程 url,或包含 mimeType 的 base64 編碼 data

SettingSource

type SettingSource =
  | "project"
  | "user"
  | "team"
  | "mdm"
  | "plugins"
  | "all";

控制本地智能體加載哪些存儲在磁盤上的設置層。雲端代理始終加載 project / team / plugins,並忽略此字段。

來源
"project" 工作區中的 .cursor/
"user" ~/.cursor/
"team" 從儀表盤同步的團隊設置
"mdm" 由 MDM 管理的企業版設置
"plugins" 插件提供的設置
"all" 上述所有設置的簡寫

ListResult

interface ListResult<T> {
  items: T[];
  nextCursor?: string;
}

Agent.list()Agent.listRuns() 返回。沒有更多頁時,不會返回 nextCursor

錯誤

所有 SDK 錯誤均繼承自 CursorSdkError (爲保持向後兼容性,以 CursorAgentError 重新導出) 。可使用 isRetryable 控制重試邏輯,並通過 code / status / requestId 進行診斷。

class CursorSdkError extends Error {
  readonly isRetryable: boolean;
  readonly code?: string;       // 穩定的 SDK / 後端錯誤代碼
  readonly status?: number;     // HTTP 狀態碼(如有)
  readonly cause?: unknown;     // 封裝的底層錯誤
  readonly endpoint?: string;
  readonly requestId?: string;
  readonly operation?: string;  // 引發該錯誤的 SDK 操作
}
錯誤類 典型消息 可能原因 推薦解決方法
AuthenticationError “無效的 API 密鑰” 缺少或錯誤的 CURSOR_API_KEY、令牌已過期,或管理員已禁用該密鑰。 API Keys (用戶) 或 團隊設置 (服務賬戶) 中生成新密鑰。確認該密鑰擁有執行此操作的權限。
RateLimitError “超出速率限制”或 “超出用量限制” 突發請求限制或每月用量上限。 使用指數退避重試 (對於臨時情況,SDK 會報告 isRetryable: true) 。若達到每月上限,請提高套餐的用量限制
ConfigurationError “模型名稱錯誤”、”不支持 API 密鑰”、”不支持該文件” model.id 無效、缺少必需的 params、工具調用中使用了不受支持的文件,或管理員策略阻止了請求。 調用 Cursor.models.list() 確認 ID 和參數。檢查倉庫和文件路徑是否存在。
AgentBusyError “智能體正忙” 同一雲端代理已有處於 CREATINGRUNNING 狀態的運行時,又發送了後續請求。 等待活躍運行完成、取消該運行,或在再次發送前輪詢 Agent.listRuns()
IntegrationNotConnectedError “[提供商] 集成未連接” 爲 SCM 提供商尚未連接到 Cursor 團隊的倉庫創建雲端代理。 打開 error.helpUrl 重新連接提供商,然後重試。
NetworkError “服務不可用”、”超時” 臨時後端問題、網絡分區或超過截止時間。 使用退避策略重試。如需提交支持工單,請查看 error.requestId
UnsupportedRunOperationError “此運行時不支持操作 “stream”“ 調用了當前運行時無法支持的 Run 方法 (例如,對已完成的重新獲取的本地運行進行流式處理) 。 先通過 run.supports(operation) / run.unsupportedReason(operation) 檢查。
AgentNotFoundError “未找到智能體” 請求的智能體不存在,或在解析後的本地工作區中不可見。 檢查智能體 ID、cwdlocal.store
UnknownAgentError 由服務器定義的消息 未分類的後端或運行時錯誤。 查看 error.codeerror.cause 以瞭解底層詳情。

檢查 error.helpUrl

某些錯誤會附帶一鍵解決鏈接。最常見的是
IntegrationNotConnectedError,但未來更多錯誤類型也可能添加 helpUrl
捕獲錯誤時,如果存在 error.helpUrl,請記錄並展示給用戶。

IntegrationNotConnectedError

class IntegrationNotConnectedError extends ConfigurationError {
  readonly provider: string;   // 例如:"github"、"gitlab"、"azuredevops"
  readonly helpUrl: string;    // 用於重新連接的儀表盤鏈接
}

默認錯誤消息不包含 helpUrl,因此請顯式記錄:

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

try {
  await Agent.create({
    apiKey: process.env.CURSOR_API_KEY!,
    cloud: {
      repos: [{ url: "https://github.com/your-org/private-repo" }],
    },
  });
} catch (err) {
  if (err instanceof IntegrationNotConnectedError) {
    console.error(err.provider, err.helpUrl);
  }
}

AgentBusyError

class AgentBusyError extends CursorAgentError {}

對於 agent_busyisRetryablefalse。立即重試會一直失敗,直到正在運行的任務結束或您將其取消。其他 409 響應 (例如 agent_archived) 則會拋出 ConfigurationError

等待正在運行的任務完成,使用 run.cancel() 將其取消,或在再次發送前輪詢 Agent.listRuns()

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

const agent = await Agent.resume("bc-00000000-0000-0000-0000-000000000001");

try {
  await agent.send({ text: "Also add tests for the auth middleware." });
} catch (err) {
  if (err instanceof AgentBusyError) {
    const runs = await Agent.listRuns(agent.agentId, { runtime: "cloud", limit: 1 });
    const active = runs.items[0];
    if (active?.status === "running") {
      await active.cancel();
    }
    await agent.send({ text: "Also add tests for the auth middleware." });
    return;
  }
  throw err;
}

本地智能體不會返回 agent_busy。啓動新的本地運行前,使用 send({ local: { force: true } }) 終止卡住的本地運行。

UnsupportedRunOperationError

class UnsupportedRunOperationError extends ConfigurationError {
  readonly operation: RunOperation;
}

當前運行時無法執行某個 Run 操作時拋出。請在調用前使用 run.supports(operation)run.unsupportedReason(operation) 進行檢查。

已知限制

  • 內聯 mcpServers 不會在 Agent.resume() 後保留。如有需要,請在恢復時再次傳入。
  • 自定義工具 (local.customTools)、Auto-review 模式 (local.autoReview)、自定義存儲 (local.store) 和工具集限制 (toolsdisallowedTools) 僅適用於本地智能體。雲端代理會拒絕 local.customTools,並在服務器端持久化。
  • toolsdisallowedTools 不會保留在智能體中。請在 Agent.resume() 時再次傳入,以維持這些限制。
  • 本地智能體尚不支持下載 Artifact (agent.listArtifacts() 返回空列表,agent.downloadArtifact() 會拋出異常) 。
  • local.settingSources (以及它所控制的基於文件的 MCP / 子智能體路徑) 不適用於雲端代理。雲端始終加載 project / team / plugins
  • 鉤子僅支持基於文件的方式 (.cursor/hooks.json) ,不支持編程式回調。
  • SDK 不會自動從本地安裝的 Cursor app 中發現憑據。請顯式設置 CURSOR_API_KEY (或傳入 apiKey) ,或通過 Cursor.auth.login() 創建密鑰。
  • 本地模式需要 Node.js 22.13 或更高版本,以及平臺對 sandbox-helper 的支持。SQLite 後端不可用時,默認存儲會回退到 JsonlLocalAgentStore
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜