Skip to content

[codex] Add sandbox API docs guide - #1717

Merged
anwithk merged 2 commits into
NVIDIA-NeMo:mainfrom
hemildesai:codex/opensandbox-coverage-tests
Jul 1, 2026
Merged

anwithk merged 2 commits into
NVIDIA-NeMo:mainfrom
hemildesai:codex/opensandbox-coverage-tests

Conversation

@hemildesai

Copy link
Copy Markdown
Contributor

Summary

  • Add a Fern guide for the provider-neutral nemo_gym.sandbox API.
  • Link the guide from the Infrastructure docs and include nemo_gym.sandbox in the API reference index.
  • Adjust Engineering Notes ordering so the new Sandbox API page appears in the Infrastructure section.

Validation

  • npm run check -- --warnings passed with 0 errors.
  • Remaining Fern warning: redirects check skipped because the local session is not authenticated with Fern.

@copy-pr-bot

copy-pr-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@hemildesai
hemildesai force-pushed the codex/opensandbox-coverage-tests branch from f007617 to a5a4d52 Compare June 24, 2026 20:40
@cwing-nvidia

Copy link
Copy Markdown
Contributor

Given we will be adding a number of providers, can we update to a parent-child content structure:

infrastructure/sandbox/index.mdx — provider-neutral overview: when to use it, core types, lifecycle, sync vs async, SandboxSpec fields, file transfer, status/cleanup, error handling, a local first-run example. This is the part every user reads.

infrastructure/sandbox/opensandbox.mdx — OpenSandbox-specific: connection/create/probe/operations config, provider_options, resource→k8s mapping, isolation/security properties, the mini_swe_agent_2 YAML + ng_run command, and OpenSandbox troubleshooting rows.

(ECS Fargate, Apptainer, OpenShell etc providers will each have their own child page)

infrastructure/sandbox/adding-a-provider.mdx — the SandboxProvider protocol + registry.py contributor guide.

Each new provider from #1685 then drops in as one more child page with the same shape (setup / config / isolation properties / example)


## YAML Configuration

The exact YAML location is agent-specific. Agents that use this module should expose provider settings and spec settings in their Gym config, then map those values into `AsyncSandbox` and `SandboxSpec`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought @ananthsub 's PR had decoupled this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes removed for now. Will add a configuration guide after Ananth's PR is merged

@hemildesai
hemildesai force-pushed the codex/opensandbox-coverage-tests branch 3 times, most recently from 09842bc to 2f96191 Compare June 25, 2026 19:01
@hemildesai
hemildesai marked this pull request as ready for review June 25, 2026 19:03
@hemildesai
hemildesai force-pushed the codex/opensandbox-coverage-tests branch 5 times, most recently from aabd1c1 to bbe8e12 Compare June 30, 2026 22:53
@hemildesai
hemildesai requested a review from a team as a code owner June 30, 2026 22:53
@hemildesai
hemildesai force-pushed the codex/opensandbox-coverage-tests branch from bbe8e12 to ec809cd Compare June 30, 2026 22:54
Signed-off-by: Hemil Desai <hemild@nvidia.com>
@hemildesai
hemildesai force-pushed the codex/opensandbox-coverage-tests branch from ec809cd to dd3000d Compare June 30, 2026 23:04
@anwithk
anwithk requested review from Glorf, ananthsub and ffrujeri July 1, 2026 15:49
@anwithk anwithk added the r0.4.0 Auto-cherrypick to release branch. Apply before merge; cherrypick happens after merge. label Jul 1, 2026
@anwithk
anwithk merged commit ab0e583 into NVIDIA-NeMo:main Jul 1, 2026
9 checks passed

@ffrujeri ffrujeri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sandbox API docs land in the Infrastructure section and document the existing nemo_gym.sandbox public interface — the provider-neutral facade that agents and resources servers use for isolated execution, backed by pluggable providers.

flowchart LR
    Agent["Agent / Resources Server"] -->|"AsyncSandbox / Sandbox"| API["nemo_gym.sandbox<br/>public facade"]
    API -->|"SandboxProvider protocol"| Reg["providers/registry"]
    Reg --> OS["opensandbox"]
    Reg --> AP["apptainer"]
    OS --> K8s[("OpenSandbox server / K8s")]
    AP --> Local[("local Apptainer instances")]
Loading

I checked the four new pages against the current nemo_gym/sandbox/ source: imports, the core-types table, AsyncSandbox/Sandbox method signatures, SandboxSpec/SandboxResources fields, SandboxStatus values, rewrite_image, the SandboxProvider protocol and registry, and both provider pages (config sections, resource mappings, user/exec behavior). The opensandbox.yaml block matches the shipped config file, every documented import is exported from nemo_gym.sandbox, the new sandbox/ subfolder auto-discovers in the sidebar (no main.yml edit needed), and the page positions are coherent.

Nicely structured and accurate. The parent-child layout also keeps provider-specific install steps correctly separated (the sandbox extra for OpenSandbox vs. the host apptainer binary for Apptainer), which a single combined page would have gotten wrong. LGTM.

ananthsub pushed a commit that referenced this pull request Jul 1, 2026
## Summary
- Add a Fern guide for the provider-neutral `nemo_gym.sandbox` API.
- Link the guide from the Infrastructure docs and include
`nemo_gym.sandbox` in the API reference index.
- Adjust Engineering Notes ordering so the new Sandbox API page appears
in the Infrastructure section.

## Validation
- `npm run check -- --warnings` passed with 0 errors.
- Remaining Fern warning: redirects check skipped because the local
session is not authenticated with Fern.

Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: NeMo Bot <nemo-bot@nvidia.com>
kajalj22 added a commit that referenced this pull request Jul 1, 2026
beep boop [🤖]: Hi @hemildesai 👋,

    we've cherry picked #1717 into  for you! 🚀

    Please review and approve this cherry pick by your convenience!

Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: NeMo Bot <nemo-bot@nvidia.com>
Co-authored-by: Hemil Desai <hemild@nvidia.com>
Co-authored-by: kajalj22 <kajalj@nvidia.com>
Glorf added a commit that referenced this pull request Jul 9, 2026
## Summary
Adds a built-in **`docker`** sandbox provider that runs each sandbox as
a container on the **local Docker daemon** via the `docker` CLI — no
OpenSandbox server or control plane required. It gives real container
isolation out of the box on any machine with Docker, and plugs in behind
the existing provider-neutral `SandboxProvider` protocol, so every agent
built on `nemo_gym.sandbox` works with it unchanged. Part of the
sandbox-providers epic (#1685).

## Motivation
The existing providers need either a remote control plane
(`opensandbox`) or a non-Docker local runtime (`apptainer`, common on
HPC). There was no zero-setup path for the most common developer/CI
environment — a machine with Docker. This provider closes that gap;
provider choice is a one-line config swap.

## Design
Mirrors the `apptainer` provider's shape — a single subprocess
chokepoint, a readiness probe, and neutral status/error mapping.
**CLI-based, no new Python dependency.**

```mermaid
flowchart LR
  Agent["Any agent"] --> API["nemo_gym.sandbox API"]
  API -- "create / exec / cp / close" --> P["DockerProvider"]
  P -- "docker run/exec/cp/rm" --> D[("local Docker daemon")]
  D --> C["sandbox container"]
```

- **One long-lived container per sandbox** — `docker run -d` + a
keep-alive PID; `docker exec` for commands, `docker cp` for files,
`docker rm -f` for teardown. State persists across `exec` calls.
- **Config swap** — registers under `docker`; the shipped `docker.yaml`
binds the same `sandbox` name every provider config uses, so switching
is a single `+config_paths` change (no agent edits).
- **`--entrypoint` override + `--init`** — the keep-alive is injected
via `--entrypoint` so images with their own `ENTRYPOINT` (e.g.
SWE-bench) don't swallow it; `--init` (tini) reaps short-lived `exec`
processes.
- **Auto-detected exec shell** — uses `bash` when the image has it
(needed for conda `source`, e.g. SWE-bench), falls back to `sh`;
resolved once per sandbox after readiness. Overridable via `exec_shell`.
- **`ttl_s` self-destruct** — when set (no custom entrypoint), the
keep-alive sleeps for `ttl_s` and `--rm` removes the container on exit —
a safety net for leaked/expired sandboxes.
- **Resource hard caps + isolation knobs** — `--cpus`, `--memory` (+ a
matching `--memory-swap`), `--gpus <n>`; opt-in `network` (incl.
`none`), `read_only`, `cap_drop`, `pids_limit`, `security_opt` (e.g.
`no-new-privileges`); never `--privileged`. Containers are labeled for
orphan reaping, and `--env` values are redacted from error messages.
- **Per-sandbox `provider_options`** — `volumes` (→ `-v`) and
`run_args`.

## Usage
```bash
ng_run "+config_paths=[$AGENT, nemo_gym/sandbox/providers/docker/configs/docker.yaml, $MODEL]"
```
or directly: `Sandbox({"docker": {}}, spec)`.

## Docs
Documented as a Fern provider page —
`fern/versions/latest/pages/infrastructure/sandbox/docker.mdx` — a
sibling of the Apptainer/OpenSandbox pages from #1717 with the same
shape (setup / config / `provider_options` / resource mapping /
lifecycle / isolation), plus a Docker card in the sandbox index. The
in-repo `README.md` stays as the developer reference, matching the other
providers.

## Validation
- **68 unit tests, 100% coverage** of the provider module — hermetic
(mock the CLI boundary) with skip-guarded real-daemon tests.
- Real-daemon smoke: create / exec / seeded files / upload / download /
status / close; `ttl_s` self-destruct verified live.
- **SWE-bench Verified (golden):** gold patch applied and graded
in-sandbox → reward 1.0.
- **SWE-bench Verified (agent):** a hosted OpenAI-compatible model drove
`mini_swe_agent_2` end-to-end through the provider → resolved, reward
1.0.

## Acceptance criteria (#1695)
- [x] Provider implementing `SandboxProvider`, registered in
`registry.py`
- [x] YAML config + example, selectable via `sandbox_provider`
- [x] Passing tests, skip-guarded when Docker/daemon is absent
- [x] Docs — Fern provider page (sibling to the #1717 sandbox pages) +
repo README, covering setup + isolation/security
- [x] Validated end-to-end on a real runtime (rollouts collected)

## Limitations
- A command timeout returns a timeout result and leaves the reused
sandbox running; the command's process is reaped with the container at
`close()` (standard `docker rm -f` teardown).
- Shares the host kernel — not an isolation boundary for untrusted code
(use a VM/gVisor/Kata).

Signed-off-by: Michal Bien <mbien@nvidia.com>
Signed-off-by: Michał Bień <mbien@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

r0.4.0 Auto-cherrypick to release branch. Apply before merge; cherrypick happens after merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants