Skip to content

feat(sandbox): add an Agent37 sandbox provider - #481

Merged
earakely-scale merged 3 commits into
scaleapi:mainfrom
vishnukool:agent37-sandbox-provider
Nov 4, 2026
Merged

earakely-scale merged 3 commits into
scaleapi:mainfrom
vishnukool:agent37-sandbox-provider

Conversation

@vishnukool

@vishnukool vishnukool commented Nov 4, 2026 •

Copy link
Copy Markdown

What and why

Adds Agent37 as a built-in sandbox provider, agent37. It needs no extra: it drives Agent37's public REST API with httpx, which agent-env already depends on.

[sandbox.providers.agent37.config]
api_key = "secret:agent37_api_key"   # or "env:AGENT37_API_KEY"
region = "us"                        # optional: "us", "eu" or "ap-south"

Closes #479

  • Sandboxes: each is an Agent37 vm instance of the agent37-ubuntu template, Ubuntu with its own kernel, Docker, Compose v2 and buildx, dockerd already running. Commands run as root, so the sudo agent-env prefixes is dropped.
    • Each request gets the smallest of the four VM shapes (2 vCPU / 4 GiB, 4 / 8, 4 / 16, 4 / 32) that covers its CPU, memory and disk, with that shape's largest disk (12, 20, 40 or 80 GB). A larger request is refused, not shrunk.
    • create_vm(image=...) is refused and boot_mode is logged as ignored.
    • Agent37 has no delete-after timer, so timeout is not enforced; the started log line says so, and the README covers finding a crashed run's VMs (named agentenv-<random>, attribution in their metadata).
  • Ports: each exposed port is an Agent37 public port, https://<random>.agent37.app, created with the instance. They live on the instance record, so get_sandbox on a freshly built provider restores them.
  • Commands: exec goes straight to the host running the instance (sandbox.agent37.app), with a random run name on each command. Agent37 answers a resend under the same name with the first run's result, waiting for it if it is still running, so a dropped connection (including a TLS error httpx passes through unwrapped) and a refusal before the command started (503 at the per-instance command cap) are resent without the command running twice. When no resend gets an answer, exec returns -1, which exec_script retries. Agent37 stops a command at 15 minutes (exit 137).
  • Creates: a create that fails or is cancelled deletes what it made, found by its unique name when the answer was lost. A VM whose Docker never readies is deleted before the error is raised.
  • Network policy: Agent37 restricts egress to IPv4 addresses and ranges, never hostnames, and every effective allowlist carries the platforms' hostnames, so any restricted policy is refused, as the provider contract asks. get_sandbox reports the instance's applied network field. *.agent37.app joins the built-in egress floor, so an allowlisted workload on another provider can still reach an env hosted on Agent37.
  • Known limit: exec returns at most 512 KB per stream. read_vm_file reads 4 MiB ranges as base64, so copying a file off the VM to a store that cannot sign URLs (the local stores) fails loudly with its truncation error rather than writing a short file; S3 and Cloud Storage are unaffected, since the VM uploads to the signed URL itself. The README says so.
  • Wiring:
    • _BUILTIN_SANDBOX_PROVIDERS, the CLI's --sandbox help, AGENTS.md and config.example.toml;
    • remote_sandbox_is_available, the stamping and capability tables, and the pinned egress floor;
    • the agent37 parameter of the gateway and task-step integration suites.

Website

Supported sandboxes should get an Agent37 row, its logo, and a short section with the config above.

How it was tested

Against a funded Agent37 workspace, from a laptop:

  • agent-env run hello --sandbox agent37 passes (about 5 s end to end) and tears its VM down.
  • tst/integration/providers/sandbox_providers/agent37_sandbox_smoke_test.py: 3 passed (~18 s). It serves a container on 8080 through the public URL, writes and reads back a 1 MiB file, reads a 300 KB file, reconnects, runs 12 commands at once, and checks terminate is idempotent.
  • tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[agent37]: a full gateway env deploy with docker compose, images pushed over exec from the local registry store, passed in 573 s.
  • A 1,000 s command comes back at 900 s with exit 137, which is what the README and exec docstring say.
  • Over a home connection about 1 in 150 execs hit a TLS error (SSLV3_ALERT_BAD_RECORD_MAC, which httpx raises unwrapped); during the gateway deploy 45 of 6,847 execs were resent under their run name and all landed. The same rate shows up with curl from that machine and never from inside a VM, so it is that network, but the resend is why it costs nothing.

Offline:

  • pytest tst/unit/providers/sandbox_providers/: 1666 passed, 7 skipped.
  • ruff check and ruff format --check clean.

RetriggerView in GreptileConfidence Score: 5/5

The latest changes appear safe to merge and address the previous cleanup finding.

Summary

Adds agent37 as a built-in Docker-capable VM provider, with public port URLs, reconnect support, configuration examples, and tests.

  • Agent37 can host agent-env sandboxes on Docker-ready virtual machines.
  • Agent37 sandbox commands keep their original result when a connection drops.
  • Agent37 public URLs stay reachable from restricted sandboxes.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Create VM] --> B{Create succeeds?}
  B -->|Yes| C[Check Docker]
  C -->|Ready| D[Return sandbox]
  C -->|Fails| E[Wait for deletion]
  B -->|Fails or cancelled| F[Wait for create to settle]
  F --> G[Use returned ID or find unique name]
  G --> E
  E --> H[Raise original error]
Loading

Reviews (3) · Last reviewed commit: "fix(sandbox): Agent37 instance calls giv..." · Reviewed by Greptile

Agent37 VMs (agent37-ubuntu, Docker and Compose inside) as the built-in
agent37 provider, over Agent37's REST API with httpx, so no extra.

Closes scaleapi#479
@vishnukool
vishnukool requested a review from a team as a code owner November 4, 2026 07:22
@earakely-scale
earakely-scale merged commit c655289 into scaleapi:main Nov 4, 2026
23 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Agent37 as an in-tree sandbox provider

2 participants