Run a Custom NeMo Gym Environment
A custom Gym environment runs from a NeMo Helix FileSet rather than from the components bundled in the Gym task image. Evaluator stages the FileSet onto job storage, mounts it read-only in an OpenSandbox Gym host, and returns the rollouts through the normal agent-evaluation result bundle.
Prerequisites
- A running NeMo Helix with the Evals plugin.
- An OpenSandbox-capable Kubernetes deployment configured for sandboxed Gym. See Configure Sandboxed Gym.
- A taskset built from Gym rows as described in Evaluate a NeMo Gym Environment.
- A model endpoint reachable from the sandbox.
FileSet-backed Gym environments cannot use colocated platform execution. Evaluator rejects the
submission when
sandboxed_gym_default is disabled or the selected execution profile does not provide compatible
shared PVC storage.
1. Package the environment
The FileSet must contain nemo-environment.yaml at its root. Evaluator accepts two formats, which
differ only in where a server’s dependencies come from:
native-v1: Gym installs each server’srequirements.txtfrom a package index at job start.wheels-v1: dependencies come from a flat, non-emptywheels/directory in the package. No package index is contacted.
The runtime image already provides NeMo Gym and everything Gym itself needs. A wheels-v1
wheelhouse carries only what your servers add on top of that: the packages your requirements.txt
files name, and their dependencies, as wheels built for the image’s Python and platform. Do not
vendor nemo-gym, ray, or the rest of Gym’s own dependencies.
Every agent and resources-server directory that ships code needs exactly one of requirements.txt
or pyproject.toml, in both formats. Gym recognises a server directory by that file; without it the
directory is invisible to Gym, and with both Gym refuses to start it. A directory holding only
configs/ is different: it references the image’s server of that name, such as
responses_api_agents/simple_agent/configs/simple_agent.yaml to run the built-in simple_agent
with your settings, and needs no marker. Evaluator checks these rules at submit time.
A minimal native-v1 resource-server package looks like this:
For wheels-v1, use the same manifest shape with format: wheels-v1, keep the server’s
requirements.txt, and add the wheelhouse that satisfies it:
With requirements.txt listing emoji==2.14.1, this is enough:
A wheels-v1 package may also carry no servers at all, only wheels. Use this when a built-in
environment needs an extra package the image does not ship. Leave config_paths empty; the job
runs the agent and resources server it selects, and the wheels are importable by both.
The package must follow these rules:
- Every
config_pathsentry is relative to the FileSet root and names an uploaded file. native-v1config paths stay underresources_servers/orresponses_api_agents/.- Every
resources_servers/<name>/andresponses_api_agents/<name>/directory that ships code has exactly one ofrequirements.txtorpyproject.toml, wherever its config file lives. A directory with onlyconfigs/references the image’s server of that name. wheels/is flat and contains only.whlfiles.- Do not include
responses_api_models/; model configuration is operator-owned. - Do not include dataset
.jsonlfiles. Store evaluation rows in a separate taskset.
2. Upload the environment
Create an environment FileSet and upload the directory contents:
Keep the trailing slash on ./my-gym-environment/. It places nemo-environment.yaml at the FileSet
root instead of creating an extra directory level.
3. Create the job specification
Create gym-custom-environment.yaml:
The Evals plugin skill includes the same shape as a validated JSON starting point at
skills/nemo-evals-plugin/assets/specs/gym_agent_eval.json.
Replace the service URL, workspace, model, taskset, and component names for your deployment. The model URL must be present in the deployment’s sandbox egress configuration.
If the package declares the selected agent instance, you can omit agent_config. Set
agent_ref_name when the instance name registered by the package differs from agent.
For an environment variable containing a credential, use a platform secret reference:
Do not place credentials in env_vars. Sandboxed submissions reject credential-shaped plaintext
environment variables.
4. Submit the job
CLI
Python SDK
Evaluator compiles two ordered steps:
stage-environmentdownloads the FileSet onto job-scoped persistent storage.agent-evaluateprovisionsnhx-gym-host, collects rollouts, scores them, and destroys the host.
Both platform steps use nhx-tasks; Gym and Ray run in the separate sandbox host.
5. Read the results
Wait for the job to finish, then download the result bundle:
The archive contains trials.jsonl, scores.jsonl, tasks.jsonl, and summary.json, plus Gym’s
output under gym_run/: rollouts.jsonl, the materialized gym_input.jsonl, and the host’s
model-call captures in gym_run/model_calls/. Evidence paths in trials.jsonl are relative to the
bundle root, the directory that holds trials.jsonl. See
Reading Results
for the queryable result record and SDK retrieval path.
Troubleshooting
- FileSet purpose or manifest error: Confirm the FileSet uses
purpose=environmentand contains a valid rootnemo-environment.yaml. - Sandbox unavailable: Confirm the deployment enabled sandboxed Gym and configured OpenSandbox, the runtime image, a shared PVC, and model egress.
- PVC mismatch: The Jobs execution profile and
sandbox_job_storage_pvc_claimmust name the same claim. - Agent returns no rollout: Set
agent_ref_nameto the agent instance registered by the package. - Model connection failure: Add the model host and port to the deployment-owned egress allowlist.
uvreports a package “not found in the cache”, or a Hugging Face load fails on a missing file: The host ran awheels-v1package offline because the deployment allows no egress beyond the model. Add the missing wheel towheels/, or vendor the dataset in the package.