> This page is for version 0.5.1.
> 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.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/gym/_mcp/server.

# nemo_gym.agent_utils.sandbox_session

Agent-server lifecycle for one supervised harness activation.

## Module Contents

### Classes

| Name                                                                     | Description                                                               |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
| [`SandboxCommand`](#nemo_gym-agent_utils-sandbox_session-SandboxCommand) | Harness argv and the installed interpreter used to launch its supervisor. |
| [`SandboxSession`](#nemo_gym-agent_utils-sandbox_session-SandboxSession) | Execute, stop, capture, then release an owned or borrowed sandbox.        |

### Functions

| Name                                                                       | Description |
| -------------------------------------------------------------------------- | ----------- |
| [`_reuse_or_start`](#nemo_gym-agent_utils-sandbox_session-_reuse_or_start) | -           |

### Data

[`LOG`](#nemo_gym-agent_utils-sandbox_session-LOG)

### API

```python
class nemo_gym.agent_utils.sandbox_session.SandboxCommand(
    argv: list[str],
    python: str
)
```

Dataclass

Harness argv and the installed interpreter used to launch its supervisor.

**`argv`** `list[str]`

---

**`python`** `str`

---

```python
class nemo_gym.agent_utils.sandbox_session.SandboxSession(
    sandbox: nemo_gym.sandbox.api.AsyncSandbox,
    session_dir: str,
    workdir: str | None,
    harness: str,
    owns_sandbox: bool = False
)
```

Dataclass

Execute, stop, capture, then release an owned or borrowed sandbox.

Runtime installation belongs in the adapter's seed hook. `stage_activation`
stages input and returns a command; `collect` copies harness artifacts
to the agent server after cleanup is confirmed. It may run a bounded snapshot
command, but must not restart the harness. Parsing responses stays in the adapter.

A new session stages input and its supervisor, runs the harness process, then
stops and collects artifacts. Execution retains the sandbox until close
releases it. Missing termination evidence remains retryable. A final negative
receipt skips capture, releases a borrowed connection and leaves teardown to
Resources; an owned sandbox falls back to provider stop. Closed means release succeeded.

On timeout or close, the supervisor preserves previously adopted children outside
the harness group and drains newly adopted children, including services orphaned
by in-flight tools during the stop. Preserved children can also be unfinished
background jobs; they remain until the sandbox owner destroys the sandbox.
Natural CLI exit has no adoption cutoff, so detached unfinished tools may remain.
Borrowed sandboxes stay available for Resources verification; owned sandboxes are
stopped on close. Unconfirmed harness termination prevents capture and verification.

Each stop, collection and release phase is bounded by `close_timeout` (or
the timeout passed to `close`). Failed cleanup/release retains the handle
for retry. Failed capture is recorded separately and does not prevent release.
HTTP request binding and activation retries belong to the agent session layer.

**`_capture_attempted`** `bool = field(default=False, init=False)`

---

**`_close_task`** `Task[None] | None = field(default=None, init=False)`

---

**`_collect`** `Callable[[], Awaitable[Artifacts]] | None = field(default=None, init=False)`

---

**`_exec_task`** `Task[SandboxExecResult] | None = field(default=None, init=False)`

---

**`_finalize_task`** `Task[None] | None = field(default=None, init=False)`

---

**`_stage_task`** `Future[SandboxCommand] | None = field(default=None, init=False)`

---

**`artifacts`** `Artifacts | None = field(default=None, init=False)`

---

**`capture_error`** `Exception | None = field(default=None, init=False)`

---

**`cleanup`** `CleanupReceipt | None = field(default=None, init=False)`

---

**`closed`** `bool`

Whether sandbox release completed successfully.

---

**`closing`** `bool`

Whether close has been requested, including a failed attempt.

---

**`harness`** `str`

---

**`launch_started`** `bool = field(default=False, init=False)`

---

**`owns_sandbox`** `bool = False`

---

**`sandbox`** `AsyncSandbox`

---

**`sandbox_stopped`** `bool = field(default=False, init=False)`

---

**`session_dir`** `str`

---

**`stop_request_path`** `str`

Marker path an adapter may pass to its harness for cancellation diagnostics.

---

**`termination_error`** `HarnessTerminationError | None = field(default=None, init=False)`

---

**`workdir`** `str | None`

---

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._cancel_and_wait(
    task: asyncio.Future[nemo_gym.agent_utils.sandbox_session.SandboxSession._cancel_and_wait[T]],
    timeout: float
) -> None
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._close(
    timeout: float
) -> None
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._finalize(
    timeout: float
) -> None
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._finish(
    timeout: float
) -> None
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._release_exec(
    timeout: float
) -> None
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession._stage(
    stage_activation: collections.abc.Callable[[], collections.abc.Awaitable[nemo_gym.agent_utils.sandbox_session.SandboxCommand]]
) -> nemo_gym.agent_utils.sandbox_session.SandboxCommand
```

async

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession.close(
    timeout: float
) -> None
```

async

Join finalization before release; concurrent/retried closes never duplicate capture.

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession.execute(
    stage_activation: collections.abc.Callable[[], collections.abc.Awaitable[nemo_gym.agent_utils.sandbox_session.SandboxCommand]],
    collect: collections.abc.Callable[[], collections.abc.Awaitable[nemo_gym.agent_utils.sandbox_session.SandboxSession[Artifacts]]],
    timeout: float,
    close_timeout: float
) -> nemo_gym.agent_utils.sandbox_session.SandboxSession[Artifacts]
```

async

Run once, preserving captured artifacts even when execution raises.

Cancellation stops the remote harness before releasing provider exec.
Callers that merely stop waiting (such as disconnected HTTP requests)
must shield their shared activation task.

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession.read_output_log() -> str
```

async

Read combined supervisor/harness diagnostics without masking the original failure.

```python
nemo_gym.agent_utils.sandbox_session.SandboxSession.stop_harness(
    timeout: float
) -> None
```

async

Confirm harness termination before capture and transport release.

```python
nemo_gym.agent_utils.sandbox_session._reuse_or_start(
    task: asyncio.Task[nemo_gym.agent_utils.sandbox_session._reuse_or_start[T]] | None,
    factory: collections.abc.Callable[[], collections.abc.Coroutine[object, object, nemo_gym.agent_utils.sandbox_session._reuse_or_start[T]]]
) -> asyncio.Task[nemo_gym.agent_utils.sandbox_session._reuse_or_start[T]]
```

```python
nemo_gym.agent_utils.sandbox_session.LOG = logging.getLogger(__name__)
```