Skip to content

feat(nemo-gym): serve a written resources server on its own - #413

Merged
earakely-scale merged 3 commits into
mainfrom
feat/nemo-gym-serve
Oct 30, 2026
Merged

earakely-scale merged 3 commits into
mainfrom
feat/nemo-gym-serve

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

What

python -m agent_env.training.nemo_gym serve FOLDER --port P runs the resources server that python -m agent_env.training.nemo_gym SOURCE ROOT wrote into FOLDER (<root>/resources_servers/<name>), on its own. It runs without Gym's head server and without the agent and environment servers the folder's config names.

Why

verifiers' built-in NeMo Gym taskset (env.taskset.id = "nemo-gym"), which prime-rl trains through, plays a Gym dataset against a resources server at env.taskset.task.resources_url. Its managed mode starts only servers from NeMo Gym's own published package, so our server has to run on its own. Until now the only way to start it was gym env start with the whole written config. That also starts simple_agent, the legacy_agent environment server and the head server, none of which a verifiers run uses.

python -m agent_env.training.nemo_gym http://127.0.0.1:8000 gym-root
python -m agent_env.training.nemo_gym serve gym-root/resources_servers/gridsim_v1 --port 9100
# then: vf-eval nemo-gym --env.taskset.dataset gym-root/resources_servers/gridsim_v1/data/eval.jsonl \
#   --env.taskset.task.resources-url http://127.0.0.1:9100 --env.agent.harness.id null

How

  • server.serve(folder, host=, port=) reads the folder's config. It builds AgentEnvResourcesServer the way verifiers' own launcher builds Gym's servers: an explicit config, a ServerClient whose stand-in head server nothing calls, then setup_webserver, setup_liveness, setup_exception_middleware and uvicorn. A bundle config still serves the bundle for the server's lifetime, as under Gym.
  • The command becomes a click group with write and serve. Any other first argument is write's, so python -m agent_env.training.nemo_gym SOURCE ROOT, as released and documented, works unchanged.
  • Writing still works without the nemo-gym extra. Writing doesn't need it, and the unit tier imports the command without it. So __main__ imports the server in a guarded top-level import, and serve reports the extra's install hint when it's missing. The import adds about a second to write when the extra is installed.
  • omegaconf joins the nemo-gym extra, under Gym's Python marker. Gym's ServerClient takes an omegaconf DictConfig, so the server now imports it directly. The dependency guard learns the nemo-gym and omegaconf module paths it can't read when the extra isn't installed. The lock gains two lines.
  • --host defaults to loopback. The server checks no token, and the help says to keep it off public interfaces.

Tests

  • New in the nemo-gym tier, test_serve_runs_a_written_server_on_its_own_at_the_port_it_is_given:
    • It writes the server for the tier's loopback bundle and starts python -m agent_env.training.nemo_gym serve . as its own process, from inside the written folder.
    • It plays a written row through seed, a tool call and verify with a cookie-keeping client: reward 1.0, not masked, episode torn down.
  • The dependency guard and tst/unit/training pass in a dev-only venv without nemo-gym or omegaconf, as the unit job runs them; the guard and tst/nemo_gym pass with them installed.
  • tst/nemo_gym and tst/unit/training pass locally on nemo-gym 0.7.0 (45 passed). The existing CLI unit test covers the SOURCE ROOT form through the default.
  • Checked by hand with nemo-gym made unimportable:
    • write imports and runs.
    • serve exits 1 with requires pip install 'agentenv-framework[nemo-gym]', on Python 3.13.14 or later.
    • --help lists both commands.
    • An option before SOURCE still routes to write.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the previous folder lookup issue is fixed.

Summary

Adds a standalone command for running a written NeMo Gym resources server.

  • Written NeMo Gym resources servers can run without Gym’s launcher.

No new actionable issues were found in the changes since the previous review. Tests were not run during this review.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  CLI["serve FOLDER --port P"] --> Folder["Resolve folder"]
  Folder --> Config["Read written config"]
  Config --> Server["Build resources server"]
  Server --> App["Set up web app"]
  App --> Uvicorn["Listen on requested host and port"]
Loading

Reviews (2) · Last reviewed commit: "fix(nemo-gym): serve resolves its folder..." · Reviewed by Greptile

`python -m agent_env.training.nemo_gym serve FOLDER --port P` runs the
resources server `write` wrote into FOLDER without Gym's head server or
the agent servers its config names, for a trainer that takes a resources
server's URL. verifiers' NeMo Gym taskset (prime-rl's) does: its managed
mode starts only servers from NeMo Gym's own package. The server is built
as verifiers' own launcher builds Gym's servers.

The command becomes a group with `write` and `serve`; any other first
argument is write's, so `python -m agent_env.training.nemo_gym SOURCE
ROOT` works as before. Writing doesn't need the nemo-gym extra, so
`__main__` imports the server guarded and `serve` reports the extra's
install hint when it's missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale and others added 2 commits October 30, 2026 12:16
serve builds Gym's ServerClient, whose config must be an omegaconf
DictConfig, so the server imports omegaconf directly. Declare it in the
nemo-gym extra under Gym's marker, and teach the dependency guard the
nemo-gym and omegaconf module paths it can't read when the extra isn't
installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The folder's name is the server's, and Path(".").name is empty. The serve
test now runs serve . from inside the written folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale merged commit 764ac68 into main Oct 30, 2026
29 of 30 checks passed
@earakely-scale
earakely-scale deleted the feat/nemo-gym-serve branch October 30, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant