Why Tensorlake
- Suspend and resume. A worker sandbox suspends when the agent goes idle and resumes in about a second when a follow-up arrives. Memory, filesystem, and the repository checkout stay intact. You do not pay for idle machines and the agent does not wait for a cold start.
- One sandbox per agent. Each request gets its own microVM. Agents cannot see each other’s code or credentials.
- No inbound ports. Workers connect out to Cursor over HTTPS. Nothing listens on the sandbox.
- Egress control. Set an allowlist so a worker can reach only Cursor and your git host.
- Desktop workers. Build the worker image from
tensorlake/ubuntu-vncand the agent can drive a browser and a desktop. See Computer use.
Prerequisites
Cursor:- A Cursor Enterprise team. Cursor offers self-hosted pools only on Enterprise.
- A service-account API key from Dashboard → Settings → API Keys → Service Accounts. Pool workers reject personal and team keys.
- A team administrator who can enable self-hosted machines and GitHub token minting.
- The Cursor GitHub App connected at the team level, with access to each repository the agents will work on.
No Enterprise team? A personal key on any plan can run one long-lived worker in one sandbox. See My Machines in the repo README.
- An account and API key from cloud.tensorlake.ai.
- The
tlCLI, optional:curl -fsSL https://tensorlake.ai/install | sh. This guide uses it to list sandboxes and read worker logs.
- Python 3.10 or newer and uv.
- Nothing stays running here after setup.
Set up Cursor
A Cursor team administrator does this once:- Open Dashboard → Cloud Agents → Self-Hosted.
- Enable Self-hosted Machines.
- Enable GitHub token minting for self-hosted pool workers.
- Give the Cursor GitHub App access to each repository.
Quickstart
The reference implementation is tensorlakeai/cursor-cloud-agents-tensorlake. One command does the whole setup.cursor-tl-up asks for the Cursor and Tensorlake keys once and saves them to .env. Then it checks the Cursor key, registers the pool, builds or reuses both images, launches the orchestrator sandbox, and waits until the controller reports watching.
The pool is a Cursor Team Pool: the queue that self-hosted workers serve. Its name comes from CURSOR_POOL, default tensorlake. This is the name you pick at cursor.com/agents under Remote Machines. Worker sandboxes are named cursor-<worker-id>.
The command is idempotent. Run it again to repair a suspended orchestrator sandbox or a dead process. It skips steps that are already done.
Useful options:
--repo-url, and --any-repo, and for the step-by-step version of this setup, see Repositories in the repo README.
Keep the orchestrator awake
The orchestrator sandbox has no idle timeout of its own, but Tensorlake suspends a named sandbox after your plan’s maximum idle window. A suspended orchestrator cannot claim requests. Schedule the launcher on an always-on machine so a suspended orchestrator is resumed and re-checked. The command is idempotent.Submit a request
- Open cursor.com/agents.
- Pick the repository. In
any-repomode pick Any repo instead. - Open the machine picker, choose Remote Machines, and pick tensorlake.
- Send the task. In
any-repomode name the repository in the prompt.
WORKER_IDLE_RELEASE_SECS (default 300 seconds) and exits. The orchestrator then suspends the sandbox. A follow-up message resumes it. A sandbox suspended for longer than SESSION_RETENTION_SECS (default one day) is terminated.
Computer use
Cursor agents can drive a desktop and a browser on Linux workers. Runcursor-tl-up --computer-use, or set WORKER_COMPUTER_USE=true in .env before you build the worker image. The worker image is then built from tensorlake/ubuntu-vnc and each worker starts with --computer-use. No inbound port opens.
Set WORKER_SHARE_DESKTOP=view or view_and_control to let authorized viewers watch the agent desktop from Cursor.
Test it with a task such as “open a browser, visit example.com, and take a screenshot”. Desktop workers need at least 4096 MB of memory, which is the default SANDBOX_MEMORY_MB.
Troubleshooting
- “No self-hosted worker matches the requested labels”. The request was sent to the Any repo row, and the pool runs in default mode. Pick the repository in the web picker instead, or start the pool with
--any-repo. - Request stays queued. Run
uv run cursor-tl-orchestrator-sandbox --status. If the sandbox is suspended, runuv run cursor-tl-upagain and set up the keep-alive cron. Then check that the pool name matchesCURSOR_POOL, that Self-hosted Machines is enabled, and that--logsshows the controller connected.uv run cursor-tl-pool pendinglists what Cursor is waiting on. - Controller rejects the key. Only an Enterprise service-account key starts pool workers. A personal key works only with My Machines.
- Workspace is empty after a run. Read
/var/log/cursor-tl/checkout.login the worker sandbox. Confirm GitHub token minting is enabled and the GitHub App has access to the repository. HTTPS remotes only. POST /v1/agentsreturns 403integration_not_connected. The request named a repository, and the Cursor GitHub integration is not connected to the team. A team admin connects it at cursor.com/dashboard/integrations.- A follow-up landed on a new sandbox. The reconnect window lapsed. Raise it with
uv run cursor-tl-pool register --ready-timeout 1800, which updates the existing pool.cursor-tl-up --ready-timeoutapplies only when it creates the pool. Or check--logsfor a failed resume. - A failed spawn left a claimed request. Run
uv run cursor-tl-pool release <request-id>so Cursor re-queues it.
Next steps
Reference implementation
Step-by-step setup, My Machines, operations commands, configuration, and design notes.
Cursor: Self-Hosted Machines
Cursor’s own documentation for pools, workers, and the Cloud Agents API.
Sandbox lifecycle
The suspend and resume model that keeps idle workers cheap.
Computer Use
The desktop image that powers
--computer-use workers.