# Setting up the Cursor TypeScript SDK: Agent.prompt, Agent.create, and Agent.resume Patterns

> Learn to set up the Cursor TypeScript SDK using Agent.prompt, Agent.create, and Agent.resume patterns. Embed Cursor agents into CI or background jobs seamlessly.

- Repository: [Cursor/plugins](https://github.com/cursor/plugins)
- Tags: getting-started
- Published: 2026-05-25

---

**The Cursor TypeScript SDK (`@cursor/sdk`) provides three canonical patterns—`Agent.prompt` for one-shot scripts, `Agent.create` for multi-turn interactions, and `Agent.resume` for reconnecting to persisted agents—enabling developers to embed Cursor agents into everything from CI pipelines to background jobs.**

The `@cursor/sdk` package in the `cursor/plugins` repository offers programmatic control over Cursor agents through these distinct execution models. Each pattern targets specific operational requirements, from ephemeral automation tasks to durable conversations that survive process restarts.

## The Three Execution Patterns

### Agent.prompt for One-Shot Tasks

**`Agent.prompt(...)`** creates a temporary agent, executes a single prompt, and automatically disposes of resources. This pattern is ideal for CI steps, GitHub Actions, or simple CLI commands where you need a result and immediate exit without managing lifecycle cleanup.

According to [`cursor-sdk/skills/cursor-sdk/SKILL.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/SKILL.md) (lines 55-66), this method accepts a prompt string and options, returning a `RunResult` directly:

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

(async () => {
  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("Status:", result.status);
  console.log("Output:", result.result);
})();

```

### Agent.create for Durable Conversations

**`Agent.create(...)`** returns a persistent `Agent` object that maintains conversation state across multiple turns. Unlike `Agent.prompt`, this pattern requires manual resource cleanup via `await agent[Symbol.asyncDispose]()` to prevent leaks.

The implementation in [`orchestrate/skills/orchestrate/scripts/cli/task.ts`](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/cli/task.ts) (around line 170) demonstrates this pattern in production use. The agent supports real-time streaming via `run.stream()` and final resolution via `run.wait()`:

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

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

  try {
    // First turn with streaming
    const run1 = await agent.send("Find the bug in src/auth.ts");
    for await (const ev of run1.stream()) {
      if (ev.type === "assistant") {
        for (const blk of ev.message.content) {
          if (blk.type === "text") process.stdout.write(blk.text);
        }
      }
    }
    const result1 = await run1.wait();
    console.log("First turn status:", result1.status);

    // Follow-up turn preserves conversation context
    const run2 = await agent.send("Now write a regression test for the bug");
    await run2.wait();
  } finally {
    // Prevent resource leaks
    await agent[Symbol.asyncDispose]();
  }
})();

```

### Agent.resume for Process Resumption

**`Agent.resume(...)`** reconnects to a previously persisted agent using its ID. This pattern supports cron jobs, webhooks, or CLI restarts where the original process no longer exists. Note that MCP servers are not persisted and must be passed again in the options.

As documented in [`cursor-sdk/skills/cursor-sdk/SKILL.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/SKILL.md) (lines 102-112):

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

(async () => {
  // previousAgentId is persisted somewhere (DB, file, env, etc.)
  const previousAgentId = "agent-1234abcd";

  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 for the latest release");
  const final = await run.wait();
  console.log("Resume run status:", final.status);
})();

```

The file [`orchestrate/skills/orchestrate/scripts/core/agent-manager.ts`](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/core/agent-manager.ts) (lines 89-95) demonstrates the lazy import pattern used when loading the SDK for these operations.

## Runtime Configuration and Architecture

All three patterns share a common options shape but differ in runtime behavior. The SDK examines the supplied configuration to determine whether to execute **locally** (on the caller's machine) or **in the cloud** (Cursor-hosted VM):

- **`local: { cwd: ... }`**: Pins execution to the current working directory
- **`cloud: { repos: [...] }`**: Forces cloud execution with specific repository access  
- **Omitting both**: Defaults to local execution silently

See [`cursor-sdk/skills/cursor-sdk/references/runtime-choice.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/references/runtime-choice.md) for the complete decision matrix.

## Run Lifecycle and Streaming Control

A `Run` represents a single prompt execution within an agent session. Each run provides:

- **`run.stream()`**: Yields events (`assistant`, `tool_call`, etc.) for live output processing
- **`run.wait()`**: Resolves to the final `RunResult` containing status, output, and errors  
- **`run.supports(op)`**: Guards optional operations like `run.cancel()` or `run.conversation()`, which may be unavailable on certain runtimes (e.g., paused cloud runs)

Always call `wait()` after streaming to release internal watchers and determine final completion status.

## Error Handling and Resource Management

The SDK distinguishes between two error domains:

1. **Startup failures** (`CursorAgentError`): Thrown before any run starts (e.g., missing API key, invalid configuration). These are catchable at the `Agent.create` or `Agent.prompt` level.
2. **Runtime failures**: Indicated by `result.status === "error"` after `run.wait()` completes—the agent started but encountered issues like tool failures or model errors.

As shown in [`cursor-sdk/skills/cursor-sdk/SKILL.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/SKILL.md) (lines 124-142), handle both domains separately:

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

(async () => {
  let agent;
  try {
    agent = Agent.create({ apiKey: process.env.CURSOR_API_KEY! });
    const run = await agent.send("Summarize the repo");
    const res = await run.wait();
    
    if (res.status === "error") {
      console.error("Run failed:", res.error?.message);
      // Inspect res.transcript, tool outputs, etc.
    } else {
      console.log("Summary:", res.result);
    }
  } catch (err) {
    if (err instanceof CursorAgentError) {
      console.error("Startup error:", err.message, "Retryable:", err.isRetryable);
    } else {
      throw err;
    }
  } finally {
    if (agent) await agent[Symbol.asyncDispose]();
  }
})();

```

## Common Pitfalls and Best Practices

Based on the "Top Five Traps" documented in [`cursor-sdk/skills/cursor-sdk/SKILL.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/SKILL.md) and [`references/error-handling.md`](https://github.com/cursor/plugins/blob/main/references/error-handling.md):

- **Always specify runtime config**: Explicitly pass `local` or `cloud` to avoid silent local fallbacks
- **Never forget disposal**: Wrap `Agent.create` and `Agent.resume` in `try ... finally` blocks, or use `await using` syntax if your TypeScript target supports it
- **Distinguish error types**: Catch `CursorAgentError` for startup issues; inspect `result.status` for runtime problems  
- **Stream with wait**: Always call `run.wait()` after streaming to release internal resources
- **Check capability support**: Use `run.supports(op)` before calling `run.cancel()` or similar optional methods that may be unavailable on paused cloud runs

## Summary

- **`Agent.prompt`** handles one-shot tasks with automatic cleanup—perfect for CI/CD pipelines and simple scripts
- **`Agent.create`** enables stateful, multi-turn conversations but requires manual disposal via `Symbol.asyncDispose`  
- **`Agent.resume`** reconnects to persisted agents by ID, supporting durable workflows across process restarts
- **Runtime choice** between local and cloud execution depends on the `local` or `cloud` options passed to any pattern
- **Error handling** requires catching `CursorAgentError` for startup failures and checking `result.status` for runtime issues
- **Resource management** demands explicit disposal for created/resumed agents to prevent file handle and socket leaks

## Frequently Asked Questions

### What is the difference between Agent.prompt and Agent.create?

**`Agent.prompt`** creates a temporary agent instance that automatically disposes after returning the result, making it ideal for one-shot tasks. **`Agent.create`** returns a persistent agent that maintains conversation context across multiple `send()` calls but requires manual cleanup via `await agent[Symbol.asyncDispose]()`. Use `Agent.prompt` for scripts and `Agent.create` for interactive or multi-step workflows.

### How do I prevent resource leaks when using the Cursor SDK?

Always wrap `Agent.create` or `Agent.resume` calls in a `try ... finally` block to ensure `await agent[Symbol.asyncDispose]()` runs. Alternatively, use the `await using` syntax if your TypeScript configuration supports it. Forgetting disposal leaks file handles, child processes, and network sockets, as noted in [`cursor-sdk/skills/cursor-sdk/SKILL.md`](https://github.com/cursor/plugins/blob/main/cursor-sdk/skills/cursor-sdk/SKILL.md).

### Can I resume an agent after my process restarts?

Yes. Persist the `agentId` returned when creating an agent, then use **`Agent.resume(agentId, options)`** to reconnect. Note that MCP servers and runtime configuration must be passed again during resume, as they are not persisted with the agent state. This pattern supports cron jobs, webhooks, and CLI tools that need to continue conversations across restarts.

### How do I handle errors correctly in the Cursor TypeScript SDK?

Distinguish between **startup errors** (`CursorAgentError`) thrown during agent initialization, and **runtime errors** indicated by `result.status === "error"` after `run.wait()` returns. Catch `CursorAgentError` for configuration issues like missing API keys. For runtime errors, inspect the `result.error` and `result.transcript` properties to diagnose tool failures or model issues.