Skip to content

feat(osworld): add exact multi-turn training support - #2554

Closed
JeffPengCoder wants to merge 45 commits into
NVIDIA-NeMo:mainfrom
JeffPengCoder:feature/osworld-exact-trace-training
Closed

JeffPengCoder wants to merge 45 commits into
NVIDIA-NeMo:mainfrom
JeffPengCoder:feature/osworld-exact-trace-training

Conversation

@JeffPengCoder

@JeffPengCoder JeffPengCoder commented Aug 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR adds first-class OSWorld support to NeMo Gym for both standalone evaluation and exact multi-turn RL training. It keeps one OSWorld task/evaluator path while allowing training callers to request the evidence needed to reproduce the model calls that actually drove the desktop.

Gym records the semantic trajectory and the real per-turn prompt, generation, token/logprob, media, identity, termination, and evaluator facts. A trainer such as NeMo-RL remains responsible for validating that evidence, converting it into trainable rows, choosing loss masks, computing advantages, and running backward. Gym never invents an append-only token history when a later multimodal prompt was independently rendered or compacted.

The runtime supports Gym Sandbox with local or remote Docker and a pre-provisioned OpenSandbox KVM Pool. The pinned OSWorld dependency retains canonical task configs and evaluator semantics; Gym owns orchestration and does not patch task setup at runtime.

Scope split and follow-ups

The branch stack is:

upstream main
  -> #2554 OSWorld runtime and exact-trace contract
     |-- #3139 sink-window history policy and failure taxonomy
     `-- #3140 AgentENV desktop through an E2B-compatible gateway

Both follow-ups are based directly on this PR and are independent siblings. Because this head lives in a personal fork, they temporarily target upstream main; their diffs shrink to their own increments after #2554 merges. Transport-contract hardening is also kept out of this PR until it can be reviewed as a separate layer.

Design

NeMo-RL or standalone evaluator
              |
      Gym request / scheduler intent
              |
      OSWorld adapter <-> policy model
 model protocol, prompt, response parsing
              |
       runner / action horizon
              |
 OSWorld DesktopEnv -> VM -> task evaluator
              |
 semantic result + exact model-call evidence
              |
 runtime admission       trainer admission
       (Gym)             (training consumer)

The ownership boundaries are deliberate:

  • Adapter: owns model wire format, history rendering, response/action parsing, and lossless parse-error facts. It does not fabricate FAIL, score a task, or decide max_steps.
  • Runner: executes accepted actions, controls the horizon, invokes the evaluator after the final state transition, and records why execution stopped.
  • Evaluator: is the sole authority for the OSWorld task score. Reaching max_steps does not rewrite its result.
  • Runtime admission: Gym classifies execution/evaluation reliability and exposes the compatibility mask_sample view.
  • Trainer admission: the consumer independently validates exact evidence and decides token/loss eligibility; it does not recompute the OSWorld score.

Logical rollout identity is separate from physical execution identity, so scheduler retries cannot silently merge two attempts. Non-idempotent /run transport calls are not retried in place; the scheduler may start a new, separately identified execution. rollout_purpose carries explicit scheduler intent without changing task, prompt, evaluator, or reward semantics, and legacy benchmark callers remain valid when it is absent.

History policy and model protocol are separate contracts. This PR includes fixed-window behavior and the hysteresis low/high-water policy used for 3-10-3 training. Each actual model-call boundary is preserved even when compaction changes the prompt prefix. Additional experimental policies remain in focused follow-ups rather than adding model-specific branches to the runner.

Main changes

  • Adds OSWorld benchmark preparation, task conversion, model/environment probes, fixed-denominator metrics, launch/cleanup wrappers, and user-facing runtime documentation.
  • Adds the OSWorld Responses API agent, runner registry, model/history contracts, exact trace envelope, semantic trajectory records, runtime outcome classification, and stable correlation IDs.
  • Captures ordered model-call evidence including prompts, generated tokens, sampled logprobs, media identities, actions, environment transitions, evaluator result, and termination facts.
  • Adds Gym Sandbox-backed OSWorld execution with local/remote Docker, dynamic service ports, /dev/kvm, immutable qcow2 identity, and run-scoped cleanup.
  • Adds OpenSandbox Pool execution without exposing Pool implementation details to the model or trainer.
  • Adds the OSWorld resources server, session-affine worker registration, capacity accounting, deployment identity, lifecycle management, and payload-free diagnostics.
  • Adds managed runtime dependency checks and source-provenance gates while keeping changing Gym source mountable and deployment images, checkpoints, credentials, and cluster scripts outside the source PR.
  • Adds focused unit and integration coverage for adapters, runner/evaluator ordering, admission, exact evidence, correlation, sandbox providers, resources-server lifecycle, CLI preparation, and runtime dependencies.

Standard preparation and execution

From a clean Linux checkout, prepare a five-task Nano Omni smoke run against a Docker/KVM environment:

uv lock --check
uv sync --frozen --extra dev --extra sandbox

python3 benchmarks/osworld/tools/probe_model_endpoint.py \
  --base-url http://MODEL_HOST:8000/v1 \
  --api-key local-vllm \
  --model SERVED_NANO_OMNI_MODEL \
  --image-count 3

bash benchmarks/osworld/tools/check_environment.sh \
  /absolute/path/to/Ubuntu.qcow2

cd benchmarks/osworld
python3 prepare.py \
  --profile nano_omni \
  --execution-backend gym_sandbox \
  --vm-path /absolute/path/to/Ubuntu.qcow2 \
  --policy-base-url http://MODEL_HOST:8000/v1 \
  --policy-model-name SERVED_NANO_OMNI_MODEL

export OSWORLD_RUN_ID=my-osworld-run
tools/start_control.sh /absolute/run/root

After the control log reports ready, run from a second terminal or supervisor:

cd benchmarks/osworld
tools/run_eval.sh /absolute/run/root

The benchmark README documents the equivalent OpenSandbox Pool flow, split-host Docker setup, full-population task generation, runtime dependency preparation, evidence locations, and run-scoped recovery.

Validation

  • The branch is synchronized with current upstream main at 9d164bf38; feat(osworld): add exact multi-turn training support #2554 currently contains 85 changed files relative to that base.
  • The complete focused current-head OSWorld, Resources Server, rollout/correlation, CLI/runtime, sandbox-provider, and vLLM-model regression suite passes.
  • Ruff lint and format checks pass for every changed Python file; shell syntax and git diff --check pass.
  • The PR-scope audit found no .gitignore, pre-commit, GitHub workflow, root dependency-policy, or lockfile changes relative to current main.
  • Every feature/fix commit through 405e9537a carries the required DCO sign-off.
  • End-to-end OpenSandbox evidence classified all 369 canonical tasks for Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16. It recorded 188 binary successes: 188/369 (50.95%) on the fixed denominator and 188/361 (52.08%) across the 361 evaluable tasks; the other eight were terminal Google Drive infrastructure failures rather than silently dropped rows.

Operational requirements and non-goals

  • The default Docker image is x86_64 and requires Docker, read/write /dev/kvm, the verified qcow2, and sufficient host memory/disk. OpenSandbox instead requires a reachable management API and a compatible pre-provisioned KVM Pool.
  • A run must record the exact Gym, OSWorld, model-protocol, history-policy, model/checkpoint, and runtime identities it actually used. The source contract declares compatible API ranges; a reproducibility record may pin the exact versions used by one experiment.
  • This PR does not implement NeMo-RL advantage calculation, sequence-level loss masking, importance correction, replay buffering, checkpointing, or backward.
  • It does not require unrelated Gym agents to implement exact trace, adopt OSWorld history policies, or use OSWorld admission semantics.
  • It does not include AgentENV/E2B, sink-window, deployment images, model assets, credentials, site-specific Slurm scripts, or raw experiment artifacts; those remain in the follow-ups or deployment/recipe assets named above.

@copy-pr-bot

copy-pr-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@JeffPengCoder
JeffPengCoder force-pushed the feature/osworld-exact-trace-training branch from 1ede45f to 57c9970 Compare August 14, 2026 08:38
Capture semantic model calls and reconstruct exact multi-turn trajectory evidence for policy training.

Add the OSWorld resources server, remote sandbox integration, reproducible runtime dependency checks, and focused coverage needed to exercise the trace contract end to end.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Carry scheduler-owned rollout purpose through both the run schema and Responses metadata, cross-check the carriers at the OSWorld boundary, and emit payload-free diagnostics.

Keep standalone benchmark callers compatible when purpose is absent while bounding complete rollout attempts and sandbox cleanup.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Reject agent and model servers resolved outside scheduler-approved Gym roots so stale image copies cannot silently serve a mixed source stack.

Expose payload-free purpose markers at the final vLLM proxy boundary and cover both accepted and rejected component paths.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
@JeffPengCoder
JeffPengCoder force-pushed the feature/osworld-exact-trace-training branch from 57c9970 to e191ef9 Compare August 14, 2026 09:27
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Allocate a fresh execution ID for each Gym /run dispatch, propagate it through OSWorld child/model/sandbox/result evidence, and keep it out of semantic exact-trace digests. Disable hidden transport replay for non-idempotent /run requests while preserving the public BaseRunRequest JSON shape.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Apply the repository-pinned Ruff 0.9.9 formatter to the execution-trace changes and drop a stale status-poll warning that loses its logging import when merged with current main.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
@JeffPengCoder
JeffPengCoder force-pushed the feature/osworld-exact-trace-training branch from 6d77121 to f799a54 Compare August 15, 2026 02:34
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
@Glorf

Glorf commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

/claude review

@Glorf

Glorf commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@ananthsub + @hemildesai could you take a look on the RL contract + sandbox logic respectively

Comment thread nemo_gym/rollout_collection.py Resolved
Comment thread nemo_gym/rollout_collection.py Resolved
@claude

claude Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

SHIP WITH CARE — the OSWorld env additions are solid and well-tested; my concern is a few shared-path changes riding along in an OSWorld-scoped PR.

Verifier / scoring correctness

  • The new OSWorldResourcesServer.verify() (evaluate → close in finally) is correct and masks on evaluator throw. binary reward via score >= 1.0 matches the existing agent convention.
  • Two shared-collector changes (rollout_collection.py) alter behavior for every agent, not just OSWorld — see the two inline RISK comments (mask_sample reclassification changing eval denominators + retry cost; unconditional retry_transport_errors=False). Neither is wrong for OSWorld; both should be an explicit, re-baselined decision for the other agents that share this loop, or scoped to OSWorld.

Async / operability — looks good

  • session_manager.py wraps every blocking DesktopEnv call in asyncio.to_thread, bounds concurrency with a per-session asyncio.Lock + a manager _lock, and makes /step idempotent by operation_id (bounded to 128). Reaper task is cancelled cleanly on stop().
  • server_utils.global_aiohttp_client_exit now routes close onto the owning loop rather than blindly asyncio.run() — good fix, covered by tests. _connectable_client_host wildcard→loopback mapping is sensible.
  • Docker create reconciliation (_run_create_with_reconciliation) authenticates ownership via label+image before reuse and refuses to remove unrelated collisions — careful and correct.

API compatibility — preserved

  • BaseRunRequest captures _ng_execution_id in a PrivateAttr via a wrap-validator; model_dump() shape is unchanged (asserted by tests). rollout_id_from_run / rollout_context / maybe_rollout_id_from_run_body retained as aliases. No public-surface breakage found.

Dependency hygiene

  • resources_servers/osworld/pyproject.toml guards the heavy OSWorld/torchvision/OCR deps via uv override/exclude; _default_env_factory imports desktop_env lazily so the module stays importable without it. Intra-PR inconsistency worth a deliberate check: this file pins numpy<2 / opencv-python-headless~=4.8.1.78 while the agent installer moves to numpy>=2.1,<2.5 / OpenCV 4.10 — separate venvs so not a conflict, but confirm the resources-server venv actually resolves on py3.13.

Notes (author's call)

  • Several new print(..., flush=True) diagnostic markers on the hot model/dispatch path (OSWORLD_MODEL_PURPOSE|, NEMO_GYM_VLLM_PROXY_PURPOSE|, per-dispatch /run summary). Payload-free and fine, but they're now unconditional stdout on every model call across all vLLM traffic, not just OSWorld.

No BLOCKERs. Recommend confirming the two shared-collector changes are intended for non-OSWorld agents before merge.

Capture semantic model calls and reconstruct exact multi-turn trajectory evidence for policy training.

Add the OSWorld resources server, remote sandbox integration, reproducible runtime dependency checks, and focused coverage needed to exercise the trace contract end to end.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Carry scheduler-owned rollout purpose through both the run schema and Responses metadata, cross-check the carriers at the OSWorld boundary, and emit payload-free diagnostics.

Keep standalone benchmark callers compatible when purpose is absent while bounding complete rollout attempts and sandbox cleanup.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Reject agent and model servers resolved outside scheduler-approved Gym roots so stale image copies cannot silently serve a mixed source stack.

Expose payload-free purpose markers at the final vLLM proxy boundary and cover both accepted and rejected component paths.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Allocate a fresh execution ID for each Gym /run dispatch, propagate it through OSWorld child/model/sandbox/result evidence, and keep it out of semantic exact-trace digests. Disable hidden transport replay for non-idempotent /run requests while preserving the public BaseRunRequest JSON shape.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Apply the repository-pinned Ruff 0.9.9 formatter to the execution-trace changes and drop a stale status-poll warning that loses its logging import when merged with current main.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
@JeffPengCoder
JeffPengCoder force-pushed the feature/osworld-exact-trace-training branch from c90f2fe to ccbb506 Compare September 2, 2026 04:01
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Brings NVIDIA-NeMo/Gym 428ff23 into the OSWorld exact-trace branch, moving
the baseline from nemo_gym 0.5.1 to 0.7.0rc0. 621 files merged cleanly; six
needed a decision, and none of them is a pure 'take one side':

server_utils.py -- upstream added a base-URL cache keyed by server name and
relocated _build_server_base_url. The branch's _connectable_client_host fix
(a wildcard bind address is not a connectable client target, and a
proxy-aware client will route 0.0.0.0 externally) is reapplied on upstream's
single surviving definition rather than kept as a second one.

rollout_collection.py -- both sides restructured the same /run dispatch. The
result is a union: the branch's dispatch summary, retry_transport_errors=False
(replaying /run can create a second physical VM run) and execution-identity
validation, plus upstream's wall-clock latency and route_failures_to_sidecar
handling. The branch's masked_sample classification now runs after upstream's
token-capture finalization, so a mask raised there is classified too, not
only one the agent set itself; its duplicate no_persist/failure_class
assignment is dropped in favour of upstream's earlier one.

osworld_agent/tests/test_app.py -- both sides define setup_server_client_mocks
with incompatible signatures: the branch patches the loader, upstream passes
the client. Upstream's definition survives and the branch's six call sites
pass mock_load_from_global_config.return_value, which is the client the code
under test actually receives, so their intent is unchanged.

The remaining test conflicts were additive on both sides with no colliding
definition names.
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
The 621-file automerge left four defects that no conflict marker pointed at.
Each was found by running the suites, not by reading the diff:

- rollout_collection lost 'from copy import deepcopy'. The branch dispatches a
  deep copy of every row so a fresh execution id never mutates the caller's
  object; without the import every dispatch raised NameError. 27 tests.
- server_utils kept the branch's '_retry_transport_errors' guards but upstream
  had meanwhile extracted the retry loop into _request_with_retries, leaving
  the guards reading a name that function does not take. The flag is now
  threaded through both _traced_request and _request_with_retries, so enabling
  HTTP tracing cannot silently restore retries on a non-idempotent /run.
- The osworld agent now reads global config off its own server_client rather
  than reloading it globally, so tests that patched
  app.ServerClient.load_from_global_config were patching a symbol upstream had
  removed. They build the client through make_server_client() instead, which
  wires the attribute the agent actually reads.
- Two test bodies had been spliced from both sides, so upstream's construction
  silently overwrote the branch's and the assertions below it tested nothing.

Also corrects a resolution of my own: masked_sample classification is back
where the branch had it, before token-capture finalization. Moving it after
looked like an improvement -- it would also catch masks raised by capture --
but it reclassified a rollout that upstream's own test expects to score, and
faithfully merging the branch is the job here, not improving it.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
@anwithk
anwithk requested a review from Glorf September 9, 2026 18:18
Integrate main dbd26a9 while preserving role-local uv policy and sandbox recovery. Honor explicit prebuilt-venv reuse and shared setup locking. Align OSWorld score aggregation with shared masking/coverage semantics and add regression coverage.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Describe optional dataset metadata without changing session initialization or canonical tasks. Cover legacy and migrated row shapes, preserve task payloads, and allow verify-only rows. Schema and OSWorld resources suite: 330 passed.

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
bxyu-nvidia pushed a commit that referenced this pull request Sep 22, 2026
…3592)

## What does this PR do?

Extract the OSWorld-owned changes from #2554 and #3140 into one
environment-focused PR. Both original PRs and their branches remain
unchanged. This branch is based on upstream `6bbc05ed9`; the
implementation comes from the AgentENV benchmark source `360b0df13`.

- Exact multi-turn evidence, logical rollout identity,
fixed-window/hysteresis history policies, and explicit train/eval
contracts.
- Runner-owned episode limits and termination facts, evaluator-owned
rewards, and separate admission decisions. Canonical OSWorld tasks and
evaluator semantics are preserved.
- Stateful OSWorld resources server, remote environment support, runtime
declarations, benchmark preparation, and regression tests.
- AgentENV desktop adaptation through Gym's E2B provider: prebuilt
templates, service-port forwarding, configurable noVNC port, and bounded
cleanup after failed startup.

Changes are limited to `benchmarks/osworld`, the relevant `examples`
config, `resources_servers/osworld`, and
`responses_api_agents/osworld_agent`. OSWorld-specific dependency-policy
tests move into the agent suite.

### Companion and merge dependency

The companion **Gym Core runtime-contracts PR #3591** owns the generic
installer, rollout collection, HTTP lifecycle, sandbox providers, and
shared `vllm_model` changes. E2B gateway/hostname endpoint resolution
and SDK transport integration belong there because they serve any E2B
consumer, not just OSWorld.

The two diffs have no overlapping files and both target `main`. This is
review/scope separation, not a claim of runtime independence: **the
complete AgentENV path requires the companion Core PR**, particularly
`E2BProvider.endpoint()`. The Core PR should land first for complete
AgentENV enablement.

## Validation

- OSWorld agent/resources/benchmark suites: **353 passed**.
- Combined OSWorld + Core tree: **1,425 passed, 2 skipped** across both
component suites and focused core, sandbox, transport, model, and
compaction regressions. This includes local HTTP connection-sharing
tests.
- `pre-commit run --all-files`, `uv lock --check --offline`, and `git
diff --check`: passed.
- Both skips require the optional E2B SDK, absent locally: real-SDK
call-shape introspection and E2B/OpenSandbox cross-provider connection
sharing. Other local HTTP-sharing fixtures passed. GitHub lint,
copyright, DCO and secret detection passed.
- Commands for the environment suite:

```bash
NEMO_GYM_EXTRA_ROOTS="$PWD" PYTHONPATH=. python -m pytest \
  responses_api_agents/osworld_agent/tests resources_servers/osworld/tests \
  benchmarks/osworld/tests --import-mode=importlib -q -o addopts='' -o log_cli=false
```

An exhaustive Git-object reconstruction audit accounts for all **92**
predecessor change paths: **80 byte-identical**, six clean
upstream/source merges, two E2B transport/test conflict adaptations,
three dependency/test-organization updates, and one comment-only
false-positive annotation on the golden-prompt SHA256. The hash and
assertion are unchanged. No unaccounted paths; unrelated upstream files
and original executable modes are preserved. Runtime-policy assertions
for `vllm_model` remain in the companion PR rather than making the
OSWorld test suite own them.

## Rollouts

The recorded predecessor completed **361/361** canonical OSWorld tasks
on AgentENV: **46.9182% raw reward**, **159/361 binary successes**, no
missing/duplicate/masked rows. It used Omni v3, fixed-three-image
history, 100 steps, temperature 0.60, and top_p 0.95. Four model-format
terminations were evaluator-scored; this is not a claim of zero format
failures.

The actual CW-DFW run checkout was rechecked:
`360b0df131de7671e2a6e243f21c8150a061c5ce`, clean. [Recipe and run
evidence](https://gitlab-master.nvidia.com/jepeng/rl/-/blob/36462b79e257cf054c67228d0942c069af29deee/osworld/recipes/benchmarking/nano-omni-osworld-bench/models/nano-omni-v3/cw-dfw-h100-x86_64/agentenv-canonical-s100/README.md).

**No fresh GPU rollout or full 361-task evaluation was run for this
split.** These scores belong to the predecessor; they are not a new
benchmark claim for the split on newer main. No new environment behavior
was intentionally introduced by the split.

## Compatibility and benchmark impact

The task definitions, evaluator, prompts, parser, history-policy
implementation, and exact-trace implementation are unchanged from the
tested source. Training's hysteresis policy remains configurable; the
recorded benchmark's fixed-3 setting is not imposed on training. The
obsolete `httpx-aiohttp` requirement is removed because newer upstream
owns `GymAiohttpTransport`; Core preserves the no-config worker
guard/fallback. Other agent implementations are not modified here.

The automatic Claude review currently fails while obtaining its OIDC
token (`ACTIONS_ID_TOKEN_REQUEST_URL` is unavailable). This is an
upstream workflow permission issue, not a code-review finding; no CI
configuration is changed in this PR.

---------

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Glorf added a commit that referenced this pull request Sep 28, 2026
## Summary

Add an opt-in `sink_window` history policy to the OSWorld Nemotron
adapter: retain the earliest screenshots alongside a recent-image
window, with intervening turns represented as text in chronological
order.

This branch includes upstream `main` at `d4c0f86c7` through a normal
merge, including the NumPy metadata fix #3649, CI preflight update
#3658, and sandbox lifecycle telemetry #3633. The OSWorld foundation
from #2554/#3140 was consolidated and merged through #3592, so this PR
no longer carries the old exact-trace/Core stack or depends on #2554. It
does not require #3591. No separate issue is needed for this follow-up
policy extension.

## Changes

- Add configurable sink, low-water and high-water counts. Both
watermarks include the sink; equal watermarks slide, while unequal
watermarks provide hysteresis.
- Represent non-contiguous image selections with intervals and render
folded text in chronological order.
- Distinguish context overflow, transport failure, truncated output,
empty output and unparseable output; retain
`agent_outcome_family=model_response_invalid` for compatibility.
- On context overflow, reduce the recent-image window within the
existing retry budget, preserve the sink/current observation, record
actual shrink events, and stop when further reduction is impossible.
- Preserve main's immediate model-timeout propagation. Report the
terminal attempt's completion fact so an earlier malformed sample cannot
hide a subsequent transport failure.

The latest synchronization also annotates six deterministic SHA-256
prompt goldens that the previous secrets-detector run falsely identified
as credentials. Only those literal lines are annotated; the digest
values, assertions, repository scanner configuration, and baseline are
unchanged.

## Design and compatibility

History policy selects image/text turns; the adapter owns model protocol
rendering and parsing. The runner owns horizon and runtime failure
handling, the evaluator owns reward, and runtime admission owns masking.
This PR does not change those ownership boundaries or add a
training/evaluation switch.

Fixed-window and hysteresis policy IDs and normal-path rendered prompts
remain covered by deterministic golden tests, including fixed-3 and
3-10-3. Sink-window is opt-in, not a new default or a claim of improved
benchmark score. Context-overflow recovery and more precise failure
outcomes are intentional behavioral changes and may affect failed-run
outcomes. The legacy scalar `image_window_start` accessor rejects
non-contiguous plans; consumers should use `image_intervals` or per-turn
decisions.

Scope relative to current main remains limited to
`responses_api_agents/osworld_agent/`: two implementation files,
documentation, and tests. No Gym Core, dependency, deployment,
sandbox-provider or model-server changes are included in the PR diff.

## Validation

Re-run on the final main-synchronized tree:

- **440 passed, zero skipped** across OSWorld agent, resource-server and
benchmark tests; one non-failing Starlette deprecation warning.
- `pre-commit run --all-files`: passed.
- `uv lock --check --offline`: passed.
- `git diff --check`: passed.
- The same `detect-secrets==1.5.0` hook and checked-in baseline used by
CI passed on all nine PR-scoped files after the inline false-positive
annotations.
- Existing model-timeout propagation, runner admission, prompt-parity,
sink selection, overflow recovery and policy-identity regressions
passed. The unchanged-overflow retry and mixed parse/transport
completion bugs had been reproduced before their earlier fixes.

Test invocation, using an existing compatible development environment
from this checkout:

```bash
export PYTHONPATH="$PWD"
export NEMO_GYM_EXTRA_ROOTS="$PWD"
python -m pytest \
  responses_api_agents/osworld_agent/tests \
  resources_servers/osworld/tests \
  benchmarks/osworld/tests \
  --import-mode=importlib -o addopts='' -o log_cli=false -q
pre-commit run --all-files
```

The explicit source root prevents an older editable checkout from
shadowing the branch under test; importlib mode avoids the shared
`osworld` test-package name collision. These checks are local evidence,
not a claim that the upstream CI run has completed.

## Score reproduction

OSWorld 361 tasks, Nemotron-3-Nano-Omni v3 (`24e67ea0`), fixed-3
history, 100 steps, one A/B run per arm. Control = main `d4c0f86c7` +
#3591 (needed for the E2B `endpoint()` on AgentEnv); treatment = control
+ this PR. Raw SR 44.61% → 46.62% (Δ +2.01 pp, paired 95% CI [−2.12,
+6.07] pp); binary 154 → 159 of 361 (McNemar p = 0.59); 0 masked and 0
missing in both arms; identical history-policy and agent-contract IDs.
No degradation. The context-overflow shrink path was not triggered in
either run.

---------

Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Co-authored-by: Michał Bień <mbien@nvidia.com>
@svcnvidia-nemo-ci svcnvidia-nemo-ci added area:environment Individual environments, benchmarks, verifiers, and environment-specific resources servers feature New capabilities, enhancements, or enablement work labels Oct 20, 2026
@JeffPengCoder

Copy link
Copy Markdown
Collaborator Author

Closing this original combined PR in favor of the scope-separated follow-ups:

The legacy compaction-session change was dropped from the core split in favor of #3368, which is also still open.

The remaining work continues in those focused PRs. The source branch is retained for provenance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:environment Individual environments, benchmarks, verifiers, and environment-specific resources servers feature New capabilities, enhancements, or enablement work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants