> ## 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.

# サンドボックスの設定

> サンドボックスのリソース、イメージ、ネットワーク、タイムアウト、ストレージを設定します。

<Note>
  The examples on this page omit `auth`. To authenticate with your W\&B API key, install `cwsandbox[wandb]` and pass `auth=AuthStrategy.WANDB` to `Sandbox.run()`, `Sandbox()`, or `Sandbox.session()`. See [Get started](/products/sandboxes/serverless/get-started).
</Note>

This guide covers sandbox configuration options, including resources, mounted files, ports, annotations, and timeouts. Use it as a reference when you need to tailor a sandbox's runtime environment to match the requirements of a workload, such as reserving GPU capacity, exposing a service, or setting operation timeouts.

This page is for developers who use the `cwsandbox` Python SDK to launch and manage sandboxes.

## Overview

You can set sandbox configuration in three places, listed from broadest to most specific scope:

* **SandboxDefaults**: Shared defaults for all sandboxes in a session.
* **Sandbox.run() kwargs**: Per-sandbox overrides.
* **@session.function() kwargs**: Function-specific configuration.

```python theme={"system"}
from cwsandbox import ResourceOptions, Sandbox, SandboxDefaults, Session

# Via SandboxDefaults
defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=3600,
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "2Gi"},
        limits={"cpu": "2", "memory": "2Gi"},
    ),
)

# Via Sandbox.run() kwargs
sandbox = Sandbox.run(
    defaults=defaults,
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "4Gi"},
        limits={"cpu": "4", "memory": "4Gi"},
    ),
)

# Via @session.function() kwargs
with Session(defaults) as session:
    @session.function(resources={"cpu": "1", "memory": "1Gi"})
    def compute(x: int) -> int:
        return x * 2
```

The following sections describe each configuration area in detail.

## Resources

`ResourceOptions` データクラスまたはプレーンな dict を使用して、CPU、メモリ、GPU のリソースを設定します。サーバーレスの配置では、リクエストと制限に同じ値が使用されます。

The following examples use equal requests and limits:

```python theme={"system"}
from cwsandbox import ResourceOptions, Sandbox

# Using ResourceOptions
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "2Gi"},
        limits={"cpu": "2", "memory": "2Gi"},
    ),
)

# Using dict
sandbox = Sandbox.run(
    resources={
        "requests": {"cpu": "2", "memory": "2Gi"},
        "limits": {"cpu": "2", "memory": "2Gi"},
    },
)
```

Both forms are equivalent: the SDK automatically converts dicts to `ResourceOptions` internally.

`ResourceOptions` separates resource requests from limits. Requests tell the scheduler what the sandbox needs. Limits set the maximum it can use. For background on how Kubernetes uses requests and limits to assign [Quality of Service classes](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/), see the Kubernetes documentation.

### ResourceOptions fields

| Field | Type | Description |
| - | - | - |
| `requests` | `dict[str, str] \| None` | CPU and memory requests for scheduling (for example, `{"cpu": "500m", "memory": "512Mi"}`). |
| `limits` | `dict[str, str] \| None` | CPU and memory limits the sandbox cannot exceed (for example, `{"cpu": "2", "memory": "2Gi"}`). |
| `gpu` | `dict[str, Any] \| None` | GPU configuration (for example, `{"count": 1, "type": "H100"}`). |

All fields are optional in the client and default to `None`. The resolved allocation must satisfy the applicable policy. If you omit the resource allocation, complete, positive CPU and memory defaults from that policy supply both requests and limits.

### Guaranteed QoS

When requests equal limits, the sandbox receives a Guaranteed Quality of Service class. The scheduler reserves the full allocation, and Kubernetes evicts Guaranteed Pods last under node resource pressure. A sandbox that tries to use more CPU than its limit is still throttled. Use this for latency-sensitive workloads.

```python theme={"system"}
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "2", "memory": "4Gi"},
        limits={"cpu": "2", "memory": "4Gi"},
    ),
)
```

For Guaranteed QoS, a flat dict shorthand is available. The SDK normalizes flat dicts by setting both requests and limits to the same values.

```python theme={"system"}
# Flat dict shorthand: requests and limits are set to identical values
sandbox = Sandbox.run(
    resources={"cpu": "2", "memory": "4Gi"},
)
```

### CPU values

Specify CPU in millicores or whole cores. For details, see [Resource units in Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes).

| Value | Meaning |
| - | - |
| `"100m"` | 100 millicores (0.1 CPU) |
| `"500m"` | 500 millicores (0.5 CPU) |
| `"1000m"` or `"1"` | 1 full CPU core |
| `"2000m"` or `"2"` | 2 CPU cores |

### Memory values

Memory uses standard [Kubernetes memory units](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memory):

| Value | Meaning |
| - | - |
| `"128Mi"` | 128 mebibytes |
| `"512Mi"` | 512 mebibytes |
| `"1Gi"` | 1 gibibyte |
| `"4Gi"` | 4 gibibytes |

### GPU

Request GPU resources alongside CPU and memory. A GPU request reserves GPUs only, so set CPU and memory explicitly.

```python theme={"system"}
sandbox = Sandbox.run(
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "16Gi"},
        limits={"cpu": "4", "memory": "16Gi"},
        gpu={"count": 1},
    ),
)
```

GPU configuration keys:

| キー | タイプ | 説明 |
| - | - | - |
| `count` | `int` | リクエストする GPU の数。 |
| `type` | `str` | GPU タイプ。サーバーレスキャパシティでは GPU タイプが自動的に割り当てられるため、指定しないでください。詳しくは、[GPU サンドボックスを実行する](/ja/products/sandboxes/serverless/gpu-sandboxes)を参照してください。 |
| `memory_gb` | `int` | GPU メモリの最小値 (GB)。ランナー上で、この値以上のメモリを搭載した GPU タイプが選択されます。条件を満たすタイプが複数ある場合、どのタイプが選択されるかは規定されていません。 |

`type` and `memory_gb` are alternatives. Set at most one of them.

### Configuration library interop

All configuration types (`NetworkOptions`, `Secret`, `ResourceOptions`) accept either the dataclass or a plain dict. This means ML configuration libraries that resolve configs to dicts or dict-like objects can pass values directly to the SDK without manual conversion.

`SandboxDefaults.from_dict()` accepts a plain dict or an OmegaConf `DictConfig` and coerces nested fields automatically. Dicts become `NetworkOptions`, `Secret`, or `ResourceOptions` as needed, and lists become tuples.

```yaml theme={"system"}
# sandbox.yaml
container_image: "pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime"
max_lifetime_seconds: 3600
tags:
  - training
  - experiment-42
resources:
  requests:
    cpu: "4"
    memory: "8Gi"
  limits:
    cpu: "4"
    memory: "8Gi"
  gpu:
    count: 1
network:
  egress_mode: "internet"
environment_variables:
  LOG_LEVEL: "info"
```

```python theme={"system"}
from omegaconf import OmegaConf
from cwsandbox import Sandbox, SandboxDefaults

cfg = OmegaConf.load("sandbox.yaml")
defaults = SandboxDefaults.from_dict(cfg)

with Sandbox.run(defaults=defaults) as sb:
    result = sb.exec(["python", "train.py"]).result()
```

Individual fields also accept dicts when you pass them directly to `Sandbox.run()` or `session.sandbox()`. The nested dict form for resources maps to `ResourceOptions` fields. The flat dict form (`{"cpu": "1", "memory": "1Gi"}`) is also accepted and treated as Guaranteed QoS.

## Mounted files

Mounted files let you provide configuration files, scripts, or other read-only assets to the sandbox at startup, without baking them into a container image.

```python theme={"system"}
sandbox = Sandbox.run(
    mounted_files=[
        {
            "path": "/app/config.json",
            "content": '{"debug": true}',
        },
        {
            "path": "/app/script.py",
            "content": "print('hello')",
        },
    ],
)

# Files are available immediately
result = sandbox.exec(["python", "/app/script.py"]).result()
```

### Mount options

| Field | Type | Description |
| - | - | - |
| `path` | `str` | Absolute path in sandbox. |
| `content` | `str` | File content (text). |

Mounted files are read-only. Use `write_file()` for files that require modification.

## Ports

Expose ports so processes inside the sandbox can serve traffic to outside clients:

```python theme={"system"}
sandbox = Sandbox.run(
    "python", "-m", "http.server", "8080",
    ports=[
        {"container_port": 8080},
    ],
)
```

### Port configuration

| Field | Type | Description |
| - | - | - |
| `container_port` | `int` | Port inside the sandbox. |

To give a port an internet-reachable address with platform TLS or TLS passthrough, see [Public endpoints](../../public-endpoints).

## Network

Configure network options using the `NetworkOptions` dataclass or a plain dict:

```python theme={"system"}
from cwsandbox import NetworkOptions, Sandbox

# Using NetworkOptions
sandbox = Sandbox.run(
    network=NetworkOptions(
        ingress_mode="public",
        exposed_ports=(8080,),
    ),
)

# Using dict
sandbox = Sandbox.run(
    network={"ingress_mode": "public", "exposed_ports": [8080]},
)
```

Both forms are equivalent: the SDK automatically converts dicts to `NetworkOptions` internally.

### NetworkOptions fields

| Field | Type | Description |
| - | - | - |
| `ingress_mode` | `str \| None` | Controls inbound traffic, such as `"public"` (internet accessible) or `"internal"` (cluster only). |
| `exposed_ports` | `tuple[int, ...] \| None` | Ports to expose (required with `ingress_mode`). Pass as tuple `(8080,)` or list `[8080]`. |
| `egress_mode` | `str \| None` | Controls outbound traffic, such as `"internet"` (full access), `"isolated"` (no external), or `"org"` (org-internal only). |

All fields are optional and default to `None`, which uses backend defaults.

### Set network in SandboxDefaults

Set a default network configuration for all sandboxes:

```python theme={"system"}
from cwsandbox import NetworkOptions, SandboxDefaults, Session

defaults = SandboxDefaults(
    network=NetworkOptions(egress_mode="internet"),
)

with Session(defaults) as session:
    # All sandboxes inherit the network config
    sb1 = session.sandbox()  # Uses egress_mode="internet"
    sb2 = session.sandbox()  # Uses egress_mode="internet"

    # Override for specific sandbox
    sb3 = session.sandbox(network=NetworkOptions(egress_mode="user"))
```

## Annotations

Add Kubernetes pod annotations to sandboxes. Annotations are key-value string pairs attached to the underlying pod, useful for integrations that read pod metadata, such as schedulers, cost-allocation tools, or external automation.

```python theme={"system"}
sandbox = Sandbox.run(
    annotations={
        "team": "ml-infra",
        "experiment": "training-run-42",
    },
)
```

### Session-level defaults

Set default annotations for all sandboxes in a session:

```python theme={"system"}
defaults = SandboxDefaults(
    annotations={
        "team": "ml-infra",
        "managed-by": "sandbox-sdk",
    },
)

with Session(defaults) as session:
    # Inherits default annotations
    sb1 = session.sandbox()

    # Merge: explicit annotations override defaults on key collision
    sb2 = session.sandbox(
        annotations={"experiment": "run-42", "team": "ml-research"},
    )
    # sb2 receives: team=ml-research, managed-by=sandbox-sdk, experiment=run-42
```

### Merge behavior

When you provide both `SandboxDefaults.annotations` and per-sandbox `annotations`, the SDK merges them. Explicit per-sandbox values win on key collision, matching the same semantics as `environment_variables`.

### Validation

The SDK does not validate annotation keys or values. The server handles validation of reserved key prefixes, value format, and maximum entry count.

<h2 id="secrets">
  シークレット
</h2>

W\&B チームのシークレット注入、認証の要件、Python および TypeScript のサンプルについては、[W\&B シークレットを使用する](/ja/products/sandboxes/serverless/secrets)を参照してください。

## Timeouts

Four settings control how long a sandbox and its operations run. The names are similar, so the following table maps each one to what it bounds.

| Setting | Bounds | Enforced by | Default |
| - | - | - | - |
| `max_lifetime_seconds` | Total sandbox lifetime before automatic termination | Server | Runner-policy default, or 10 minutes if none is set |
| `timeout_seconds` | A single `exec()`, `read_file()`, or `write_file()` call | Client | Falls back to `request_timeout_seconds` |
| `max_timeout_seconds` | How long the server waits to place a sandbox before the attempt fails | Server | 30 seconds |
| `request_timeout_seconds` | Client-side HTTP timeout for most remote procedure calls (RPCs) | Client | 300 seconds |

Only `max_lifetime_seconds` terminates a sandbox. The other three bound individual requests and leave the sandbox running.

### max\_lifetime\_seconds

`max_lifetime_seconds` sets the total wall-clock lifetime of a sandbox. When a sandbox reaches this age, the platform terminates it even if work is still in progress.

If you don't set `max_lifetime_seconds`, the runner-policy default applies. If no positive policy default supplies a lifetime, the platform uses 10 minutes. Set the value explicitly for long-running work:

```python theme={"system"}
from cwsandbox import Sandbox

with Sandbox.run(max_lifetime_seconds=7200) as sandbox:  # 2 hours
    sandbox.exec(["python", "train.py"], timeout_seconds=7000).result()
```

To apply one lifetime to every sandbox a session creates, set it in `SandboxDefaults`:

```python theme={"system"}
from cwsandbox import Sandbox, SandboxDefaults

defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=3600,  # 1 hour
)

with Sandbox.run(defaults=defaults) as sandbox:
    sandbox.exec(["python", "-c", "print('working')"]).result()
```

An explicit `max_lifetime_seconds` argument on `Sandbox.run()` takes precedence over the value in `defaults`. Because the argument's default is `None`, you can't use it to remove a lifetime that `defaults` already sets.

リクエストできる有効期間の上限は 30 日 (2,592,000 秒) です。これを超える値をリクエストすると、プラットフォームによって拒否されます。

<Warning>
  You can't change `max_lifetime_seconds` after a sandbox starts. No API extends the lifetime of a running sandbox, so choose the value when you create it. To keep working past the limit, capture what you need and start a new sandbox with a lifetime of up to 30 days.
</Warning>

作成のサンプルについては、[長時間実行のサンドボックスを実行する](/ja/products/sandboxes/serverless/long-running-sandboxes)を参照してください。

#### Behavior when the lifetime expires

The platform enforces the lifetime by terminating the sandbox's underlying Kubernetes Job, so termination is immediate rather than graceful. Two consequences matter in practice:

* Processes inside the sandbox don't receive the grace period that [`stop()`](sandbox-lifecycle) provides. Anything not already written out is lost.
* The client doesn't receive a distinct error or reason for the termination. The SDK reports no termination reason on a `Sandbox`, so you can't distinguish lifetime expiry from other failures programmatically. Track the age of long-lived sandboxes yourself.

Set a lifetime that comfortably exceeds the work you expect, and stop sandboxes explicitly when you finish rather than relying on expiry.

### timeout\_seconds

`timeout_seconds` bounds a single operation on a running sandbox:

```python theme={"system"}
result = sandbox.exec(
    ["python", "long_script.py"],
    timeout_seconds=300,  # 5 minutes
).result()
```

This controls how long the client waits for a response. If the wait exceeds the timeout, the SDK raises `SandboxTimeoutError`. The sandbox keeps running. The clock starts only after the sandbox reaches `RUNNING`, so startup time doesn't count against it.

Keep `timeout_seconds` below the sandbox's `max_lifetime_seconds`. A command whose timeout exceeds the sandbox's remaining lifetime stops when the sandbox terminates.

### max\_timeout\_seconds

`max_timeout_seconds` bounds how long the server waits to place a sandbox on a runner before the attempt fails. It's a server-side placement budget, not a client read timeout, and it doesn't affect how long the sandbox runs afterward:

```python theme={"system"}
sandbox = Sandbox.run(max_timeout_seconds=120)
```

The server accepts values from 1 to 300 seconds and defaults to 30. The server clamps values above 300 to 300. If sandboxes fail to start under heavy cluster load, raise the value. `max_timeout_seconds` is available on `Sandbox.run()` and `session.sandbox()`, but not on `SandboxDefaults`.

### request\_timeout\_seconds

`request_timeout_seconds` is the client-side HTTP timeout applied to most RPCs, and it's the fallback when a call doesn't pass its own `timeout_seconds`. Set it in `SandboxDefaults`:

```python theme={"system"}
defaults = SandboxDefaults(request_timeout_seconds=600.0)
```

Status polling uses `poll_rpc_timeout_seconds` instead, so a stalled poll fails fast rather than blocking for the full request timeout. For the full set of client-side tuning options, see the [SandboxDefaults reference](/products/sandboxes/client/ref/core/sandbox-defaults).

## Complete example

The following example combines defaults, per-sandbox overrides, mounted files, and ports into a single configuration that mirrors how a production workload might be launched:

```python theme={"system"}
from cwsandbox import NetworkOptions, ResourceOptions, Sandbox, SandboxDefaults

defaults = SandboxDefaults(
    container_image="python:3.11",
    max_lifetime_seconds=1800,  # 30 minutes
    tags=("production", "ml-pipeline"),
    resources=ResourceOptions(
        requests={"cpu": "4", "memory": "8Gi"},
        limits={"cpu": "4", "memory": "8Gi"},
    ),
    network=NetworkOptions(egress_mode="internet"),
)

with Sandbox.run(
    defaults=defaults,
    mounted_files=[
        {
            "path": "/app/config.yaml",
            "content": "model: gpt-4\nmax_tokens: 1000",
        },
    ],
    ports=[
        {"container_port": 8000},
    ],
) as sandbox:
    # Install dependencies
    sandbox.exec(["pip", "install", "fastapi", "uvicorn"]).result()

    # Run application
    result = sandbox.exec(
        ["python", "-c", "print('Server started')"],
        timeout_seconds=60,
    ).result()
    print(result.stdout)
```
