> This page is for version Main (default).
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/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.process_supervisor

Standalone Linux process supervisor to upload beside a sandboxed harness.

Uses only the standard library; Gym need not be installed in the task sandbox.
The receipt confirms descendant cleanup independently of the harness result.

## Module Contents

### Classes

| Name                                                                        | Description                                                        |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [`CleanupReceipt`](#nemo_gym-agent_utils-process_supervisor-CleanupReceipt) | Outcome written only after supervision and bounded cleanup finish. |

### Functions

| Name                                                                              | Description                                                                      |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| [`_drain_children`](#nemo_gym-agent_utils-process_supervisor-_drain_children)     | Reap tool descendants, including processes that detached with setsid().          |
| [`_positive_seconds`](#nemo_gym-agent_utils-process_supervisor-_positive_seconds) | -                                                                                |
| [`_supervise`](#nemo_gym-agent_utils-process_supervisor-_supervise)               | Enforce a harness deadline, then acknowledge cleanup after all descendants exit. |
| [`exec_timeout`](#nemo_gym-agent_utils-process_supervisor-exec_timeout)           | Reserve TERM grace, harness process reaping, and descendant draining.            |
| [`main`](#nemo_gym-agent_utils-process_supervisor-main)                           | Run COMMAND and atomically write its cleanup receipt outside the task workdir.   |

### Data

[`CLEANUP_PHASE_COUNT`](#nemo_gym-agent_utils-process_supervisor-CLEANUP_PHASE_COUNT)

[`DEFAULT_CLEANUP_TIMEOUT`](#nemo_gym-agent_utils-process_supervisor-DEFAULT_CLEANUP_TIMEOUT)

### API

```python
class nemo_gym.agent_utils.process_supervisor.CleanupReceipt
```

**Bases:** `typing.TypedDict`

Outcome written only after supervision and bounded cleanup finish.

**`cleanup_confirmed`** `bool`

---

**`error`** `str | None`

---

**`return_code`** `int | None`

---

**`timed_out`** `bool`

---

```python
nemo_gym.agent_utils.process_supervisor._drain_children(
    timeout: float
) -> None
```

Reap tool descendants, including processes that detached with setsid().

```python
nemo_gym.agent_utils.process_supervisor._positive_seconds(
    value: str
) -> float
```

```python
nemo_gym.agent_utils.process_supervisor._supervise(
    command: list[str],
    timeout: float,
    cleanup_timeout: float = DEFAULT_CLEANUP_TIMEOUT,
    stop_path: pathlib.Path | None = None
) -> nemo_gym.agent_utils.process_supervisor.CleanupReceipt
```

Enforce a harness deadline, then acknowledge cleanup after all descendants exit.

```python
nemo_gym.agent_utils.process_supervisor.exec_timeout(
    timeout: float,
    cleanup_timeout: float = DEFAULT_CLEANUP_TIMEOUT
) -> float
```

Reserve TERM grace, harness process reaping, and descendant draining.

The extra 30 seconds cover startup, polling, and receipt I/O beyond those
bounded cleanup phases. Keep their count shared with the controller budget.

```python
nemo_gym.agent_utils.process_supervisor.main() -> int
```

Run COMMAND and atomically write its cleanup receipt outside the task workdir.

```python
nemo_gym.agent_utils.process_supervisor.CLEANUP_PHASE_COUNT = 3
```

```python
nemo_gym.agent_utils.process_supervisor.DEFAULT_CLEANUP_TIMEOUT = 10.0
```