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

# Sessions

> Group and manage multiple sandboxes with sessions.

This guide covers using `Session` to manage multiple sandboxes with shared configuration. It's for client developers who need to coordinate groups of sandboxes, apply common defaults, and ensure consistent cleanup across a workload.

## Session overview

A `Session` provides:

* Shared default configuration for all sandboxes.
* Automatic cleanup when the session closes.
* A scope for the `@session.function()` decorator.

## Basic usage

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

# Define shared configuration
defaults = SandboxDefaults(
    container_image="python:3.11",
    tags=("project-alpha",),
)

# Create a session with context manager
with cwsandbox.Session(defaults=defaults) as session:
    # Create sandboxes through the session
    sb1 = session.sandbox()
    sb2 = session.sandbox()

    # Use the sandboxes
    result1 = sb1.exec(["echo", "sandbox 1"]).result()
    result2 = sb2.exec(["echo", "sandbox 2"]).result()

# All sandboxes automatically stopped when exiting context
```

## Create sandboxes

The following sections describe how to create sandboxes through a session and override session defaults.

### session.sandbox()

Creates a sandbox with session defaults. The sandbox doesn't start until first use:

```python theme={"system"}
with cwsandbox.Session(defaults=defaults) as session:
    # sandbox() returns an unstarted sandbox
    sandbox = session.sandbox()

    # Operations auto-start the sandbox on first use
    result = sandbox.exec(["echo", "hello"]).result()
```

For explicit control over when the start RPC fires:

```python theme={"system"}
with cwsandbox.Session(defaults=defaults) as session:
    sandbox = session.sandbox()
    sandbox.start().result()  # Explicit start
    sandbox.wait()            # Wait for RUNNING
    result = sandbox.exec(["echo", "hello"]).result()
```

### Override defaults

Pass additional arguments to override session defaults:

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

# Session with base configuration
defaults = SandboxDefaults(
    container_image="python:3.11",
    tags=("my-project",),
)

with cwsandbox.Session(defaults=defaults) as session:
    # Override image and resources for this sandbox
    gpu_sandbox = session.sandbox(
        command="sleep",
        args=["infinity"],
        container_image="pytorch/pytorch:latest",
        resources=ResourceOptions(
            requests={"cpu": "4", "memory": "16Gi"},
            limits={"cpu": "8", "memory": "32Gi"},
            gpu={"count": 1},
        ),
        tags=["gpu-workload"],  # Merged with session tags
    )
```

See the [Sandbox configuration guide](/products/sandboxes/client/guides/sandbox-configuration) for all available options.

## Multiple sandbox management

Sessions work well for managing sandbox pools:

```python theme={"system"}
with cwsandbox.Session(defaults=defaults) as session:
    # Create a pool of sandboxes
    sandboxes = [
        session.sandbox()
        for _ in range(5)
    ]

    # Distribute work across the pool
    processes = [
        sb.exec(["python", "-c", f"print({i})"])
        for i, sb in enumerate(sandboxes)
    ]

    # Collect results
    results = [p.result() for p in processes]

# All 5 sandboxes automatically cleaned up
```

## Session lifecycle

The following sections describe how to close a session, what `close()` does, and how to handle errors.

### Manual close

When you don't use a context manager, close a session explicitly:

```python theme={"system"}
session = cwsandbox.Session(defaults=defaults)

sandbox = session.sandbox()
result = sandbox.exec(["echo", "hello"]).result()

# Close the session (stops all sandboxes)
session.close().result()
```

### What close() does

Calling `close()` performs the following actions:

1. Stops all sandboxes created through the session.
2. Waits for cleanup to complete.
3. Returns `OperationRef[None]`.

### Error handling

Sessions clean up even if exceptions occur:

```python theme={"system"}
with cwsandbox.Session(defaults=defaults) as session:
    sandbox = session.sandbox()
    raise RuntimeError("Something went wrong!")
# Sandbox is still cleaned up
```

## Adopt external sandboxes

Bring sandboxes created outside the session under session management:

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

with cwsandbox.Session(defaults=defaults) as session:
    # Find existing sandboxes
    existing = Sandbox.list(tags=["orphaned-work"]).result()

    # Adopt them for cleanup
    for sandbox in existing:
        session.adopt(sandbox)

    # Now session.close() will clean them up too
```

## Session properties

Inspect session state with built-in properties such as `sandbox_count`:

```python theme={"system"}
session = cwsandbox.Session(defaults=defaults)

# Number of sandboxes tracked
print(session.sandbox_count)  # 0

sandbox = session.sandbox()
print(session.sandbox_count)  # 1
```

## When to use sessions

| Use case                          | Recommended approach                 |
| --------------------------------- | ------------------------------------ |
| Single sandbox, simple task       | `Sandbox.run()` with context manager |
| Multiple sandboxes, shared config | Session                              |
| Function decorator API            | Session required                     |
| Pool of workers                   | Session                              |
| One-off command                   | Direct `Sandbox.run()`               |

## Without sessions

You don't need sessions for single sandboxes:

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

# Direct usage without session
with Sandbox.run() as sandbox:
    result = sandbox.exec(["echo", "hello"]).result()
# Cleanup handled by context manager
```
