Repository navigation
Conversation
nkurraDO
force-pushed
the
managed-agents-sandbox-backend
branch
2 times, most recently
from
October 6, 2026 14:02
51d67b3 to
b02433c
Compare
Adds a tenth sandbox backend that runs each qm computer as a Managed Agents microVM. Sessions are created with agent: none, which asks for a bare sandbox with no managed agent loop, no event-translation runtime and no model credential of its own, so qm keeps its own agent loop and its own approval gates. The backend talks to two planes. Session lifecycle is bearer-authenticated REST under /v2/agents/sessions, with a DigitalOcean IAM token that carries the team identity owning the sessions. Exec and file transfer take a different route: a WebSocket port-forward to guest port 8443, bridged to a local TCP listener, carrying gRPC to the sandbox-agent that every microVM runs. That path has no request deadline, so a command is bounded by qm's SANDBOX_TIMEOUT_SEC rather than by a control-plane buffer. Transfer inside the guest is confined to /workspace, so a scope's home lives at /workspace/home. Sessions are created allowing bash outright, because the provider would otherwise hold every command at its own approval gate behind qm's. Select it with SANDBOX_BACKEND=do-managed-agents and DO_AGENTS_API_TOKEN. Set DO_AGENTS_SNAPSHOT_S3_BUCKET so a scope's home survives losing its session: the provider exposes session checkpoints, but qm does not capture them yet, so a portable tar is the only recovery path. The proto is vendored rather than consumed from a published SDK. That is a stopgap: the REST exec endpoint buffers in the control plane, so it clamps to four minutes and 1 MiB and carries no per-command environment, which rules it out for a general sandbox. When streaming exec reaches the public edge, the vendored proto, the tunnel and the two gRPC dependencies all go away.
The fake service answers the session REST surface and serves a real WebSocket port-forward bridged to a real gRPC sandbox-agent over a temporary directory, so the tests exercise the actual wire path rather than a stub of it: upgrade, bridge, gRPC exec, upload and download. Covers the cases that are easy to get wrong and expensive to debug in production. A port-forward the edge refuses reads as a retryable gone error carrying the rejection, not as a command that may have half run. A transient lifecycle failure while waiting for readiness is polled through, while one that never clears surfaces its own status rather than a readiness timeout. Pause and resume preserve the home, scratch sandboxes are reference counted and never persisted, and the egress allowlist is only claimed when a proxy is actually configured.
docs/managed-agents.md covers what the backend provides, the two planes it talks to, and each operation: create, exec, upload and download, pause and resume, and delete. Pause and resume are both automatic and there is no manual control for either, which is worth stating plainly because the sandbox tool offers no verb for them. The gotchas are the things that cost real debugging time. Deleting a conversation does not delete the microVM, because this backend implements no deep-idle reaping. PUBLIC_API_URL has to be reachable from inside the guest, since microVMs call back into core for connector credentials and file callbacks, and a deployment behind localhost runs shell commands fine while failing every cron and send. The bare base carries no jq, rg or unzip, all of which prompts reach for by name. The ADR records the two asks on the provider and why the vendored proto is a stopgap rather than a choice.
nkurraDO
force-pushed
the
managed-agents-sandbox-backend
branch
2 times, most recently
from
October 6, 2026 18:56
978180e to
b489653
Compare
Resume completes in about a second, but the fixed 2s poll added most of a second interval to every warm turn. Poll quickly at first and fall back to 2s so slow resumes don't hammer the API.
nkurraDO
force-pushed
the
managed-agents-sandbox-backend
branch
from
October 6, 2026 19:00
b489653 to
306f05a
Compare
added 3 commits
October 7, 2026 18:22
deploy/do-managed-agents/Dockerfile is the E2B image plus ripgrep with HOME at the adapter's home, registered on the agentless sandbox base. With DO_AGENTS_TEMPLATE set, the profile advertises jq, rg, unzip and wget as installed. docs/managed-agents.md covers building it.
Contributor
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.
Adds a tenth sandbox backend that runs each qm computer as a DigitalOcean Managed Agents microVM.
Sessions are created with
agent: none, which asks for a bare sandbox: no managed agent loop, no event-translation runtime, and no model credential of its own. qm keeps its own agent loop and its own approval gates, and the provider supplies the machine.How it talks to the provider
Two planes, deliberately:
/v2/agents/sessions, with a DigitalOcean IAM token carrying the team identity that owns the sessions.sandbox-agentevery microVM runs.The second plane exists because the REST exec endpoint buffers in the control plane: it clamps to four minutes and 1 MiB and carries no per-command environment, which rules it out for a general-purpose sandbox. The port-forward has no request deadline, so a command is bounded by qm's own
SANDBOX_TIMEOUT_SEC.Configuration
The bucket matters more than it looks. The provider exposes session checkpoints, but qm does not capture them yet, so a portable tar is the only recovery path: without the bucket, a destroyed or reclaimed session takes the scope's home with it.
Two things worth a reviewer's attention
The vendored proto is a stopgap, not a preference. Every other backend consumes a published SDK. This one vendors
managed-agents-sandbox-agent.proto, which means one wire with two owners in two repos. It is there only because the buffered REST endpoint cannot carry a general sandbox. When streaming exec reaches the public edge, the vendored proto, the tunnel, and both gRPC dependencies all go away. The ADR records this.Deleting a conversation does not delete the microVM. This backend implements no deep-idle reaping, so a scope's machine outlives the conversation and is reclaimed by the provider's idle timeout or an explicit retire.
DO_AGENTS_IDLE_TIMEOUT_SECis the backstop. That is a deliberate choice to document rather than a gap to fix quietly, anddocs/managed-agents.mdsays so.Testing
The fake control plane answers the session REST surface and serves a real WebSocket port-forward bridged to a real gRPC
sandbox-agentover a temp directory, so the tests exercise the actual wire path — upgrade, bridge, exec, upload, download — rather than a stub of it.The cases covered are the ones that are cheap to get wrong and expensive to debug in production:
Verification on this branch: typecheck, lint, and knip clean; the two backend suites pass 41/41; the live smoke passes end to end against the real provider, including pause and resume.
On the full suite, this branch reports 8348 tests with 285 failures. Clean
mainat the same commit reports 8305 tests with the same 285 failures and the same 9 cancelled, so the branch adds 43 tests, all passing, and introduces no new failures. The 285 are pre-existing onmainand unrelated to sandboxes.Each of the three commits typechecks standalone.