> This page is for version 0.5.0.
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo/gym/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo/gym/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo/gym/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo/gym/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo/gym/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo/gym/v0.3.0/llms.txt
> - 0.2.1: https://docs.nvidia.com/nemo/gym/v0.2.1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/gym/llms.txt.

# nemo_gym.server_runtime.sandbox_lending

The sandboxes a resources server lends to a harness, one per resources session.

## Module Contents

### Classes

| Name                                                                      | Description                                                                                      |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| [`LentSandboxes`](#nemo_gym-server_runtime-sandbox_lending-LentSandboxes) | Start, lend and stop one sandbox per resources session, from the server's sandbox configuration. |

### Functions

| Name                                                      | Description                                                                                     |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [`_stop`](#nemo_gym-server_runtime-sandbox_lending-_stop) | Stop `sandbox` within `STOP_TIMEOUT_S`, even while the request that owns it is being cancelled. |

### Data

[`LOGGER`](#nemo_gym-server_runtime-sandbox_lending-LOGGER)

[`LentSandboxNetworkAccess`](#nemo_gym-server_runtime-sandbox_lending-LentSandboxNetworkAccess)

[`SHUTDOWN_STOP_CONCURRENCY`](#nemo_gym-server_runtime-sandbox_lending-SHUTDOWN_STOP_CONCURRENCY)

[`STOP_TIMEOUT_S`](#nemo_gym-server_runtime-sandbox_lending-STOP_TIMEOUT_S)

[`_LABEL_LIMIT`](#nemo_gym-server_runtime-sandbox_lending-_LABEL_LIMIT)

### API

```python
class nemo_gym.server_runtime.sandbox_lending.LentSandboxes(
    sandbox_provider: str,
    sandbox_config: nemo_gym.sandbox.config.SandboxConfig,
    image: str | None,
    workdir: str,
    network_access: nemo_gym.server_runtime.sandbox_lending.LentSandboxNetworkAccess = 'inherit',
    model_server: str | None = None,
    tool_servers: collections.abc.Sequence[str] = ()
)
```

Start, lend and stop one sandbox per resources session, from the server's sandbox configuration.

A server's episode seed calls `lend` and its episode close calls `release`, both under the server's
`ResourcesSessionLocks` lock. The server keeps any other session state, such as task files it serves or a
tool workspace, and calls `release_all` at shutdown. A server that grades in the lent sandbox after the
episode reads it with `get` before the close.

The harness gets an `operate` descriptor, which asks the provider to let it use the sandbox but not destroy it
(providers without leases ignore the scope). A stop goes on when the request that asked for it is cancelled, and
gives up after `STOP_TIMEOUT_S`. A session that is never closed keeps its sandbox until shutdown, or until the
provider reclaims it after `sandbox_config.ttl_s`, so set `ttl_s` above the episode deadline plus the time
that grading and cleanup take. A sandbox from a failed seed whose stop also fails is kept apart from the lent
ones, and the session's next lend, its release or the shutdown tries the stop again.

With `network_access="model_only"`, each sandbox is created with an egress rule that allows only the host of
`model_server`, the model server that a harness in the sandbox calls. `model_and_tools` also allows the hosts
of `tool_servers`, the servers whose tools the harness calls over MCP, such as this resources server. Every port
of an allowed host is open, so other services on that host stay reachable. The harness that borrows the sandbox
keeps this network; it cannot change it.

**`_failed_seed_sandboxes`** `dict[str, AsyncSandbox] = {}`

---

**`_sandboxes`** `dict[str, AsyncSandbox] = {}`

---

**`_tool_servers`** `= tuple(tool_servers)`

---

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes._access(
    sandbox: nemo_gym.sandbox.api.AsyncSandbox
) -> nemo_gym.sandbox.access.SandboxAccess
```

async

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes._restricted_policy(
    provider_config: collections.abc.Mapping[str, object]
) -> dict[str, object]
```

The egress rule for `network_access`, refused (422) where it cannot be enforced.

It allows the model server's host, and for `model_and_tools` the tool servers' hosts too.

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes._stop_failed_seed_sandbox(
    resources_session_id: str
) -> None
```

async

Stop the sandbox a failed seed of the session left running, if any. A failed stop raises and keeps it.

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes.get(
    resources_session_id: str
) -> nemo_gym.sandbox.api.AsyncSandbox | None
```

Return the sandbox lent for `resources_session_id`, or `None`.

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes.lend(
    resources_session_id: str,
    task_id: nemo_gym.core.episode_types.TaskId,
    files: collections.abc.Mapping[str, str | bytes] | None = None
) -> nemo_gym.sandbox.access.SandboxAccess
```

async

Return the access a harness needs to the session's sandbox, and start the sandbox on the first call.

`files` maps absolute paths in the sandbox to their contents; it can be empty. A repeated call, as for a
repeated seed, returns the same sandbox. If the new sandbox cannot start, receive its files or be described,
it is stopped and the error is raised. If that stop fails too, the sandbox is kept for a later stop: the
session's next lend stops it before it starts another one, and a failed stop there fails the lend.

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes.release(
    resources_session_id: str
) -> None
```

async

Stop the session's sandbox; safe to repeat. A failed stop raises and keeps it, so a close can retry.

It also stops a sandbox that a failed seed of the session left running.

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxes.release_all() -> None
```

async

Stop every sandbox still lent, as at server shutdown. A failed stop is logged and the rest go on.

```python
nemo_gym.server_runtime.sandbox_lending._stop(
    sandbox: nemo_gym.sandbox.api.AsyncSandbox
) -> None
```

async

Stop `sandbox` within `STOP_TIMEOUT_S`, even while the request that owns it is being cancelled.

A client that disconnects cancels its request handler and every later await in it, so an unshielded stop would
never run, and the sandbox would outlive every reference to it.

```python
nemo_gym.server_runtime.sandbox_lending.LOGGER = logging.getLogger(__name__)
```

```python
nemo_gym.server_runtime.sandbox_lending.LentSandboxNetworkAccess = Literal['inherit', 'model_only', 'model_and_tools']
```

```python
nemo_gym.server_runtime.sandbox_lending.SHUTDOWN_STOP_CONCURRENCY = 64
```

```python
nemo_gym.server_runtime.sandbox_lending.STOP_TIMEOUT_S = 120.0
```

```python
nemo_gym.server_runtime.sandbox_lending._LABEL_LIMIT = 63
```