> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensorlake.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run Cursor Cloud Agents on Tensorlake Sandboxes

> Use Tensorlake sandboxes as the self-hosted machines for Cursor Cloud Agents. Cursor runs the agent loop; every command, file edit, and repo checkout runs in a sandbox you control.

[Cursor Cloud Agents](https://cursor.com/docs/cloud-agent/self-hosted) can run on self-hosted machines. Cursor keeps the agent loop and the model in its cloud. The machine, where commands run, files change, and Cursor checks out repositories, is a Tensorlake sandbox you own.

A small orchestrator claims Cursor requests and gives each one its own worker sandbox. The orchestrator also runs in a Tensorlake sandbox, so nothing stays running on your laptop. When a worker goes idle, its sandbox suspends. A follow-up message resumes the same sandbox with the checkout and caches intact.

```mermaid theme={null}
graph LR
    C["Cursor cloud<br/>agent loop + request queue"]
    O["Orchestrator<br/>one per pool, runs in a Tensorlake sandbox"]
    W["Worker sandbox<br/>one per agent, runs the Cursor agent worker"]

    C -->|"pending requests"| O
    O -->|"create · suspend · resume · start worker"| W
    W -->|"outbound HTTPS"| C
```

## Prerequisites

You need a Cursor Enterprise team, a Tensorlake account, and a local machine with Python and uv.

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 work on.

<Note>
  Without an Enterprise team, a personal key on any plan can run one long-lived worker in one sandbox. See [My Machines in the repo README](https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake#my-machines).
</Note>

Tensorlake:

* An account and API key from [Tensorlake Cloud](https://cloud.tensorlake.ai).
* The `tl` command-line interface (CLI), optional. Install it with `curl -fsSL https://tensorlake.ai/install | sh`. This guide uses it to list sandboxes and read worker logs.

Local machine:

* Python 3.10 or newer and [uv](https://docs.astral.sh/uv/).
* Nothing stays running here after setup.

## Set up Cursor

A Cursor team administrator does this once:

1. Open **Dashboard → Cloud Agents → Self-Hosted**.
2. Enable **Self-hosted Machines**.
3. Enable GitHub token minting for self-hosted pool workers.
4. Give the Cursor GitHub App access to each repository.

## Quickstart

The reference implementation is [tensorlakeai/cursor-cloud-agents-tensorlake](https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake). One command does the whole setup.

```bash theme={null}
git clone https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake
cd cursor-cloud-agents-tensorlake
uv sync --all-extras
uv run cursor-tl-up
```

`cursor-tl-up` asks for the Cursor and Tensorlake keys once and saves them to `.env`. Then it:

1. Checks the Cursor key.
2. Registers the pool.
3. Builds or reuses both images.
4. Launches the orchestrator sandbox.
5. 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](https://cursor.com/agents) under **Remote Machines**. Worker sandbox names are `cursor-` followed by the worker ID.

The command is idempotent: it skips steps that are already done. Run it again to repair a suspended orchestrator sandbox or a dead process.

Useful options:

```bash theme={null}
uv run cursor-tl-up --computer-use    # desktop worker image; workers start with --computer-use
uv run cursor-tl-up --repo-url https://github.com/acme/widgets    # serve one repository only
uv run cursor-tl-up --any-repo        # let Cursor clone after the claim
uv run cursor-tl-up --rebuild         # rebuild the orchestrator image after a code change
```

By default, the pool serves every repository the Cursor GitHub App can reach. [Repositories in the repo README](https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake#repositories) explains the difference between the default, `--repo-url`, and `--any-repo`. It also has the step-by-step version of this setup.

### 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 it resumes and re-checks a suspended orchestrator.

```cron theme={null}
*/15 * * * * cd /path/to/cursor-cloud-agents-tensorlake && uv run cursor-tl-orchestrator-sandbox >/dev/null 2>&1
```

Keep the interval shorter than your plan's idle window.

## Submit a request

Send a task from the Cursor web app or from the API, then watch a worker sandbox pick it up.

1. Open [cursor.com/agents](https://cursor.com/agents).
2. Pick the repository. In `any-repo` mode pick **Any repo** instead.
3. Open the machine picker, choose **Remote Machines**, and pick **tensorlake**.
4. Send the task. In `any-repo` mode name the repository in the prompt.

You can also send a request from the API:

```bash theme={null}
uv run cursor-tl-pool agent "Add a unit test for the parser" --repo https://github.com/acme/widgets
```

Watch the worker start:

```bash theme={null}
tl sbx ls                                                        # a cursor-… sandbox appears
uv run cursor-tl-orchestrator-sandbox --logs                     # claim, spawn, worker start
tl sbx exec cursor-your_worker_id tail -n 50 /var/log/cursor-tl/worker.log
```

After the session ends, the worker waits `WORKER_IDLE_RELEASE_SECS` (default 300s) and exits. The orchestrator then suspends the sandbox. A follow-up message resumes it. The orchestrator terminates a sandbox that stays suspended longer than `SESSION_RETENTION_SECS` (default 1 day).

## Computer use

Cursor agents can drive a desktop and a browser on Linux workers. Run `cursor-tl-up --computer-use`, or set `WORKER_COMPUTER_USE=true` in `.env` before you build the worker image. `cursor-tl-up` then builds the worker image from [`tensorlake/ubuntu-vnc`](/sandboxes/computer-use), 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

Each entry names the symptom, then the cause and the fix.

* **`No self-hosted worker matches the requested labels`.** You sent the request 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, run `uv run cursor-tl-up` again and set up the [keep-alive cron](#keep-the-orchestrator-awake). Then check that the pool name matches `CURSOR_POOL`, that **Self-hosted Machines** is enabled, and that `--logs` shows the controller connected. `uv run cursor-tl-pool pending` lists 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.log` in the worker sandbox. Confirm GitHub token minting is enabled and the GitHub App has access to the repository. HTTPS remotes only.
* **`POST /v1/agents` returns 403 `integration_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](https://cursor.com/dashboard/integrations).
* **A follow-up started 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-timeout` applies only when it creates the pool. Or check `--logs` for a failed resume.
* **A failed spawn left a claimed request.** Run `uv run cursor-tl-pool release your_request_id` so Cursor re-queues it.

More cases, including split orchestrators and idle workers that stay running, are in [Troubleshooting in the repo README](https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake#troubleshooting).

## Next steps

<CardGroup cols={2}>
  <Card title="Reference implementation" icon="github" href="https://github.com/tensorlakeai/cursor-cloud-agents-tensorlake">
    Step-by-step setup, My Machines, operations commands, configuration, and design notes.
  </Card>

  <Card title="Cursor: Self-Hosted Machines" icon="book" href="https://cursor.com/docs/cloud-agent/self-hosted">
    Cursor's own documentation for pools, workers, and the Cloud Agents API.
  </Card>

  <Card title="Sandbox lifecycle" icon="arrows-rotate" href="/sandboxes/lifecycle">
    The suspend and resume model that keeps idle workers cheap.
  </Card>

  <Card title="Computer Use" icon="desktop" href="/sandboxes/computer-use">
    The desktop image that powers `--computer-use` workers.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.