feat(sandbox): add the sandbox_task hook mechanism - #2402
Draft
terrykong wants to merge 2 commits into
Draft
Conversation
Four of the six sandbox consumers build their SandboxSpec in Python because it depends on the task row, so there is nothing declarative to read. Anything outside the owning server -- a debugger, a validator -- cannot answer "what image would this row get" without importing that server's whole dependency tree. `sandbox_task` lets a server declare that answer instead: `spec_resolver` and `exec_wrapper` name plain module:attribute callables, plus `image_from_row` and `id_from_row` for the cases that need no Python at all. It is optional on BaseRunServerInstanceConfig, so servers that declare nothing are unaffected and servers at runtime ignore it entirely. `nemo_gym.sandbox.hooks` deliberately imports nothing from the CLI: the whole point is that the resolver is reachable from a process that has not imported the agent. Signed-off-by: Terry Kong <terryk@nvidia.com>
…nto hooks The image name was derived in `app.py` and the conda preamble lived in `sandbox_environment.py`, both reachable only by importing modules that pull in ray, minisweagent and swebench. Anything outside the agent's own venv -- `gym sandbox debug`, for one -- could not ask "what image would this row get?" without paying for all of that. Move both into a stdlib-only `sandbox_hooks` module and point the agent at it, so there is one definition rather than two that can drift, and declare it from the config through the `sandbox_task` block. No behaviour change: the same image names and the same wrapped command. Signed-off-by: Terry Kong <terryk@nvidia.com>
This was referenced Aug 7, 2026
cmunley1
reviewed
Aug 7, 2026
| remaining = dict(mapping or {}) | ||
| image = rewrite_image(remaining.pop("image", None), list(remaining.pop("image_rewrites", []) or [])) | ||
|
|
||
| spec = SandboxSpec( |
Contributor
There was a problem hiding this comment.
should this have ports too
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 3 of 4 in the
gym sandbox debugstack (#2400 → #2401 → #2402 → #2403).Why
Four of the six
nemo_gym.sandboxconsumers build theirSandboxSpecin Python, because it depends on the task row — there is nothing declarative to read. So anything outside the owning server (a debugger, a validator) cannot answer "what image would this row get?" without importing that server's entire dependency tree. Formini_swe_agent_2that meansray,minisweagentandswebench.What
An optional
sandbox_taskblock onBaseRunServerInstanceConfig:Servers that declare nothing are unaffected, and servers ignore the block at runtime.
nemo_gym.sandbox.hooksdeliberately imports nothing from the CLI — the whole point is that a resolver is reachable from a process that has not imported the agent.And its first user
mini_swe_agent_2adopts it in the same PR, because a mechanism with no users is not reviewable. Image derivation moved out ofapp.pyand the conda preamble out ofsandbox_environment.py, into a stdlib-onlysandbox_hooks.pythat both the agent and an outside process can import.app.pyandsandbox_environment.pynow delegate to it — one source of truth, no behaviour change.