Skip to main content
Cursor Cloud Agents take a task from Cursor, Slack, GitHub, or Linear and come back with a pull request. By default they run on VMs in Cursor’s cloud. Self-Hosted Machines lets you move the part that touches your code, the checkout, the file edits, and the shell commands, onto machines you control. Cursor keeps running the agent loop, the model calls, and the Cloud Agent experience your team already uses. With Self-Hosted Machines you decide which image the agent runs on, what it can reach, and what happens to the workspace when it’s done. A Team Pool also means managing a fleet of machines, and Cursor’s docs are clear about what that involves: keeping enough workers online, patching images, resetting machines between runs, scaling for bursts, and cleaning up after every session. Superserve gives you the control without having to manage a fleet of machines. Point Cursor’s worker controller at the spawn hook in this guide, and every Cloud Agent that lands in your pool gets its own sandbox: created for that request, booted from a template you built, limited to an egress allowlist if you set one, and deleted the moment the worker exits. Follow-ups don’t have to start cold either. A sandbox can pause between turns at no compute cost and resume in under 50ms with the checkout and caches intact, which is the hibernation model Cursor designed pools around. Nothing runs before a request arrives, and nothing lingers after. This is for you if:
  • Security or procurement asked where agent commands run, and you’d rather answer with an image, an egress allowlist, and a per-connection log than with a fleet you operate.
  • Your environment doesn’t fit a Cloud Agent build: a custom base image, a heavy toolchain, or a large checkout you want to keep warm across follow-ups.
  • Agents write a real share of your pull requests now, and idle machines have become the cost problem.
If Cursor-hosted Cloud Agents already meet your requirements, stay there. Cursor recommends them for most teams, and so do we. This guide is for the teams that need a pool.

How it works

  • Cursor runs the agent loop and a per-team queue of pending pool requests. Each worker opens one outbound HTTPS connection to Cursor, and Cursor sends tool calls over it. Nothing connects into your infrastructure.
  • You run Cursor’s agent worker controller on a host you manage, pointed at a spawn hook from this guide. The controller claims requests from the queue and runs the hook once per claim.
  • Superserve provides the workers. The spawn hook creates a sandbox and starts agent worker inside it under the worker id Cursor assigned to the claim. A monitor process recycles the sandbox when the worker exits.
The worker clones the requested repo with a short-lived GitHub token that Cursor mints per run, serves the session, then exits after an idle window.
A reference implementation with the template builder, spawn hook, and monitor is available on GitHub in both TypeScript and Python.

Prerequisites

  • A Superserve account and API key
  • A Cursor Enterprise plan with Self-Hosted Machines enabled by a team admin
  • A Cursor service-account API key. Personal, team, and organization keys cannot start pool workers.
  • A Linux or macOS controller host with the Cursor CLI, outbound HTTPS, and Node.js 22+ or Python 3.12+

Configure your Cursor team

A team admin enables three things in the Cursor dashboard:
  1. Allow Self-Hosted Machines under Cloud Agents → Self-Hosted. This adds the pool picker to Cloud Agent creation.
  2. GitHub token minting for self-hosted workers, on the same page. The worker starts with --clone-git-repos, which asks Cursor for a repo-scoped token at claim time. Without minting, workers connect but cannot check anything out.
  3. The Cursor GitHub App under Settings → Integrations, connected at the team level with access to every repo the pool will serve. Minted tokens inherit their permissions from the app.
Then create a service account under Settings → API Keys → Service Accounts and export its key alongside your Superserve key on the controller host:

Build the worker template

Build a template with the Cursor CLI, git, and a /workspace directory. Sandboxes created from it boot in under 50ms with the CLI already on PATH, so nothing is downloaded at claim time.
Run this once. The template persists in your Superserve account and every worker boots from it. The agent --version step fails the build immediately if the CLI download or install broke, rather than at the first claim.
Add the runtimes, package caches, and internal CA certificates your repos need to the build steps. The snapshot captures the full filesystem, so workers inherit everything with no install cost at claim time.

Run the controller

Clone the reference implementation, add both keys to .env, and build the template:
The controller ships with the Cursor CLI. Install it on the same host:
Start the controller and the monitor as two separate processes. Both run until stopped - keep them under systemd, a container, or your own process manager. The scripts read .env themselves, but the controller is a Cursor binary and does not, so export it into that shell first.
--pool registers the pool with Cursor, so superserve appears in the pool picker as soon as the controller connects. Any name works except default, which does not allow --clone-git-repos.

The spawn hook

The controller runs the hook once per claim with CURSOR_AGENT_WORKER_ID, CURSOR_POOL, CURSOR_REQUEST_ID, and the request’s repo fields in its environment. The hook creates a sandbox tagged with the worker id and launches the worker:
What the hook does on each claim:
  1. Finds or creates a sandbox for the worker id. A paused sandbox with the same tag is resumed rather than recreated (see Hibernate with pause and resume).
  2. Launches the worker detached from the exec call, with CURSOR_AGENT_WORKER_ID in its environment. The Cursor CLI reads the id from there and connects as the worker the controller already claimed for.
  3. Verifies it stayed up. If the worker is not running a few seconds later, the hook prints the worker log, releases the claim so another worker can take the request, deletes the sandbox, and exits non-zero.
Keep SUPERSERVE_API_KEY on the controller host only - it never enters a sandbox. CURSOR_API_KEY does: the worker authenticates to Cursor with it, and the agent’s commands run as the same user as the worker, so anything the worker can read, a task’s commands can read too. That is Cursor’s worker model on every platform. Scope the service account to one pool, and treat the pool as one trust boundary.
Delivering this key as a bound Superserve secret is not offered here yet: the worker’s authentication format has not been verified against the secrets proxy, so the guide ships the key to the worker process as an environment variable.

Send a task

In Cursor, create a Cloud Agent for a repo the GitHub App can access and select the superserve pool. Slack, GitHub, Linear, and the Cloud Agents API can target the pool the same way. A cursor-<worker id> sandbox appears in the console, tagged with the worker, pool, and request ids. Open its terminal to watch the worker:
The worker clones the repo into /workspace, serves the session, and stays connected for follow-ups. Once the idle window closes it exits, and the monitor deletes the sandbox on its next pass.

Idle release and cleanup

A worker serves one request and stays attached to it. After a session ends it keeps its connection open for CURSOR_WORKER_IDLE_RELEASE_TIMEOUT seconds - 600 in this guide, an hour by Cursor’s default - so a follow-up reuses the workspace instead of starting cold. When the timer fires the worker exits with code 0. The monitor sweeps every 15 seconds, finds sandboxes whose worker has exited, and deletes them.

Hibernate with pause and resume

Deleting on idle discards the checkout, the dependency install, and any build cache. A follow-up that arrives an hour later starts from an empty /workspace. Cursor supports hibernation: a pool can declare a reconnect window, and Cursor holds a follow-up for an offline worker instead of reassigning it. Superserve’s pause() fits this directly - it checkpoints the full sandbox - memory, processes, and filesystem - at zero compute cost, and resume() brings it back in under 50ms.
1

Give the pool a reconnect window

Register the pool with workerReadyTimeoutSeconds. Cursor holds a follow-up for up to that long while the worker’s machine comes back:
2

Pause instead of delete

Set CURSOR_WORKER_HIBERNATE=true in .env. The monitor now pauses a sandbox when its worker exits. SANDBOX_AUTO_DELETE_SECONDS still applies, so sandboxes nobody returns to are deleted after a day by default.
3

Wake on follow-up

In hibernate mode the monitor also polls the pool’s pending requests. When Cursor lists a follow-up as claimed by an offline worker and a paused sandbox carries that worker id, the monitor resumes the sandbox and starts a worker under the same id. The follow-up continues on the original workspace.
The spawn hook and the monitor coordinate through sandbox metadata tags (cursor.launching, cursor.recycling), and metadata updates have no compare-and-swap. Each side writes its tag and re-reads before acting, the launch script holds a lock so two launchers can never start two workers, and claims are released only after a worker is confirmed gone. What remains is a window of one API round-trip in which a recycle and a relaunch can overlap; the outcome in that case is a follow-up that Cursor re-queues, never two workers on one request.

Warm workers

For pools where startup latency matters, run the controller with --warm-idle <count>. It keeps that many idle workers connected ahead of demand and Cursor assigns requests to them directly. The same spawn hook serves this mode; it runs without a request id.

Lock down egress

Sandboxes can reach any public IP by default. A worker needs outbound HTTPS to:
  • api2.cursor.sh and api2direct.cursor.sh - the agent session
  • downloads.cursor.com - CLI self-updates
  • cloud-agent-artifacts.s3.us-east-1.amazonaws.com - screenshot and recording uploads
  • The git host, package registries, and any internal services the agent’s work touches
To restrict egress, set CURSOR_WORKER_ALLOW_OUT to a comma-separated list of hosts and CIDRs. The spawn hook creates sandboxes that allow those, plus the sandbox’s DNS resolvers (1.1.1.1/32 and 8.8.8.8/32, without which nothing resolves) and *.superserve.ai (which the SDK needs to reach the sandbox), and deny everything else. Write single IPs as /32; the hook does this for you if you leave the suffix off. See Network rules for the format and the network log for every HTTP and HTTPS connection a worker attempted, allowed or blocked. No inbound ports are required. The worker connects out to Cursor, and Superserve reaches the sandbox through its own control plane.
Git access comes from tokens Cursor mints per run. There is no personal access token in .env, in the template, or in the sandbox. Use a dedicated service account per pool so a compromised worker can only claim that pool’s work.

Configuration

The scripts read these from .env: The controller sets CURSOR_AGENT_WORKER_ID, CURSOR_REQUEST_ID, and CURSOR_WORKER_NAME on each spawn. Leave them out of .env.

Troubleshooting

Check that the controller is running, that its --pool matches the pool users select, and that CURSOR_API_KEY is a service-account key. The controller logs every claim and spawn; a silent log means it is not seeing requests.
Read the log tail it printed. Common causes: a key of the wrong type, --clone-git-repos without GitHub token minting enabled, or the default pool. To run workers that do not clone, set CURSOR_WORKER_CLONE_GIT_REPOS=false.
The build VM could not fetch the CLI from downloads.cursor.com, or the installed binary did not run on the base image. Stream the build logs to see which.
The monitor is not running. Every sandbox the hook creates carries cursor.managed=true in its metadata, so Sandbox.list({ metadata: { "cursor.managed": "true" } }) finds them all.
All three pieces are required: the pool registered with workerReadyTimeoutSeconds, CURSOR_WORKER_HIBERNATE=true, and the monitor running with CURSOR_API_KEY and CURSOR_POOL in its .env.

Resources

Reference implementation

Template builder, spawn hook, and monitor in TypeScript and Python.

Cursor Team Pools

Pools, the worker controller, hibernation, and the pending-request API.

Templates

Build reusable images with your toolchains baked in.

Pause, resume, and delete

Checkpoint a sandbox between turns and restore it on demand.