Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
This was referenced Oct 1, 2026
Draft
Draft
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 1, 2026 19:38
aa41669 to
defe5d3
Compare
7 tasks done
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 1, 2026 21:53
defe5d3 to
f481624
Compare
This was referenced Oct 1, 2026
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 1, 2026 22:05
f481624 to
4e9f81d
Compare
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 2, 2026 13:22
4e9f81d to
b72fe50
Compare
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 2, 2026 19:43
b72fe50 to
7f1cfb6
Compare
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 2, 2026 21:17
7f1cfb6 to
412e854
Compare
Every resources server takes part in checkpoints once checkpointing is
on, in one of three modes:
- restart_only (the default): live sessions block a checkpoint until
their rollouts are retired, so an unsupported server fails closed.
- stateless: tool results depend only on the request, so nothing is
exported. The weather example server uses it.
- exported: the server implements export_session_state,
restore_session_states, and retire_session_state. The counter example
server uses it. export_session_state raises KeyError for a session the
server already dropped (for example after a failed verification); the
participant stops tracking it instead of failing the commit.
The session lifecycle comes from /seed_session, /close_session, and
/verify, keyed by the rollout attempt from the rollout context, so no
request body is inspected. Servers whose protocol creates sessions
elsewhere, such as Gymnasium-style servers, call
checkpoint_session_started and checkpoint_session_ended.
The checkpoint_verify class attribute declares whether /verify is safe
to run again after a crash ("replay") or must finish before a
checkpoint ("wait", the default). It is a property of the code, so it is
not configurable. The server reports it in an x-ng-checkpoint-verify
header on every /seed_session reply, which is how callers learn it
without another request, and in its checkpoint status.
Replay-safe requests (/seed_session, and /verify when declared replay)
are admitted even after admission closes. The checkpoint does not wait for
the episode steps that send them, so refusing one would fail its episode.
A session seeded while closed is not part of that checkpoint: it neither
blocks it nor is exported by it, and becomes an ordinary session on
resume.
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Resources session hooks become coroutines, and export takes every session at once: export_session_states(session_ids) returns the state of each session the server still holds. A server whose session state lives outside the process, such as a sandbox per session, can then snapshot it concurrently within the commit. A session left out of the result replaces the KeyError signal for a session the server already dropped. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
…over MCP A resources server with expose_tools_over_mcp and checkpointing failed at startup: MCP auto-exposure refused the checkpoint middleware, because direct MCP dispatch skips middleware. - The checkpoint middleware declares that it applies to the MCP request as a whole, and MCP auto-exposure accepts it. Admission, in-flight counting, and attempt fencing work on the one POST that carries each tool call. - An MCP request names its session with the signed token, not the cookie, so the middleware reads the session from the token and fences retired sessions. The token key is deterministic, so a harness keeps its token across a restore. - While a checkpoint is open, an MCP call waits for resume instead of being refused. MCP clients are third-party agent harnesses that would hand the refusal to the model as a tool error. A waiting call is not in flight, so it does not hold up prepare. - Checkpoint control routes are no longer harvested as MCP tools. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
…for resume While a checkpoint was open, the resources participant refused every request except seeds and replayable verifications, including /close_session. An episode that ends while a checkpoint is open, for example one a controller retired or one whose replay step failed, closes its resources session once from its final cleanup. The refusal was only logged, so the server's release of that session was lost. A /close_session now waits for resume, as an MCP tool call already does. A waiting close is not in flight, so it does not hold up prepare, and it never changes state a commit is exporting. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
- A /close_session for a retired attempt's session is no longer refused as stale. Closing is how the server releases that session's state, and a restart_only server's retire runs no hook, so its state leaked. - Restored sessions no request has used yet are reported as pending, so a commit that no longer continues their episode retires them through the server's retire hook instead of exporting them at every checkpoint. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
… requests in flight A retire now refuses the attempt's sessions while it stops them, waits until every request in flight on them, tool calls over MCP included, has finished, then releases them. The set of sessions retired over the life of the process is gone: nothing remains of a session once its retire replies. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
pthombre
added this pull request to stack #3962
October 2, 2026 22:50
ananthsub
force-pushed
the
ananthsub/partial-ckpt-resources
branch
from
October 2, 2026 23:32
412e854 to
fb28578
Compare
This branch has not been deployed
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.
What changed and why
Every resources server takes part in checkpoints once checkpointing is on, in one of three modes, declared with the
checkpoint_modeclass attribute:restart_only(the default): live sessions block a checkpoint until their rollouts are retired, so a server without support fails closed.stateless: tool results depend only on the request, so nothing is exported. The weather example server uses it.exported: the server implements the session hooks. The counter example server (example_session_state_mgmt) uses it.The session hooks are coroutines, and export takes every session at once:
export_session_states(session_ids),restore_session_states(states), andretire_session_state(session_id). A server whose session state lives outside the process, such as a sandbox per session, can snapshot all of it concurrently within the commit. A session missing from the export result is treated as already dropped (for example, after a failed verification) and is no longer tracked, instead of failing the commit.The session lifecycle comes from
/seed_session,/close_session, and/verify, keyed by the rollout attempt, so no request body is inspected. Servers that create sessions elsewhere (Gymnasium-style servers) callcheckpoint_session_startedandcheckpoint_session_ended.The
checkpoint_verifyclass attribute declares whether/verifymay run again after a crash (replay) or must finish before a checkpoint (wait, the default). The server reports it in thex-ng-checkpoint-verifyheader on every/seed_sessionreply and in its checkpoint status. Replay-safe requests are admitted even after admission closes, because the checkpoint does not wait for the episode steps that send them.Tools called over MCP (
expose_tools_over_mcp: true). A CLI agent harness calls tools over MCP with a signed session token and no session cookie. Before this change, such a server failed at startup with checkpointing on: MCP auto-exposure refuses middleware that direct MCP dispatch would skip, and the checkpoint middleware was one of them.Ending sessions.
/close_sessionis never refused. Closing is how a server releases a session's state. A close that arrives while a checkpoint is open, from an episode that ended during it, waits for resume as an MCP call does; a refusal would lose the release, since the environment server closes once.retire_session_statefor exported servers. Nothing about a retired session remains afterwards.How it works
Where this PR sits in the overall flow
The highlighted part is what this PR adds.
flowchart LR C["Controller<br/>NeMo RL, or rollout collection"] CO["Coordination<br/>prepare, commit, restore, resume, retire"] K["Control plane on every server<br/>phases, lease, storage,<br/>retire: stop, then free"] subgraph G["One participant per Gym server"] E["Environment server<br/>episode steps"] M["Policy model<br/>held responses, generation cuts"] A["Agent<br/>sessions parked at boundaries"] R["Resources server<br/>session state"] end W["Inference worker<br/>stages cut prefixes"] D[("Checkpoint directory<br/>records, then manifest")] L[("Capture ledger<br/>retire and delete from #3938, #3939")] C --> CO --> K K --> E & M & A & R M --> W M --> L G --> D classDef this fill:#fde68a,stroke:#b45309,stroke-width:2px,color:#1f2937 class R thisOne checkpoint, a crash, and the restore, end to end:
This PR
How a resources server takes part, chosen by a class attribute.
flowchart TD M{"checkpoint_mode"} -->|stateless| S["Nothing to export.<br/>Never blocks a checkpoint."] M -->|exported| X["export_session_states at commit<br/>restore_session_states after a crash<br/>retire_session_state on retire"] M -->|"restart_only, the default"| O["A live session blocks prepare<br/>until its rollout is retired"]A session's lifecycle, as the participant learns it from the routes that already define it.
Retire drains a session before releasing it.
Where this sits in the stack
This is one PR in a stack of draft PRs that re-cut partial-rollout checkpointing onto environment servers. Each PR's base is the branch of the PR before it, so each diff shows only that PR's commits.
The stack is based on the token-capture cleanup PRs #3938 (capture ledger
retireanddelete) and #3939 (complete-recordretireanddelete): #3882's base is #3939's branch. The checkpoint stack uses those operations to free the ledgers of retired attempts and to clear a dead execution's capture files before a restore. The striped lock files of #3937 are independent of the stack.ananthsub/partial-ckpt-core): feat(checkpoint): add the participant control plane, episode steps, and coordinationananthsub/partial-ckpt-policy-model): feat(checkpoint): make policy model servers checkpoint participants with generation cutsananthsub/partial-ckpt-model-worker-cuts): feat(token-capture): add worker staging helpers for generation cutsananthsub/partial-ckpt-environment): feat(checkpoint): continue environment server episodes from their boundariesananthsub/partial-ckpt-resources): feat(checkpoint): add the resources server participant with asynchronous session hooks (this PR)ananthsub/partial-ckpt-verifier-declarations): feat(checkpoint): declare five training verifiers stateless with replayable verificationananthsub/partial-ckpt-agent): feat(checkpoint): add the agent session participant and Simple Agent continuationananthsub/partial-ckpt-e2e): test(checkpoint): add a process-level end-to-end suite driven by coordinationananthsub/partial-ckpt-rollout-collection): feat(checkpoint): checkpoint evaluation runs from rollout collectionananthsub/partial-ckpt-telemetry): feat(checkpoint): spans and metrics for partial-rollout checkpointsananthsub/partial-ckpt-multi-worker): feat(checkpoint): resources, agent, and environment servers with several workersPartial-rollout checkpointing lets a training controller, such as NeMo RL, checkpoint Gym while rollouts are in flight and, after a crash, continue those rollouts from their last safe point instead of starting them over. Checkpointing is off by default; with the
checkpoint:block unset, no server installs any checkpoint routes or behavior.Relationship to the old stack (#2939 to #2946)
Issue
No tracking issue exists for this re-cut. The design and the mapping from the old stack are described in this PR series, and the old stack's PRs (#2939 to #2946) carry the original discussion.
Validation
Run on this branch, on top of #3939's branch:
RAY_TMPDIR=/tmp .venv/bin/python -m pytest -q -p no:cacheprovider tests/unit_tests/test_checkpoint_*.py: 117 passed, including, each failing without its change:/close_sessionduring a checkpoint waits for resume, then ends the session;RAY_TMPDIR=/tmp .venv/bin/python -m pytest -q -p no:cacheprovider tests/unit_tests/test_mcp_auto_exposure.py tests/unit_tests/test_checkpoint_resources_mcp.py: 51 passed. The MCP checkpoint tests go through the real control routes and MCP JSON-RPC:RAY_TMPDIR=/tmp .venv/bin/python -m pytest -q -p no:cacheprovider resources_servers/example_session_state_mgmt/tests: 1 passed.RAY_TMPDIR=/tmp .venv/bin/python -m pytest -q -p no:cacheprovider resources_servers/example_single_tool_call/tests: 2 passed.tests/unit_tests, eight processes, withouttest_opensandbox_compose.py, which needs the optionalopensandboxpackage): 6,538 passed, 2 failed. The two failures, a sandbox retry test and a Slurm script test, fail the same way onmainin this development environment.pre-commit run --files <files changed by this PR>: all hooks passed, and no hook modified a file.Signed-off-byline.Rollout evidence
Compatibility
checkpoint_mode,checkpoint_verify,export_session_states,restore_session_states,retire_session_state,checkpoint_session_started,checkpoint_session_ended. All are new; existing servers need no change and default torestart_onlywithwaitverification./seed_sessionreplies carry a newx-ng-checkpoint-verifyheader when checkpointing is on.checkpoint:block setsenabled: true.