# Running on workbenches.dev

A cloud run executes one Workbench version in a fresh Daytona sandbox on workbenches.dev, or on one of your organization's [workers](/docs/workers/setup), and records everything it does as normalized events. You start it from a coding agent through `mcp.workbenches.dev`, or with the API. You follow and steer it from the agent, the API, or its run page in the dashboard.

Local runs with the CLI are a separate thing: they run on your machine and are never metered.

## What a sandbox run needs

These rules are for runs in a hosted sandbox. A run on a [worker](/docs/workers/setup) needs a worker that offers one of the Workbench's runtimes, and the secrets the Workbench requires. It can use any runner, a local-only Workbench, and members' own sign-ins, and it spends no sandbox time.

1. **A sandboxed Workbench.** Its manifest declares a runtime with an image: `runtimes.daytona.image`, or a `docker` image the sandbox falls back to. A local-only Workbench can be published, and can run on a worker's `local` runtime, but not in a cloud sandbox: `POST /v1/runs` returns 409 `This Workbench runs locally only. Install it with wb add <ref> and run it with the wb CLI.`
2. **A supported runner in the image.** OpenCode, Pi, and Claude Code all run on Daytona. Claude Code requires version 2.1.318 or newer. Pi supports native extension questions but has no permission protocol.
3. **An OpenRouter route.** Its model allows OpenRouter: an `openrouter/` model ID or a declared `openrouter` route.
4. **Secrets.** The organization has an `OPENROUTER_API_KEY` secret, and a secret of the same name for every other `env` entry the manifest marks required. See [Organization secrets](/docs/cloud/secrets).
5. **A payment method and sandbox time.** A payment method must be on file before any cloud run, even within the included hours. See [Sandbox time and plans](/docs/cloud/plans).

A run that breaks a rule fails with the reason as its `terminal_reason`, before any sandbox exists. Model tokens in a sandbox are always your organization's own, on your OpenRouter key.

### Preflight reasons

These are the reasons a cloud run fails before a sandbox exists, checked in this order:

| Rule                                                                                     | `terminal_reason`                                                                                         |
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| The Daytona class, when declared, is `linux`.                                            | `class <class> is not available yet`                                                                      |
| `requirements.os`, when declared, includes `linux`.                                      | `The workbench requires <os>, and sandboxes run linux`                                                    |
| `requirements.arch`, when declared, includes `x64`.                                      | `The workbench requires <arch>, and sandboxes run x64`                                                    |
| `requirements.gpu` is not `true`.                                                        | `GPU sandboxes are not available yet`                                                                     |
| The model allows OpenRouter.                                                             | `Cloud runs use OpenRouter. The model must be an openrouter/ id or declare an openrouter route.`          |
| A published image is declared on `runtimes.daytona` or, failing that, `runtimes.docker`. | `The workbench declares no image for a sandbox. Declare runtimes.daytona.image or runtimes.docker.image.` |
| The image is a published name, not a build.                                              | `Image builds are not supported in cloud runs yet. Publish the image and reference it by name.`           |
| The organization has `OPENROUTER_API_KEY`.                                               | `The organization has no OPENROUTER_API_KEY secret. Set it in the organization settings.`                 |
| Every required `env` name has a secret.                                                  | `The workbench requires <NAME>, and the organization has no secret with that name`                        |

The sandbox runs the image from `runtimes.daytona.image`, or from `runtimes.docker.image` when the Daytona entry has none. An image declared only for `e2b` does not run in the cloud.

The `search` MCP tool returns only Workbenches that run in the cloud unless you pass `runnable: "any"`, and `POST /v1/searches` takes the same `runnable` filter.

## Start a run

From a coding agent connected to `mcp.workbenches.dev`:

```json
{
    "tool": "run",
    "arguments": {
        "workbench": "acme/code-review",
        "task": "Review the open migration and open a draft pull request with fixes.",
        "repository": "acme/api",
        "ref": "main"
    }
}
```

With the API:

```sh
curl https://api.workbenches.dev/v1/runs \
  -H "Authorization: Bearer $WORKBENCHES_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workbench": "acme/code-review",
    "task": "Review the open migration and open a draft pull request with fixes.",
    "workspace": { "repository": "acme/api", "ref": "main" },
    "idempotency_key": "review-2026-10-28"
  }'
```

`workbench` is `organization/name`, which runs the latest version, or `{ "version_id": "<uuid>" }` for one exact version. Internal Workbenches resolve only for their own organization. Runs belong to the organization that starts them, never to the publisher of the Workbench. The full request is on [Runs](/docs/api/runs).

## Time limit

A run stops after `max_minutes`, a whole number from 1 to 1440 (24 hours). The default is 60. The limit is part of the request, never of the manifest. Your organization's remaining sandbox time caps it further: a longer request is refused with 402 `plan_limit` naming the minutes requested and available.

The agent is told the absolute time the run stops, such as `This run stops at 2026-10-13 14:05 UTC.` A run past its deadline fails with `The run exceeded its N minute limit and timed out`.

## Run states

A run moves through `queued`, `provisioning`, `starting`, `running`, `needs_input`, `completing`, and one of `completed`, `failed`, or `cancelled`. Status is derived from the run's events.

## Follow and steer

- **The dashboard.** Each run has a page under your organization's runs, with its live timeline, usage, returned files, changes, pull request, and previews. You can send messages, answer questions and permissions, and cancel from it.
- **MCP.** `wait`, `send`, `answer`, `cancel`, `changes`. See [The run loop](/docs/mcp/loop).
- **The API.** `GET /v1/runs/:id/events` as JSON or a WebSocket, and `POST /v1/runs/:id/commands`. See [Events](/docs/api/events) and [Commands](/docs/api/commands).

Continuing a session in the cloud is not supported yet: a run with `session_id` fails with that reason. Start a new run, and name the same `branch` to carry on a pull request.

## What a run returns

- **Files.** Each sandbox has an outbox at `/outbox`, named to the runner as `WORKBENCH_OUTPUT_DIR`. Every file the run writes there is returned, with an optional `outcome.json` naming them. Outcomes larger than 50 MB are not kept: collection stops at the first file that would pass the limit.
- **Changes.** A repository run's patch, as a changeset in the outcome and as `text/x-diff` from `GET /v1/runs/:id/changes`. Patches over 10 MB are not kept.
- **A pull request**, when the agent opened one. See [Repositories and pull requests](/docs/cloud/repositories).
- **The final response, usage, and status** on the run.

## Secrets never land in history

Before a runner event or outcome file is stored, every value injected into the sandbox is replaced with `[redacted]`: the organization secrets the run received, the runner's password, the image pull token, and the run's GitHub credential. Values are matched exactly and in their JSON-escaped form; values shorter than eight characters are left alone. A runner that encodes, splits, or reformats a value defeats exact matching.

## Reliability

Each run has one coordinating process on workbenches.dev. If it restarts, it adopts the sandbox and restores saved runner progress atomically with the recorded events. OpenCode resumes through its native HTTP session; Claude Code and Pi attach to their running command and replay only output not yet stored. Recovery requires that the sandbox, command, and logs still exist. A lost sandbox or command fails the run. Daytona destroys the sandbox after the run's lease in any case: the time limit plus 15 minutes for collection and teardown.

## Images from this registry

An internal image in `images.workbenches.dev` is pulled with a short-lived pull token for the run's own organization only. Another organization's internal image fails the run. See [Publishing](/docs/authoring/publishing#publish-an-image).
