verify() method that returns the reward.
NeMo Gym runs code through a provider-neutral sandbox API, nemo_gym.sandbox. A sandbox provider creates the sandboxes on a backend. This page adds a provider that runs each NeMo Gym sandbox as a Superserve sandbox. Then it builds a small environment: a model writes Python, each run_python tool call runs the code in a new Superserve sandbox, and verify() scores the final answer. Model-written code never runs on your machine.
Setup
NeMo Gym needs Python 3.13.14 or later, uv, and git. Clone NeMo Gym, install it, and add the Superserve SDK:Gym folder.
How it works
- NeMo Gym code creates a sandbox with
AsyncSandboxand aSandboxSpec.AsyncSandboxcalls the provider to create the sandbox, run commands, move files, read the status, and close the sandbox. SuperserveProvidermakes these calls with the Superserve Python SDK.register_provider()makes it available under the namesuperserve.- A config block selects the provider and its settings. A resources server refers to the block by name, so you change the backend in config, not in code.
- The resources server on this page creates a sandbox for each
run_pythoncall, runs the code, and deletes the sandbox.
Add the provider
Create the folderresources_servers/superserve_python and save this file in it as superserve_provider.py. The highlighted lines are the Superserve calls.
resources_servers/superserve_python/superserve_provider.py
SandboxSpec fields to Superserve sandbox options:
The provider has two settings.
template is the default template, superserve/base when you do not set it. deny_out is a list of CIDR ranges that the sandbox cannot reach. ["0.0.0.0/0"] blocks all outbound traffic. See Networking.
Try the provider
Save this file astry_superserve.py in the Gym folder. It registers the provider, starts a sandbox from the superserve/python-3.11 template, and runs a script that SandboxSpec.files uploads.
try_superserve.py
async with stops the sandbox when the block exits, and the provider deletes it.
Build the environment
The environment gives the model one tool,run_python, and rewards the correct final number.
Resources server
Save this file asresources_servers/superserve_python/app.py. The highlighted lines register the provider, read its config block, and run the tool call in a sandbox.
resources_servers/superserve_python/app.py
verify() reads expected_answer from the task and compares it with the last number in the final answer by value, so 249.0 and 2.49e2 match 249, and 0.249 and .249 do not. The # type: ignore[override] comment is there because verify() takes a request type with that extra field.
Config
Save the resources server and agent config asresources_servers/superserve_python/configs/superserve_python.yaml. sandbox_provider: sandbox names the config block that selects the provider.
resources_servers/superserve_python/configs/superserve_python.yaml
resources_servers/superserve_python/configs/superserve.yaml. The sandbox block selects the superserve provider and passes the settings to its constructor. Here every sandbox boots the superserve/python-3.11 template and has no outbound network access.
resources_servers/superserve_python/configs/superserve.yaml
Dependencies
NeMo Gym installs each server in its own virtual environment. Save the server’s dependencies asresources_servers/superserve_python/requirements.txt:
resources_servers/superserve_python/requirements.txt
Tasks
Save the tasks asresources_servers/superserve_python/data/example.jsonl. Each line has the model input, the run_python tool definition, and the expected answer.
resources_servers/superserve_python/data/example.jsonl
Run rollouts
The agent calls the model through the OpenAI Responses API. Save the model settings asenv.yaml in the Gym folder:
env.yaml
SUPERSERVE_API_KEY, and collect one rollout for each task:
results/superserve_python_rollouts.jsonl has the full rollout, with the tool calls, the tool outputs, and the reward. In this sample run, the model first tried to import sympy. The superserve/python-3.11 template does not include sympy, so the import failed. The model then wrote a sieve in plain Python. A summary of that rollout:
Clean up
Eachrun_python call deletes its sandbox when the call ends. If a server stops before it closes a sandbox, the sandbox pauses after ttl_s and is then deleted. Press Ctrl+C in the first terminal to stop the servers.
Learn more
NeMo Gym documentation
Read about NeMo Gym environments, agents, and training.
NeMo Gym sandbox API
See the provider-neutral sandbox API and the provider contract.
Commands
Run commands in a sandbox with the Superserve SDK.
Templates
Build a template with the packages your environment needs.