feat(sandbox): add OpenShell sandbox provider - #2013
Merged
Conversation
Adds a built-in sandbox provider for OpenShell (github.com/NVIDIA/OpenShell), a policy-enforced sandbox runtime for autonomous agents. The provider drives an OpenShell gateway's gRPC control plane through the synchronous openshell SDK, running blocking calls on a bounded thread pool. - create: CreateSandbox + async READY-phase poll + exec readiness probe; spec.metadata maps to gateway labels, resources.gpu to GPU requirements, provider_options.providers to OpenShell credential providers - exec: streaming ExecSandbox as '<shell> -c <cmd>' with server-enforced timeout; gRPC DEADLINE_EXCEEDED -> error_type=timeout, other RPC/SDK failures -> error_type=sandbox (never raises for command failure) - upload/download: the SDK has no file-transfer API, so uploads stream bytes through exec stdin (mkdir -p && cat) and downloads round-trip through base64 on stdout (binary-safe) - status: sandbox phase mapping (NOT_FOUND -> STOPPED) - close: DeleteSandbox + poll until gone; aclose closes the channel Verified end-to-end against a local gateway (ghcr.io gateway image, docker compute driver, colima): create/ready/probe, exec stdout/exit codes/env/ workdir/timeout, spec.files upload, binary upload/download round-trip, status, and delete cleanup all pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Hemil Desai <hemild@nvidia.com>
ananthsub
reviewed
Jul 29, 2026
…ed client/pool, policy passthrough Addresses ananthsub's review on #2013: - openshell>=0.0.92,<0.1: pass the now-required 'workspace' kwarg on every lifecycle call (configurable via connection.workspace, default 'default'); upper bound because the alpha SDK and its private _proto are load-bearing. A new SDK-conformance test binds the provider's exact call shapes against the installed SDK so signature drift fails unit CI even with fakes; the fakes now enforce 0.0.92 signatures and return real SandboxRef objects. - share one SandboxClient + worker pool per connection config at module scope (refcounted; released on the last aclose), so per-sandbox provider instances no longer allocate a 32-thread pool and gRPC channel each. aclose stops workers (cancel_futures) before closing the channel. - create: only runtime failures are wrapped as OpenShellCreateError (programming errors like TypeError propagate); transient RPC failures (UNAVAILABLE/RESOURCE_EXHAUSTED/ABORTED/DEADLINE_EXCEEDED) retried with backoff reusing the sandbox name, ALREADY_EXISTS recovered via GetSandbox; _wait_ready treats DELETING as terminal; failed cleanup logs a leak warning; marker label applied last so user metadata cannot clobber it. - provider_options validated via OpenShellProviderOptions (unknown keys raise); new escape hatches: policy (SandboxPolicy mapping or YAML path), template_resources / driver_config (SandboxTemplate Struct passthroughs); resources warning reworded to point at template_resources. - close gates the deletion wait on DeleteSandbox's returned bool. - uploads chunked at exec.upload_chunk_bytes (512 KiB default — live gateway rejects gRPC messages over 1 MiB; verified with a 5 MiB upload); download buffering documented. Exec env values coerced to str at the boundary. - probe backoff stable_delay_s defaults to 1.0 and is set in the shipped YAML; exec.concurrency semantics (shared pool, unbounded queue) documented; missing SDK raises ModuleNotFoundError matching other providers; phase mapping built from openshell_pb2 constants instead of hardcoded ints. Verified live against a local gateway: 11/11 smoke checks plus a 5 MiB chunked upload round-trip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
ananthsub
approved these changes
Jul 29, 2026
OlegSudakov
pushed a commit
to OlegSudakov/Gym
that referenced
this pull request
Aug 7, 2026
## Summary Adds a built-in sandbox provider for [OpenShell](https://github.com/NVIDIA/OpenShell), a policy-enforced sandbox runtime for autonomous agents. The provider drives an OpenShell gateway's gRPC control plane through the synchronous `openshell` SDK (new optional dep in the `sandbox` extra), running blocking SDK calls on a thread pool bounded by `exec.concurrency`. ### Provider mapping | `SandboxProvider` method | OpenShell | |---|---| | `create` | `CreateSandbox` + async READY-phase poll + exec readiness probe; `metadata` → gateway labels, `resources.gpu` → GPU requirements, `provider_options.providers` → OpenShell credential providers | | `exec` | streaming `ExecSandbox` as `<shell> -c <cmd>` with server-enforced timeout; `DEADLINE_EXCEEDED` → `error_type=timeout`, other RPC/SDK failures → `error_type=sandbox` | | `upload_file` / `download_file` | the SDK has no file-transfer API: upload streams bytes via exec stdin (`mkdir -p && cat`), download round-trips through `base64` stdout (binary-safe) | | `status` | `GetSandbox` phase mapping (`NOT_FOUND` → `STOPPED`) | | `close` / `aclose` | `DeleteSandbox` + poll until gone / close channel + shut down pool | Documented caveats (see the provider README): no `ttl_s` enforcement (warns), no `entrypoint` (raises), `exec(user=...)` ignored with a warning (no user field in the exec API; sandboxes run as a non-root user). ## Testing - `tests/unit_tests/test_openshell_provider.py`: 60 tests against a fake SDK client (spec/label mapping, ready polling, probe retry/cleanup, exec error taxonomy, upload/download round-trip, phase mapping, close/wait-deleted, config validation). All pass; guarded by `pytest.importorskip('openshell')`. - Live end-to-end against a local gateway (`ghcr.io/nvidia/openshell/gateway:latest`, docker compute driver on colima), exercising the full `AsyncSandbox` surface: create/READY/probe, exec stdout + exit codes, `spec.env` / per-exec env / `workdir` / cwd override, `spec.files` upload at start, 256 KiB binary upload→sha256→download round-trip, server-enforced exec timeout (exit 124), status, delete cleanup — **11/11 checks pass**. - Note: the gateway `latest` image requires `[openshell.gateway.gateway_jwt]` signing keys plus `[openshell.gateway.auth] allow_unauthenticated_users = true` for local plaintext use — the compose `gateway.toml` in the OpenShell repo doesn't include these yet; the provider README's quickstart points at OpenShell's deploy docs. - Full core unit suite: 1202 passed; the 6 failures (`test_benchmarks`/`test_cli_utils`/`test_config_types_help`) are pre-existing ANSI/terminal-formatting assertions that fail identically on `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Hemil Desai <hemild@nvidia.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Adds a built-in sandbox provider for OpenShell, a policy-enforced sandbox runtime for autonomous agents. The provider drives an OpenShell gateway's gRPC control plane through the synchronous
openshellSDK (new optional dep in thesandboxextra), running blocking SDK calls on a thread pool bounded byexec.concurrency.Provider mapping
SandboxProvidermethodcreateCreateSandbox+ async READY-phase poll + exec readiness probe;metadata→ gateway labels,resources.gpu→ GPU requirements,provider_options.providers→ OpenShell credential providersexecExecSandboxas<shell> -c <cmd>with server-enforced timeout;DEADLINE_EXCEEDED→error_type=timeout, other RPC/SDK failures →error_type=sandboxupload_file/download_filemkdir -p && cat), download round-trips throughbase64stdout (binary-safe)statusGetSandboxphase mapping (NOT_FOUND→STOPPED)close/acloseDeleteSandbox+ poll until gone / close channel + shut down poolDocumented caveats (see the provider README): no
ttl_senforcement (warns), noentrypoint(raises),exec(user=...)ignored with a warning (no user field in the exec API; sandboxes run as a non-root user).Testing
tests/unit_tests/test_openshell_provider.py: 60 tests against a fake SDK client (spec/label mapping, ready polling, probe retry/cleanup, exec error taxonomy, upload/download round-trip, phase mapping, close/wait-deleted, config validation). All pass; guarded bypytest.importorskip('openshell').ghcr.io/nvidia/openshell/gateway:latest, docker compute driver on colima), exercising the fullAsyncSandboxsurface: create/READY/probe, exec stdout + exit codes,spec.env/ per-exec env /workdir/ cwd override,spec.filesupload at start, 256 KiB binary upload→sha256→download round-trip, server-enforced exec timeout (exit 124), status, delete cleanup — 11/11 checks pass.latestimage requires[openshell.gateway.gateway_jwt]signing keys plus[openshell.gateway.auth] allow_unauthenticated_users = truefor local plaintext use — the composegateway.tomlin the OpenShell repo doesn't include these yet; the provider README's quickstart points at OpenShell's deploy docs.test_benchmarks/test_cli_utils/test_config_types_help) are pre-existing ANSI/terminal-formatting assertions that fail identically onmain.🤖 Generated with Claude Code