cwsandbox Python SDK to launch and manage sandboxes.
Choose authentication
Choose the credential for the account that owns your sandboxes. To obtain a Forge API key or CoreWeave API access token, see Choose and get credentials. Run the installation commands in an active Python virtual environment. Save the Python code from your credential tab as asandbox_auth.py file beside the Python script that uses it. This file stores only the authentication choice. Import AUTH from that file. When you create a sandbox or session, pass AUTH explicitly or set it in SandboxDefaults.
- Forge API key
- CoreWeave API access token
Use your Forge API key with the
wandb integration in the software development kit (SDK). Replace [WANDB-API-KEY] with your API key:sandbox_auth.py
placement_mode="cks" when you create a sandbox or in SandboxDefaults.
To authenticate a session and the sandboxes it owns, create the session with auth=AUTH. When you reconnect, list, or clean up sandboxes, keep the same credential.
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.
Resources
Configure CPU, memory, and GPU resources using theResourceOptions dataclass or a plain dict. Serverless is the default placement mode. For serverless sandboxes, set equal CPU and memory requests and limits. For unequal requests and limits, use CKS placement with a runner whose policy permits them. To choose values, see Size sandbox CPU and memory.
Do not rely on serverless to normalize unequal values. Successful creation with unequal requests and limits does not establish support for resource bursting.
The following examples use equal requests and limits:
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, see the Kubernetes documentation.
ResourceOptions fields
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
Guaranteed Quality of Service depends on the resources of every container in the Pod. With container-level allocations, each container must have positive CPU and memory requests, with matching limits for each resource. This includes init containers and sidecars. Equal values for your workload container alone do not establish the QoS class of the whole sandbox Pod. A sandbox that tries to use more CPU than its limit is still throttled.Burstable QoS
On a CKS runner whose policy permits unequal requests and limits, lower requests give the sandbox a Burstable Quality of Service class. Lower requests let the scheduler bin-pack more sandboxes, but each sandbox can burst up to its limit if capacity is available. Complete Use your own compute and setCWSANDBOX_API_KEY to a CoreWeave API access token. Replace [RUNNER-ID] with the ID of a CKS runner whose policy permits these requests and limits:
CPU values
Specify CPU in millicores or whole cores. For details, see Resource units in Kubernetes.Memory values
Memory uses standard Kubernetes memory units:GPU
Request GPU resources alongside CPU and memory. A GPU request reserves GPUs only, so set CPU and memory explicitly.type and memory_gb are alternatives. Set at most one of them.
Inspect confirmed resources
After a sandbox starts, inspect the confirmed resource allocation. This example uses unequal requests and limits on CKS. Complete the CKS setup and setCWSANDBOX_API_KEY to a CoreWeave API access token. Replace [RUNNER-ID] with the ID of a CKS runner that has GPU capacity and a policy that permits these resources:
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. It converts network and secret configurations to their SDK types and resource mappings to plain dicts. The SDK normalizes those resource dicts to ResourceOptions when it constructs a sandbox.
The following configuration uses the same PyTorch 2.8 and CUDA 12.8 image as the GPU guide. Before you run a training workload, use that guide’s tensor check to confirm basic CUDA execution on the allocated GPU.
Sandbox.run() or session.sandbox(). The nested dict form for resources maps to ResourceOptions fields. The flat dict form ({"cpu": "1", "memory": "1Gi"}) sets matching CPU and memory requests and limits for the workload container. The Guaranteed QoS requirements still apply to every container in the Pod.
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.Mount options
Mounted files are read-only. Use
write_file() for files that require modification.
Ports
Declare ports withservices=[Service(...)]. A declaration such as Service(port=8080, name="web"), with neither visibility nor endpoint set, remains container-local and doesn’t request external exposure.
To serve HTTP to internet clients, request a public HTTPS endpoint. This example runs on serverless capacity, starts an HTTP server on port 8080, and requests its assigned HTTPS URL from your local machine. The platform terminates TLS and forwards HTTP to the container port.
The example uses EndpointAuth.OPEN, so anyone with the URL can access it without a credential. It uses the demonstration container’s /tmp directory as its document root. The credential used with auth=AUTH authorizes sandbox creation and deletion. It isn’t required for requests to this OPEN endpoint.
HTTP 200: directory listing received on success, and deletes the sandbox after the access attempt. The 5-minute lifetime also bounds how long it can run.
The ports parameter was removed in cwsandbox 1.x. Passing a value raises TypeError. Use services=[Service(...)] instead.
Service fields
Each
sandbox.service_urls entry is a (port, name, url) tuple. A URL can appear while the sandbox is still CREATING; an assigned URL does not guarantee that the application is listening.
A plain service has no endpoint value. For rules about combining plain services and endpoints in one sandbox, see Declare an endpoint.
For HTTPS, EndpointAuth.OPEN allows unauthenticated access. EndpointAuth.SHARE_TOKEN requires a share token returned at creation, Python SDK 1.16.0 or later, and a deployment that supports share-token HTTPS.
TLS passthrough leaves endpoint authentication unset. Your workload handles TLS termination and access control. Before you connect, prepare the TLS server, certificate, and private key. The server certificate must cover the assigned endpoint hostname for a client that verifies hostnames.
See Public endpoints for endpoint routing and authentication. The generated Service reference and Endpoint reference describe SDK version 1.14.2, which supports OPEN but predates SHARE_TOKEN.
Network
Configure outbound and inbound traffic using theNetworkOptions dataclass or a plain dict. Egress and ingress rules grant access over a default-deny baseline. A nonempty egress list replaces the runner policy’s default destination grants.
Hostname grants require a runner that supports hostname-based HTTPS egress and a policy that permits every requested destination. For CKS placement, ask your administrator to check the runner’s network constraints. For serverless placement, CoreWeave manages the pool and its policy. If the pool rejects these hostname rules, contact CoreWeave support.
To download packages from PyPI, allow both pypi.org for the package index and files.pythonhosted.org for package files. The pypi.org and *.pypi.org grants don’t cover files.pythonhosted.org:
NetworkOptions internally.
NetworkOptions fields
All fields are optional and default to
None. An empty rule list with its deny flag unset or False uses the runner policy default. Port exposure uses services, not NetworkOptions. For every EgressRule and IngressRule field, see Network rules.
An EgressRule requires exactly one destination: dns_name, cidr, tenant, any, or selector. A DNS grant accepts an exact name or a single leftmost wildcard such as *.pypi.org. An IngressRule requires exactly one source: cidr, tenant, or any.
The egress_mode, ingress_mode, and exposed_ports fields are not supported in cwsandbox 1.x. Use the fields above and declare ports with services.
deny_egress=True isn’t complete network isolation. Platform-required traffic can remain available, and outbound DNS is controlled separately. The Python NetworkOptions type doesn’t expose dnsEgress. Use the NetworkConfig API to change that mode where supported.
The Python SDK applies network options when it creates a sandbox and doesn’t provide methods to update a running sandbox’s network policy. For the API workflow, see Dynamic network policies. Exposed ports and service visibility remain creation-time settings.
Set network in SandboxDefaults
Set a default network configuration for all sandboxes:network replaces the SandboxDefaults.network value rather than merging with it. In the example above, sb3 suppresses destination grants; DNS remains controlled separately.
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.Session-level defaults
Set default annotations for all sandboxes in a session:Merge behavior
For single-container sandboxes created withSandbox.run() or session.sandbox() without template_id, the SDK merges SandboxDefaults.annotations with per-sandbox annotations. Explicit per-sandbox values override defaults with the same key. The SDK merges environment_variables the same way for these sandboxes.
For template creation, the SDK doesn’t merge SandboxDefaults.annotations or SandboxDefaults.environment_variables into the request. For template override rules, see the Sandbox.run_from_template() reference.
Sandbox.run_from_file() merges default annotations with explicit annotations, but doesn’t inherit SandboxDefaults.environment_variables. The Compose file supplies the container environment variables. See the Sandbox.run_from_file() reference.
SUNK integration
To pass Slurm context as pod annotations for SUNK integration, see the SUNK Pod Scheduler integration guide.Validation
The SDK does not validate annotation keys or values. The server handles validation of reserved key prefixes, value format, and maximum entry count.Secrets
For Forge team secret injection, authentication requirements, and Python and TypeScript examples, see Use Forge secrets.Timeouts
Three 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.
Only
max_lifetime_seconds terminates a sandbox. The other two bound individual requests and leave the sandbox running.
The max_timeout_seconds parameter was removed in cwsandbox 1.x. Passing a value raises TypeError; use request_timeout_seconds for the client request timeout.
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:
SandboxDefaults:
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.
The longest lifetime you can request is 30 days (2,592,000 seconds), for both serverless and CKS placement. The platform rejects larger requests.
For creation examples and CKS runner-policy defaults, see Run long-running sandboxes.
Behavior when the lifetime expires
The platform enforces the lifetime with a deadline on the sandbox’s underlying Kubernetes Job. Reaching the deadline triggers workload termination even if work is still in progress. Save results or checkpoints outside the sandbox before expiry. The Python SDK exposes the backend-reported reason inSandbox.status_reason, cached from the latest API response. Lifetime expiry can appear as a reason beginning with DeadlineExceeded. If the SDK raises SandboxFailedError, its status_reason attribute also carries the backend-reported reason. A reason can be absent, so track the age of long-lived sandboxes as well.
Set a lifetime that comfortably exceeds the work you expect. When you finish, stop sandboxes explicitly rather than relying on expiry.
timeout_seconds
timeout_seconds bounds a single operation on a running sandbox:
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.
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:
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.