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

# 샌드박스에서 Devin Outposts 실행하기

> Devin은 Devin Cloud에서 작업을 계획하고, 명령어는 사용자가 직접 제어하는 CoreWeave 샌드박스에서 실행하세요.

[Devin Outposts](https://docs.devin.ai/cloud/outposts/overview) keep Devin's planning and model inference in Devin Cloud. Devin runs commands, edits files, and accesses repositories on a machine you operate. This guide makes that machine a CoreWeave sandbox: an isolated environment with the image, CPU, memory, GPU, and lifetime you choose.

An outpost is a named queue in Devin Cloud. A worker is the `devin worker` process that connects to Devin Cloud over outbound HTTPS, claims sessions from the queue, and runs them locally. It doesn't require inbound ports, a public IP address, or a virtual private network (VPN). Here, one sandbox runs one worker, and that worker serves sessions one after another for as long as the sandbox lives.

Each worker serves one active session at a time. Additional sessions wait until a worker becomes available. This guide starts a fixed number of workers. It doesn't create more sandboxes when sessions queue. Start more workers manually or use an orchestrator to provision them automatically.

## Prerequisites

Before you begin, make sure you have the following:

* Outposts가 활성화된 Devin 조직이 필요합니다. Devin Cloud의 **Settings > Environment**에 **Outposts**가 표시되지 않으면 Devin Admin에게 문의하세요.
* [W\&B API 키](https://forge.coreweave.com/settings#apikeys)가 필요합니다. 이 예시에서는 W\&B 인증을 사용합니다.
* SDK(소프트웨어 개발 키트)를 직접 사용하려면 [`uv`](https://docs.astral.sh/uv/)가 설치된 Python 3.11 이상 또는 Node.js 22 이상이 필요합니다.

이 가이드를 진행할 터미널에서 W\&B API 키를 export하세요. `cws-agent`가 W\&B 인증을 선택하도록 설정된 CoreWeave 토큰은 모두 unset하세요.

```bash theme={"system"}
export WANDB_API_KEY="[WANDB-API-KEY]"
unset CWSANDBOX_API_KEY
```

## Create an outpost in Devin Cloud

To create an outpost and get its token, follow these steps:

1. In [Devin Cloud](https://app.devin.ai), go to **Settings > Environment > Outposts**.
2. Click **Create Outpost**, enter a name, and select **Linux**.
3. Copy the outpost token. Devin Cloud shows it once.

With the outpost ready, choose either `cws-agent` or the Sandbox SDK to start its worker, then run the verification session.

## Quick start with cws-agent

[`cws-agent` 설치 안내](https://github.com/coreweave/cws-agent#install)에 따라 설치하세요. 이 도구는 [파일 시스템 스냅샷](/products/sandboxes/serverless/file-system-snapshots#start-a-sandbox-with-a-snapshot-mount)으로 워크스페이스를 저장하고 복원하는 데 사용할 스냅샷 볼륨을 설정합니다.

Replace `[OUTPOST-TOKEN]` with the token you copied, `[OUTPOST-NAME]` with your outpost name, and `[SANDBOX-NAME]` with a `cws-agent` session name for this sandbox. For the session name, use 1 to 40 lowercase letters, digits, or hyphens, starting with a letter or digit:

```bash theme={"system"}
export DEVIN_OUTPOSTS_TOKEN="[OUTPOST-TOKEN]"
cws-agent launch [SANDBOX-NAME] --outpost [OUTPOST-NAME]
```

The tool passes the token into the sandbox and starts one worker.

To view the worker's terminal, run:

```bash theme={"system"}
cws-agent connect [SANDBOX-NAME] --cmd 'tmux attach -t outpost-0'
```

Detach with **Ctrl-b**, then **d**, and continue to [Run and verify a Devin session](#run-and-verify-a-devin-session). This worker connects to Devin Cloud. It's separate from the interactive Devin command-line interface (CLI) launched with `--agent devin`.

## Set up with the Sandbox SDK

Use this alternative to launch a worker directly, without `cws-agent`. It doesn't configure persistent storage.

Run Python snippets in the virtual environment created in [Configure credentials and install the client](#configure-credentials-and-install-the-client). Save TypeScript snippets as `.mts` files in the project where you install the client, then run them with `npx tsx [FILENAME].mts`.

### Configure credentials and install the client

Export the token you copied when creating the outpost in the terminal where you run the script:

```bash theme={"system"}
export DEVIN_OUTPOSTS_TOKEN="[OUTPOST-TOKEN]"
```

Choose a client and install it locally:

<Tabs>
  <Tab title="Python">
    Python 3.11 이상과 `uv`를 사용하세요.

    ```bash theme={"system"}
    uv venv --python 3.11
    source .venv/bin/activate
    uv pip install 'cwsandbox[wandb]>=1.14.2'
    ```
  </Tab>

  <Tab title="TypeScript">
    Node.js 22 이상을 사용하세요. 프로젝트에 클라이언트와 TypeScript 러너를 설치하세요.

    ```bash theme={"system"}
    npm install @coreweave/cwsandbox@0.5.0-beta.0 tsx
    ```
  </Tab>
</Tabs>

### Start the worker

<Tip>
  To reduce worker startup time, use your own image with the Devin CLI, Git, language runtimes, and project dependencies preinstalled. Set `container_image` in Python or `containerImage` in TypeScript to that image. If it already includes Git and certificate authority (CA) certificates, remove the `apt-get` commands from the example.
</Tip>

The following script creates a sandbox from Cognition's official worker image and runs `devin worker` as the sandbox's main command. The client reads `DEVIN_OUTPOSTS_TOKEN` from your local environment and passes its value in the sandbox request to set the worker's environment variable. The worker's output becomes the sandbox log. If the worker exits with an error, the platform restarts the container up to a retry limit.

<Tabs>
  <Tab title="Python">
    ```python title="start_outpost_worker.py" theme={"system"}
    import os
    import sys

    from cwsandbox import AuthStrategy, ResourceOptions, Sandbox

    outpost = sys.argv[1]

    # 워커 이미지에는 Devin CLI가 포함되어 있지만, Devin이 저장소를 복제할 때
    # 필요한 git은 없습니다. git을 설치한 다음 프로세스를 워커로 넘깁니다.
    command = """
    apt-get update -qq
    DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git ca-certificates >/dev/null
    mkdir -p /workspace
    cd /workspace
    exec devin worker start --outpost="$DEVIN_OUTPOST"
    """

    sandbox = Sandbox.run(
        "bash", "-ec", command,
        auth=AuthStrategy.WANDB,
        container_image="public.ecr.aws/e0h8a4b6/devin-cli:stable",
        environment_variables={
            "DEVIN_OUTPOSTS_TOKEN": os.environ["DEVIN_OUTPOSTS_TOKEN"],
            "DEVIN_OUTPOST": outpost,
        },
        max_lifetime_seconds=8 * 3600,
        resources=ResourceOptions(
            requests={"cpu": "2", "memory": "4Gi"},
            limits={"cpu": "2", "memory": "4Gi"},
        ),
        tags=["devin-outpost-worker"],
    )
    try:
        sandbox.wait()
    except BaseException:
        sandbox.stop().result()
        raise

    print(f"Worker sandbox ID: {sandbox.sandbox_id}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript title="start_outpost_worker.mts" theme={"system"}
    import { createSandboxClientFromEnv } from "@coreweave/cwsandbox/wandb";

    const token = process.env.DEVIN_OUTPOSTS_TOKEN;
    if (!token) throw new Error("Set DEVIN_OUTPOSTS_TOKEN.");
    const outpost = process.argv[2];
    if (!outpost) throw new Error("Pass an outpost name.");

    const command = `
    apt-get update -qq
    DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git ca-certificates >/dev/null
    mkdir -p /workspace
    cd /workspace
    exec devin worker start --outpost="$DEVIN_OUTPOST"
    `;

    const client = createSandboxClientFromEnv();
    const sandbox = await client.run(["bash", "-ec", command], {
      containerImage: "public.ecr.aws/e0h8a4b6/devin-cli:stable",
      environmentVariables: {
        DEVIN_OUTPOSTS_TOKEN: token,
        DEVIN_OUTPOST: outpost,
      },
      resources: { cpu: "2", memory: "4Gi" },
      maxLifetimeSeconds: 8 * 3600,
      waitUntilRunning: false,
      tags: ["devin-outpost-worker"],
    });
    try {
      await sandbox.wait();
    } catch (error) {
      await sandbox.stop();
      throw error;
    }
    console.log(`Worker sandbox ID: ${sandbox.sandboxId}`);
    ```
  </Tab>
</Tabs>

Run it with the outpost name from [Create an outpost in Devin Cloud](#create-an-outpost-in-devin-cloud):

<Tabs>
  <Tab title="Python">
    ```bash theme={"system"}
    python start_outpost_worker.py [OUTPOST-NAME]
    ```
  </Tab>

  <Tab title="TypeScript">
    ```bash theme={"system"}
    npx tsx start_outpost_worker.mts [OUTPOST-NAME]
    ```
  </Tab>
</Tabs>

In Python, `sandbox.wait()` returns when the sandbox is running or has already completed. Installation and worker authentication can still be in progress, so check the worker before submitting a task. The worker starts from `/workspace`. A session for `your-org/app` checks out its repository under `/workspace/repos/app`.

The script doesn't use a `with` block, so a running sandbox continues after the script exits.

<Warning>
  `max_lifetime_seconds` is a hard cap that can't be extended later. When it expires, the platform terminates the sandbox, interrupting execution for any session using the worker. This script configures no snapshot or persistent volume. A container restart resets its writable filesystem, including files under `/workspace`. Keep results outside the sandbox, such as in a repository Devin pushes to.
</Warning>

<h3 id="optional-use-a-secret-store">
  선택 사항: 시크릿 저장소 사용
</h3>

outpost 토큰 값 대신 [W\&B 시크릿 참조](/ko/products/sandboxes/serverless/secrets)를 전달할 수 있습니다. SDK 예시는 이미 W\&B 인증을 사용하도록 설정되어 있습니다. 토큰을 담당 W\&B 팀의 Secret Manager에 저장하고, 해당 팀이 기본 entity가 아니라면 `WANDB_ENTITY`로 그 팀을 지정하세요.

`[SECRET-NAME]`을 팀 시크릿의 이름으로 바꾸세요.

<Tabs>
  <Tab title="Python">
    `cwsandbox`에서 `Secret`을 임포트하고, `environment_variables`에서 `DEVIN_OUTPOSTS_TOKEN`을 제거한 다음, `Sandbox.run()`에 `secrets=[Secret(store="wandb", name="[SECRET-NAME]", env_var="DEVIN_OUTPOSTS_TOKEN")]`를 추가하세요.
  </Tab>

  <Tab title="TypeScript">
    `const token` 선언과 해당 `if (!token)` 검사를 제거하세요. `environmentVariables`에서 `DEVIN_OUTPOSTS_TOKEN`을 제거하고, `client.run()`에 전달하는 옵션에 `secrets: [{ store: "wandb", name: "[SECRET-NAME]", envVar: "DEVIN_OUTPOSTS_TOKEN" }]`를 추가하세요.
  </Tab>
</Tabs>

이제 outpost 토큰을 로컬에서 export하지 않아도 됩니다. 플랫폼이 참조를 확인한 뒤 워커의 환경 변수를 설정합니다.

## Run and verify a Devin session

Use an outpost with only this worker and no other queued or active sessions for the test. Choose a unique, non-secret value for this test and replace `[PROOF-VALUE]` in the following task. In Devin Cloud, start a new session and select your outpost under **Configuration > Virtual environment**. Submit the following task, beginning with `Write the exact text`. Or, in Slack, send the full message:

```text theme={"system"}
@Devin !outpost [OUTPOST-NAME] Write the exact text [PROOF-VALUE] to /workspace/outpost-proof.txt and read the file back. Report its contents.
```

After Devin reports completion, read the file from your own terminal using the command for your setup. Replace `[SANDBOX-NAME]` with your `cws-agent` workspace name or `[SANDBOX-ID]` with the ID printed by the SDK script:

<Tabs>
  <Tab title="cws-agent">
    ```bash theme={"system"}
    cws-agent exec [SANDBOX-NAME] 'cat /workspace/outpost-proof.txt'
    ```
  </Tab>

  <Tab title="Sandbox SDK">
    <Tabs>
      <Tab title="Python">
        ```python theme={"system"}
        from cwsandbox import AuthStrategy, Sandbox

        sandbox = Sandbox.from_id("[SANDBOX-ID]", auth=AuthStrategy.WANDB).result()
        result = sandbox.exec(["cat", "/workspace/outpost-proof.txt"], check=True).result()
        print(result.stdout, end="")
        ```
      </Tab>

      <Tab title="TypeScript">
        ```typescript theme={"system"}
        import { createSandboxClientFromEnv } from "@coreweave/cwsandbox/wandb";

        const client = createSandboxClientFromEnv();
        const sandbox = await client.fromId("[SANDBOX-ID]");
        const result = await sandbox.commands.run(["cat", "/workspace/outpost-proof.txt"], { check: true });
        process.stdout.write(result.stdout);
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

Confirm that the output matches your unique value. Reading it through that sandbox's ID ties the session's file write to the sandbox you created. The absolute path avoids relying on the session's working directory.

If the session stays queued, check the worker's log as shown in the next section. A worker serving an earlier session can't claim another until the earlier session ends or is suspended. If you no longer need the earlier session, end it in Devin Cloud. Alternatively, start another worker.

## Check the worker and stop it

For `cws-agent`, attach to the worker terminal as shown in the quick start. For the SDK path, inspect its status and recent logs. Replace `[SANDBOX-ID]` with the printed ID:

<Tabs>
  <Tab title="Python">
    ```python theme={"system"}
    from cwsandbox import AuthStrategy, Sandbox

    sandbox = Sandbox.from_id("[SANDBOX-ID]", auth=AuthStrategy.WANDB).result()
    print("Sandbox status:", sandbox.get_status())
    for container in sandbox.container_statuses:
        print(container.name, container.state, container.exit_code, container.restart_count)
    for line in sandbox.stream_logs(tail_lines=100):
        print(line, end="")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import { createSandboxClientFromEnv } from "@coreweave/cwsandbox/wandb";

    const client = createSandboxClientFromEnv();
    const sandbox = await client.fromId("[SANDBOX-ID]");
    console.log("Sandbox status:", sandbox.status, "Exit code:", sandbox.exitCode);
    for (const line of await sandbox.logs.read({ tailLines: 100 })) {
      process.stdout.write(line);
    }
    ```
  </Tab>
</Tabs>

Rerun this check to fetch newer logs. The Python client also reports per-container state, exit codes, and restart counts. The TypeScript client doesn't expose those details.

If the log reports that the Outposts API rejected the worker's token, confirm that you used the token copied when creating the outpost. Confirm that the token belongs to the account that owns the outpost. If you use a service user's v3 API token instead, its role must grant **Outposts write** (`account.outposts.write`). Correct the credential, then create the sandbox again.

A sandbox can report `running` while its worker repeatedly exits and restarts. Inspect its logs and, with the Python client, the per-container details shown in the preceding example.

Stop a worker that keeps failing authentication before creating its replacement. If startup fails without a useful reason, retain the sandbox ID and logs for [CoreWeave Support](/support/contact).

Stop the sandbox when you no longer need the worker. For serverless setup, see [Get started](../get-started).

Wait for the active Devin session to finish and save its results, then stop compute using the command for your setup:

<Tabs>
  <Tab title="cws-agent">
    ```bash theme={"system"}
    cws-agent down [SANDBOX-NAME]
    ```

    `down`은 중지하기 전에 워크스페이스의 스냅샷을 생성합니다. 캡처에 실패하면 보고된 오류와 `cws-agent status [SANDBOX-NAME]`의 출력을 확인하고, 문제를 해결한 후 다시 시도하세요. 저장되지 않은 변경 사항을 버려도 된다면 `cws-agent down [SANDBOX-NAME] --no-snapshot`을 사용하세요.
  </Tab>

  <Tab title="Sandbox SDK">
    <Tabs>
      <Tab title="Python">
        ```python theme={"system"}
        from cwsandbox import AuthStrategy, Sandbox

        sandbox = Sandbox.from_id("[SANDBOX-ID]", auth=AuthStrategy.WANDB).result()
        sandbox.stop().result()
        ```
      </Tab>

      <Tab title="TypeScript">
        ```typescript theme={"system"}
        import { createSandboxClientFromEnv } from "@coreweave/cwsandbox/wandb";

        const client = createSandboxClientFromEnv();
        const sandbox = await client.fromId("[SANDBOX-ID]");
        await sandbox.stop();
        ```
      </Tab>
    </Tabs>

    이 예제에는 영구 마운트가 없습니다. 중지하기 전에 파일을 외부로 복사하거나 변경 사항을 저장소에 푸시하세요.
  </Tab>
</Tabs>

Ending a Devin session doesn't stop this worker's sandbox. To restore a `cws-agent` workspace, see its [Devin Outposts guide](https://github.com/coreweave/cws-agent/blob/main/docs/self-hosted.md#devin-outposts).

## Optional: Customize the environment

You can customize the worker environment in the following ways:

* **Bring your own image.** The official image contains the `devin` CLI and little else. Build an image from it that adds your toolchain, and pass it as `container_image` in Python or `containerImage` in TypeScript. Devin requires `git`. Screen recording requires `ffmpeg`, and the browser and computer-use tools require a compatible browser binary.

  For amd64 images based on the official Ubuntu image, install Google Chrome. Ubuntu's `chromium` package is a snap stub that doesn't work in containers. See [Devin's container setup](https://docs.devin.ai/cloud/outposts/quickstart). Computer use also requires a running graphical display, such as Xvfb, with `DISPLAY` set for the worker.

  The worker searches standard install locations. If it doesn't find your binary, set `DEVIN_CHROME_PATH` to its absolute path. See the [Devin Outposts reference](https://docs.devin.ai/cloud/outposts/reference).
* **Configure GPUs.** See [sandbox GPU configuration](../client/guides/sandbox-configuration#gpu) for the available options. This guide's worker example uses CPU resources only.
* **Run more workers.** A worker serves one session at a time. Run the script again with the same outpost name to start another worker for the queue.
* **Create one sandbox per session.** The worker here reuses its sandbox across sessions. For a fresh sandbox per session, see Devin's [orchestration guide](https://docs.devin.ai/cloud/outposts/orchestration).
