cursor-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cursor SDK

Cursor SDK

The Cursor TypeScript SDK (
@cursor/sdk
) runs Cursor agents programmatically. The same interfaces drives the local runtime (agent runs on your machine against your files) and the cloud runtime (agent runs on Cursor-hosted or self-hosted infrastructure against a cloned repo and opens PRs).
Use this skill to help someone bootstrap a working integration quickly and avoid the handful of traps that bite new users. Canonical docs live at https://cursor.com/docs/api/sdk/typescript; this skill only adds decision-making, failure-mode prevention, and ready-to-extend patterns.
Cursor TypeScript SDK(
@cursor/sdk
)可通过程序化方式运行Cursor agent。同一接口同时支持本地运行时(agent在你的机器上针对本地文件运行)和云运行时(agent在Cursor托管或自托管的基础设施上运行,针对克隆的仓库并创建PR)。
使用本技能可帮助用户快速搭建可用的集成避开新用户常遇到的陷阱。官方文档位于https://cursor.com/docs/api/sdk/typescript;本技能仅补充决策指导、故障预防方案及可扩展的现成模式。

Voice and Posture

语气与定位

This skill helps the user build with the SDK. It is not the place to validate, congratulate, or sell the SDK as a choice. The user's intent is the input; your job is execution.
  • When the user names the SDK explicitly (says "Cursor SDK",
    @cursor/sdk
    ,
    Agent.create
    ,
    Agent.prompt
    , etc.): assume they know what the SDK is and have decided to use it. Skip framing, skip pep talk, go straight to producing the integration. No "good news", no "the SDK is perfect for this", no "this is almost exactly the pattern X is designed for".
  • When the user describes a problem the SDK fits but doesn't name it ("I want a bot that reviews my PRs", "I want a script that asks Cursor questions about my repo"): the SDK isn't yet a confirmed choice. Surface it as a question, briefly, then wait: "The Cursor SDK is what I'd reach for here — want me to design it that way, or do you have a different runtime in mind?" If they confirm, proceed. If they push back or want options, give options.
  • In either case, don't restate the user's intent back to them. They know what they want. Get to the design.
Avoid these specific openers (and their close cousins):
  • "Good news: this is exactly the pattern…"
  • "The SDK is built for this shape."
  • "Great, you've come to the right place."
  • "This is almost exactly the X the SDK is designed for."
  • Any lede that compliments the user's choice or restates their goal in flattering terms.
Prefer:
  • Open with the design decision or the first thing they need to know.
  • If you genuinely have a design choice to flag (local vs cloud, prompt vs send, sync vs stream), name it in one sentence and explain why; don't preface it with validation.
本技能旨在帮助用户使用SDK进行构建。此处无需验证、称赞或推销SDK。用户的需求是输入,你的工作是执行。
  • 当用户明确提及SDK时(如说“Cursor SDK”、
    @cursor/sdk
    Agent.create
    Agent.prompt
    等):假设用户了解SDK是什么并已决定使用它。跳过介绍、跳过鼓励,直接进入集成实现。不要说“好消息”、“SDK非常适合这个场景”、“这正是X模式的设计初衷”之类的话。
  • 当用户描述的问题适合SDK但未明确提及它时(如“我想要一个能审核PR的机器人”、“我想要一个脚本让Cursor查询我的仓库”):SDK尚未被确认作为方案。简要地将其作为选项提出,然后等待用户回复:*“我会推荐使用Cursor SDK来实现——需要我按这个方案设计,还是你有其他运行时的想法?”*如果用户确认,继续推进;如果用户反对或需要其他选项,则提供备选方案。
  • 无论哪种情况,都不要重复用户的需求。用户清楚自己想要什么,直接进入设计环节。
避免使用以下开场白(及类似表述):
  • “好消息:这完全符合……模式”
  • “SDK就是为这类场景打造的”
  • “很棒,你来对地方了”
  • “这几乎完全是SDK为X设计的场景”
  • 任何称赞用户选择或用奉承语气重复其目标的开场白。
推荐使用:
  • 直接以设计决策或用户需要了解的第一件事开场。
  • 如果确实有需要指出的设计选择(本地vs云、prompt vs send、同步vs流式),用一句话说明并解释原因;不要用验证性的话作为前缀。

When to open a reference file

何时打开参考文件

Keep this page short. Read a reference file only when the user's task clearly falls inside it:
If the user is...Read
Picking between local and cloud runtime, or not sure which they should use
references/runtime-choice.md
Debugging auth (401s, "Missing CURSOR_API_KEY", team-vs-user keys, local vs prod)
references/auth.md
Handling errors, retries, rate limits,
CursorAgentError
,
result.status === error
references/error-handling.md
Consuming streams, picking event types, cancelling, or deciding stream vs wait
references/streaming.md
Configuring MCP servers (HTTP, stdio, cloud vs local transport, auth injection)
references/mcp.md
Using sub-agents, resume, artifacts, listing/inspecting agents,
Agent.messages
references/advanced.md
Building a specific integration (CI review bot, scheduled triage, chat, webhook)
references/patterns.md
Everything below is the minimum needed for 80% of tasks.
保持本页面简洁。仅当用户的任务明确属于某参考文件的范围时,才打开该文件:
用户的需求是...参考文件
在本地与云运行时之间做选择,或不确定应使用哪一种
references/runtime-choice.md
调试授权问题(401错误、“Missing CURSOR_API_KEY”、团队密钥vs用户密钥、本地vs生产)
references/auth.md
处理错误、重试、速率限制、
CursorAgentError
result.status === error
references/error-handling.md
处理流式传输、选择事件类型、取消操作,或决定使用流式还是等待模式
references/streaming.md
配置MCP服务器(HTTP、标准输入输出、云vs本地传输、授权注入)
references/mcp.md
使用子agent、resume、工件、列出/检查agent、
Agent.messages
references/advanced.md
构建特定集成(CI审核机器人、定期分类、聊天、Webhook)
references/patterns.md
以下内容是完成80%任务所需的最小知识集。

The Three Invocation Patterns

三种调用模式

Almost every SDK integration collapses to one of three shapes. Pick the one that fits the job, don't mix them.
几乎所有SDK集成都可归为以下三种模式之一。选择适合任务的模式,不要混合使用。

1.
Agent.prompt(...)
— one-shot

1.
Agent.prompt(...)
— 一次性调用

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

const result = await Agent.prompt("Refactor src/utils.ts for readability", {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});
console.log(result.status, result.result);
Use for fire-and-forget scripts, GitHub Actions steps, or any "send this prompt, get a result, exit" flow. No streaming, no follow-ups, no cleanup to remember. If you're reaching for this and then immediately resuming, you wanted pattern 2 instead.
typescript
import { Agent } from "@cursor/sdk";

const result = await Agent.prompt("Refactor src/utils.ts for readability", {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});
console.log(result.status, result.result);
适用于“发送即忘”脚本、GitHub Action步骤,或任何“发送提示、获取结果、退出”的流程。无需流式传输、无需后续跟进、无需记住清理操作。如果你选择此模式后立即调用resume,那你实际需要的是第二种模式。

2.
Agent.create(...)
+
agent.send(...)
— durable with follow-ups

2.
Agent.create(...)
+
agent.send(...)
— 持久化支持后续跟进

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

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

try {
  const run = await agent.send("Find the bug in src/auth.ts");
  for await (const event of run.stream()) {
    if (event.type === "assistant") {
      for (const block of event.message.content) {
        if (block.type === "text") process.stdout.write(block.text);
      }
    }
  }
  const result = await run.wait();

  // Follow-up keeps full conversation context.
  const run2 = await agent.send("Now write a regression test for it");
  await run2.wait();
} finally {
  await agent[Symbol.asyncDispose]();
}
Use when you need streaming, multi-turn conversation, or lifecycle operations (cancel, status listener). This is the shape of most non-trivial integrations.
typescript
import { Agent } from "@cursor/sdk";

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

try {
  const run = await agent.send("Find the bug in src/auth.ts");
  for await (const event of run.stream()) {
    if (event.type === "assistant") {
      for (const block of event.message.content) {
        if (block.type === "text") process.stdout.write(block.text);
      }
    }
  }
  const result = await run.wait();

  // 后续跟进会保留完整对话上下文。
  const run2 = await agent.send("Now write a regression test for it");
  await run2.wait();
} finally {
  await agent[Symbol.asyncDispose]();
}
适用于需要流式传输、多轮对话或生命周期操作(取消、状态监听)的场景。这是大多数非 trivial 集成的模式。

3.
Agent.resume(...)
— pick up an existing agent later

3.
Agent.resume(...)
— 后续恢复现有agent

typescript
const agent = Agent.resume(previousAgentId, {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});
const run = await agent.send("Also update the changelog");
await run.wait();
Use across process boundaries: a cron that continues last night's cleanup, a webhook that extends a user's agent, an interactive CLI that reloads conversation state. Inline
mcpServers
are not persisted across resume
— pass them again on the resume call.
typescript
const agent = Agent.resume(previousAgentId, {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});
const run = await agent.send("Also update the changelog");
await run.wait();
适用于跨进程边界的场景:定时任务继续昨晚的清理工作、Webhook扩展用户的agent、交互式CLI重新加载对话状态。内联的
mcpServers
不会在resume时持久化
——需在resume调用时再次传入。

Top Five Traps (read these before writing code)

五大陷阱(编写代码前务必阅读)

These trip up almost every new integration. They're all easy to prevent once you know about them.
这些陷阱几乎会绊倒所有新用户。一旦了解后,它们都很容易避免。

1. Missing
cloud: { repos }
silently defaults to local

1. 缺失
cloud: { repos }
会静默默认使用本地运行时

AgentOptions
doesn't require
local
or
cloud
; if you omit both, the SDK selects the local runtime. The trap: if you intended a cloud agent and forgot the
cloud:
field, you get a local agent silently — no error, just a local agent ID and a local executor. Always pass
cloud: { repos }
explicitly when you want cloud, and pass
local: { cwd }
explicitly for local even though it's the default. Picking the right runtime: see
references/runtime-choice.md
.
AgentOptions
不要求传入
local
cloud
;如果两者都省略,SDK会选择本地运行时。陷阱在于:如果你想使用云agent却忘记传入
cloud:
字段,会静默创建本地agent——没有错误,只有本地agent ID和本地执行器。当你需要云运行时时,务必显式传入
cloud: { repos }
;即使本地是默认选项,也请显式传入
local: { cwd }
。如何选择合适的运行时:参考
references/runtime-choice.md

2. Two different kinds of failure, one instinct to conflate them

2. 两种不同类型的失败,容易混淆

typescript
try {
  const run = await agent.send(prompt);
  const result = await run.wait();
  if (result.status === "error") {
    // Agent started but failed mid-run. Inspect transcript, git state, tool outputs.
    console.error(`run failed: ${result.id}`);
    process.exit(2);
  }
} catch (err) {
  if (err instanceof CursorAgentError) {
    // Didn't start. Auth, config, network. Fix environment, retry.
    console.error(`startup failed: ${err.message}, retryable=${err.isRetryable}`);
    process.exit(1);
  }
  throw err;
}
CursorAgentError
thrown → the run never executed (auth, config, network).
result.status === "error"
→ the agent did work, and that work failed. Different fixes, different exit codes, different observability. Full taxonomy in
references/error-handling.md
.
typescript
try {
  const run = await agent.send(prompt);
  const result = await run.wait();
  if (result.status === "error") {
    // Agent已启动但在运行中途失败。检查对话记录、Git状态、工具输出。
    console.error(`run failed: ${result.id}`);
    process.exit(2);
  }
} catch (err) {
  if (err instanceof CursorAgentError) {
    // 未启动。可能是授权、配置、网络问题。修复环境后重试。
    console.error(`startup failed: ${err.message}, retryable=${err.isRetryable}`);
    process.exit(1);
  }
  throw err;
}
抛出
CursorAgentError
→ 运行从未执行(授权、配置、网络问题)。
result.status === "error"
→ agent已执行工作,但工作失败。两者的修复方式、退出码、可观测性都不同。完整分类参考
references/error-handling.md

3. Forgetting
await agent[Symbol.asyncDispose]()
leaks resources

3. 忘记
await agent[Symbol.asyncDispose]()
会导致资源泄漏

The SDK holds handles to local executors, persisted run stores, and cloud API clients. Not disposing means leaked child processes, open databases, and in long-running services, memory growth. Always dispose in a
finally
, or use
Agent.prompt()
(disposes for you), or use the
await using
syntax if your tsconfig targets it:
typescript
await using agent = Agent.create({ /* ... */ });
SDK会持有本地执行器、持久化运行存储和云API客户端的句柄。不进行清理会导致子进程泄漏、数据库连接未关闭,在长期运行的服务中还会导致内存增长。务必在
finally
块中进行清理,或使用
Agent.prompt()
(会自动清理),如果你的tsconfig支持,也可以使用
await using
语法:
typescript
await using agent = Agent.create({ /* ... */ });

4. Streaming is optional but
wait()
is (almost) required

4. 流式传输是可选的,但
wait()
(几乎)是必须的

run.stream()
is how you observe;
run.wait()
is how you get the terminal result. You can skip streaming, but skipping
wait()
means you can't tell whether the run finished, errored, or was cancelled, and you'll leak the run's internal watchers. Always call
wait()
. If you don't want live output, just call
wait()
alone. See
references/streaming.md
for event type reference.
run.stream()
用于观察运行过程;
run.wait()
用于获取最终结果。你可以跳过流式传输,但跳过
wait()
意味着你无法知道运行是否完成、出错或被取消,还会泄漏运行的内部监听器。务必调用
wait()
。如果你不需要实时输出,直接调用
wait()
即可。事件类型参考
references/streaming.md

5. Not every
run
operation is supported on every runtime

5. 并非所有
run
操作都支持所有运行时

Run
exposes four operations —
stream
,
wait
,
cancel
,
conversation
— and the runtime may or may not support each. Always guard with
run.supports("...")
before calling, rather than assuming:
typescript
if (run.supports("cancel")) await run.cancel();
if (run.supports("conversation")) console.log(await run.conversation());
Current gap worth knowing about: detached/re-hydrated runs (you got the handle from
Agent.getRun(...)
after the live event store has closed) may not support
stream()
and may have empty
conversation()
.
run.unsupportedReason(op)
tells you why. Cloud
run.conversation()
IS supported — it accumulates best-effort from the stream.
Run
公开了四种操作——
stream
wait
cancel
conversation
——不同运行时可能支持或不支持这些操作。调用前务必用
run.supports("...")
进行检查,不要假设所有操作都支持:
typescript
if (run.supports("cancel")) await run.cancel();
if (run.supports("conversation")) console.log(await run.conversation());
需要注意的当前差异:分离/重新 hydrated 的运行(实时事件存储关闭后,你通过
Agent.getRun(...)
获取的句柄)可能不支持
stream()
,且
conversation()
可能为空。
run.unsupportedReason(op)
会告诉你原因。云运行时的
run.conversation()
是支持的——它会从流中尽可能累积对话内容。

Local vs Cloud, in one sentence each

本地vs云运行时,一句话总结

  • Local — runs on the caller's machine against
    cwd
    , reuses their environment and credentials, good for dev loops and CI that already has a repo checkout.
  • Cloud — runs on a Cursor-hosted VM against a freshly cloned
    repos[].url
    , good for long jobs, fire-and-forget automation, and opening real PRs (
    autoCreatePR: true
    ).
Decision tree, capability differences, and capability gaps (artifacts, cancel, MCP transport):
references/runtime-choice.md
.
  • 本地 — 在调用者的机器上针对
    cwd
    运行,复用调用者的环境和凭据,适合开发循环和已检出仓库的CI流程。
  • — 在Cursor托管的VM上针对新克隆的
    repos[].url
    运行,适合长时间任务、“发送即忘”自动化流程,以及创建真实PR(
    autoCreatePR: true
    )。
决策树、能力差异和能力缺口(工件、取消操作、MCP传输):参考
references/runtime-choice.md

Auth, minimum viable

授权,最简配置

bash
export CURSOR_API_KEY="cursor_..."  # user API key or team service-account key
The SDK reads
CURSOR_API_KEY
if
apiKey
isn't passed. Both user keys (from https://cursor.com/dashboard/cloud-agents) and team service-account keys (Team Settings → Service accounts) work for local and cloud runs.
If you're seeing 401s, the usual suspects are: key pasted with surrounding whitespace, key minted against a different environment, or the key belongs to a user without repo access for a cloud run. Full troubleshooting:
references/auth.md
.
bash
export CURSOR_API_KEY="cursor_..."  # 用户API密钥或团队服务账户密钥
如果未传入
apiKey
,SDK会读取
CURSOR_API_KEY
环境变量。用户密钥(来自https://cursor.com/dashboard/cloud-agents)和团队服务账户密钥(团队设置 → 服务账户)均可用于本地和云运行。
如果你遇到401错误,常见原因包括:密钥粘贴时包含前后空格、密钥针对不同环境生成,或密钥所属用户没有云运行所需的仓库访问权限。完整故障排查:参考
references/auth.md

Model Selection

模型选择

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

const models = await Cursor.models.list({ apiKey: process.env.CURSOR_API_KEY! });
composer-2
is the current default for most integrations.
{ id: "auto" }
lets the server pick. Model IDs change; don't hardcode exotic ones without calling
Cursor.models.list()
first to confirm the caller has access.
Model is required for local, optional for cloud (the server resolves a default from the caller's account).
typescript
import { Cursor } from "@cursor/sdk";

const models = await Cursor.models.list({ apiKey: process.env.CURSOR_API_KEY! });
composer-2
是当前大多数集成的默认模型。
{ id: "auto" }
让服务器自动选择。模型ID会变化;在硬编码特殊模型ID前,请先调用
Cursor.models.list()
确认调用者有权限访问。
本地运行时必须指定模型,云运行时可选(服务器会根据调用者的账户解析默认模型)。

Production Best Practices

生产环境最佳实践

Apply these to any integration that runs unattended:
  1. Wrap every
    Agent.create
    /
    Agent.prompt
    /
    Agent.resume
    in a try/finally with
    [Symbol.asyncDispose]()
    . Non-negotiable.
  2. Distinguish startup failures from run failures — exit code 1 for
    CursorAgentError
    , exit code 2 for
    result.status === "error"
    , exit code 0 only for
    finished
    . Makes CI failures actually readable.
  3. Log
    run.id
    and
    agent.agentId
    immediately after
    send()
    before streaming. If the stream hangs, the IDs are what you need to investigate in the dashboard or via
    Agent.getRun(...)
    .
  4. Respect
    error.isRetryable
    — it's the backend telling you the specific failure is safe to retry. Blind retries can cause duplicate cloud runs; respecting the flag doesn't.
  5. Use
    local: { settingSources: [] }
    (default) unless you need ambient config.
    Opting into
    "all"
    loads project/user/team/MDM settings from the caller's environment, which is rarely what you want from a service. Note:
    settingSources
    lives under
    local
    , not at the top level; it has no effect on cloud agents (cloud always honors team/project/plugins).
  6. For cloud agents in CI, set
    skipReviewerRequest: true
    unless a human should be paged — it suppresses the reviewer-request step and keeps PR notifications quiet.
  7. Always pass
    apiKey
    explicitly
    in shared-infrastructure code instead of relying on the env var. Makes the credential dependency obvious and prevents cross-tenant mistakes.
  8. Prefer
    Agent.prompt(...)
    for true one-shots
    — it disposes for you and is harder to leak.
Longer version with examples:
references/patterns.md
.
以下适用于任何无人值守运行的集成:
  1. 将每个
    Agent.create
    /
    Agent.prompt
    /
    Agent.resume
    包裹在try/finally块中,并调用
    [Symbol.asyncDispose]()
    。这是必须的。
  2. 区分启动失败与运行失败
    CursorAgentError
    使用退出码1,
    result.status === "error"
    使用退出码2,仅当
    finished
    时使用退出码0。这会让CI失败信息更易读。
  3. send()
    后立即记录
    run.id
    agent.agentId
    ,然后再进行流式传输。如果流挂起,这些ID是你在仪表板或通过
    Agent.getRun(...)
    进行调查所需的。
  4. 尊重
    error.isRetryable
    — 这是后端告诉你该特定故障可以安全重试。盲目重试可能导致重复的云运行;遵循该标志则不会。
  5. 除非需要环境配置,否则使用
    local: { settingSources: [] }
    (默认值)
    。选择
    "all"
    会从调用者的环境加载项目/用户/团队/MDM设置,这很少是服务所需的。注意:
    settingSources
    位于
    local
    下,而非顶层;它对云agent无效(云agent始终遵循团队/项目/插件设置)。
  6. 对于CI中的云agent,设置
    skipReviewerRequest: true
    — 除非需要通知人工审核,否则这会跳过审核请求步骤,避免PR通知干扰。
  7. 在共享基础设施代码中始终显式传入
    apiKey
    ,不要依赖环境变量。这会让凭据依赖更明显,防止跨租户错误。
  8. 对于真正的一次性任务,优先使用
    Agent.prompt(...)
    — 它会自动清理,更难导致资源泄漏。
带示例的详细版本:参考
references/patterns.md

Observing a Run You Didn't Launch

观察未由你启动的运行

You can inspect any agent/run by ID later:
typescript
// Cloud: IDs that start with "bc-" auto-route to the cloud API
const info = await Agent.get("bc-abc123", { apiKey });
const run = await Agent.getRun(runId, { runtime: "cloud", agentId: "bc-abc123", apiKey });

// Local: you need the cwd where the agent was created
const localInfo = await Agent.list({ runtime: "local", cwd: process.cwd() });
A cloud
bc-
-prefixed agent ID is not a run ID. If you only have a run ID (from a log or a webhook), pass it to
Agent.getRun
with the runtime hint; don't confuse the two.
你可以通过ID稍后检查任何agent/run:
typescript
// 云:以"bc-"开头的ID会自动路由到云API
const info = await Agent.get("bc-abc123", { apiKey });
const run = await Agent.getRun(runId, { runtime: "cloud", agentId: "bc-abc123", apiKey });

// 本地:你需要agent创建时的cwd
const localInfo = await Agent.list({ runtime: "local", cwd: process.cwd() });
云环境中以
bc-
为前缀的agent ID不是运行ID。如果你只有运行ID(来自日志或Webhook),请将其传入
Agent.getRun
并指定运行时提示;不要混淆两者。

Offering a Canvas

提供Canvas

If the user's integration monitors, lists, or visualizes agents — dashboards of active runs, conversation replays, tool-call timelines — offer a Cursor Canvas to render it. If they accept, defer entirely to the
canvas
skill.
如果用户的集成需要监控、列出或可视化agent——如活跃运行仪表板、对话回放、工具调用时间线——可提供Cursor Canvas来渲染。如果用户接受,请完全交由
canvas
技能处理。

What This Skill Doesn't Cover

本技能不涵盖的内容

  • The Cloud Agents REST API (
    /v1/agents/*
    ). If the user needs a non-TS client, the REST API is documented separately at https://cursor.com/docs/cloud-agent/api; check there for current capabilities before assuming parity with the SDK.
  • .cursor/hooks.json
    hooks. Cloud agents execute them but the SDK doesn't manage them; see Cursor's Hooks docs.
  • Private workers / self-hosted cloud. Send users to the Private Workers docs.
  • Python / non-TS SDKs. There is no first-party SDK in other languages at time of writing; REST is the portable option.
  • Cloud Agents REST API(
    /v1/agents/*
    )。如果用户需要非TypeScript客户端,REST API单独记录在https://cursor.com/docs/cloud-agent/api;在假设其与SDK功能一致前,请先检查当前功能。
  • .cursor/hooks.json
    钩子。云agent会执行它们,但SDK不管理它们;请参考Cursor的Hooks文档。
  • 私有工作器/自托管云。请引导用户查看私有工作器文档。
  • Python/非TypeScript SDK。撰写本文时,官方尚未提供其他语言的SDK;REST是可移植的选项。