[feat] Add E2B sandbox running Pi, bake harnesses into template#5045
[feat] Add E2B sandbox running Pi, bake harnesses into template#5045junaway wants to merge 4 commits into
Conversation
Baked E2B template (daemon+pi+node22), e2b provider branch with timeoutMs/autoPause leak backstop, refuse-restricted-network under strict, Pi asset-prep on E2B handle, E2bConfig, unit tests, docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…+ harnessFiles containment Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
D2: extend e2b.Dockerfile to pre-install codex, opencode, and claude (in
addition to the already-baked Pi), replicating what `install-agent` does
manually since it hangs in the E2B builder. Adds
AGENTA_AGENT_SANDBOX_{CODEX,OPENCODE,CLAUDE}_INSTALLED env levers mirroring
Pi's, documented as visibility-only since (unlike Pi) the daemon has no
skip mechanism for these three — the bake still pays off via the daemon's
own already-installed fast path.
D3: add an E2B idle-refresh keepalive (e2b-keepalive.ts) that calls the
E2B SDK's `Sandbox.setTimeout` on an interval so E2B_TIMEOUT_MS measures
idle time since the last liveness proof, matching Daytona's autostop
semantics, instead of acting as a hard wall-clock cap on the whole run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds E2B as a second remote sandbox provider for the services/runner sandbox-agent engine, including an E2B-specific relay path, idle-time keepalive semantics, workspace write hardening, and a baked E2B template image (Pi + forward-looking harnesses) to reduce cold-start latency.
Changes:
- Add E2B provider support end-to-end (plan normalization, provider creation, remote-vs-local gates, and docs/config).
- Introduce E2B timeout keepalive that refreshes
Sandbox.setTimeoutperiodically to approximate Daytona-like idle semantics. - Harden workspace file writes for both local and remote sandboxes with path-traversal containment checks, plus add/extend unit tests.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| services/runner/src/engines/sandbox_agent/provider.ts | Adds E2B provider branch and E2B timeout/env option builder. |
| services/runner/src/engines/sandbox_agent/run-plan.ts | Introduces isE2B / isRemoteSandbox, E2B cwd + relay dir behavior, and E2B network-policy refusal. |
| services/runner/src/engines/sandbox_agent.ts | Wires E2B asset prep + E2B keepalive; generalizes remote gates from Daytona-only to any remote sandbox. |
| services/runner/src/engines/sandbox_agent/e2b.ts | Adds E2B-specific Pi asset prep and env helpers. |
| services/runner/src/engines/sandbox_agent/e2b-keepalive.ts | Implements idle-refresh keepalive via Sandbox.setTimeout. |
| services/runner/src/engines/sandbox_agent/workspace.ts | Switches to isRemoteSandbox and adds path-traversal containment for harness file writes (local + remote). |
| services/runner/src/engines/sandbox_agent/mcp.ts | Adds isRemote gating for internal MCP channel and remote relay log labeling. |
| services/runner/src/engines/sandbox_agent/usage.ts | Generalizes usage-file reads from Daytona-only to any remote sandbox. |
| services/runner/src/engines/sandbox_agent/pi-assets.ts | Adjusts local Pi asset prep gating to exclude any remote sandbox. |
| services/runner/tests/unit/session-mcp-layering.test.ts | Updates MCP layering tests for new isRemote input. |
| services/runner/tests/unit/sandbox-agent-workspace.test.ts | Updates workspace tests for isRemoteSandbox and adds E2B + path-traversal test coverage. |
| services/runner/tests/unit/sandbox-agent-usage.test.ts | Updates usage tests for isRemote flag. |
| services/runner/tests/unit/sandbox-agent-run-plan.test.ts | Extends existing run-plan tests to assert isRemoteSandbox. |
| services/runner/tests/unit/sandbox-agent-e2b-run-plan.test.ts | New unit tests for E2B run-plan behavior and E2B network-policy refusal. |
| services/runner/tests/unit/sandbox-agent-e2b-provider.test.ts | New unit tests for E2B create-option construction + timeout leak backstop behavior. |
| services/runner/tests/unit/sandbox-agent-e2b-keepalive.test.ts | New unit tests for keepalive scheduling, stop semantics, and error swallowing. |
| services/runner/sandbox-images/e2b/e2b.Dockerfile | New baked E2B template that preinstalls sandbox-agent + harnesses (incl. Node 22). |
| services/runner/sandbox-images/e2b/README.md | Documentation for building/configuring the baked E2B template and timeout semantics. |
| services/runner/package.json | Adds @e2b/code-interpreter dependency. |
| services/runner/pnpm-lock.yaml | Locks @e2b/code-interpreter and transitive deps. |
| docs/design/agent-workflows/projects/add-sandbox-e2b/tasks.md | Project task breakdown for E2B sandbox addition. |
| docs/design/agent-workflows/projects/add-sandbox-e2b/specs.md | Design/specs and acceptance criteria for E2B sandbox support. |
| docs/design/agent-workflows/projects/add-sandbox-e2b/research.md | Research notes and provider constraints (network policy, template build gotchas, etc.). |
| docs/design/agent-workflows/documentation/running-the-agent.md | Updates env var docs to include e2b provider + E2B env vars. |
| api/oss/src/utils/env.py | Adds E2BConfig to the shared env object. |
Files not reviewed (1)
- services/runner/pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| envs: { | ||
| AGENTA_AGENT_SANDBOX_CODEX_INSTALLED: String(E2B_CODEX_INSTALLED), | ||
| AGENTA_AGENT_SANDBOX_OPENCODE_INSTALLED: String(E2B_OPENCODE_INSTALLED), | ||
| AGENTA_AGENT_SANDBOX_CLAUDE_INSTALLED: String(E2B_CLAUDE_INSTALLED), | ||
| ...piExtEnv, | ||
| ...secrets, | ||
| }, |
Context
The only remote sandbox supported so far was Daytona. E2B is a second remote provider
sandbox-agentalready exports support for; standing it up meant a new provider branch, a new relay path (E2B's sandbox FS API instead of a geesefs-mounted cwd), and a new keepalive story since E2B has no built-in idle timeout like Daytona.Changes
provider.ts: E2B branch alongside Daytona, with a typedE2BCreateOptionsreturn (dropped anas anycast).run-plan.ts: newisRemoteSandboxflag derived asisDaytona || isE2B, used at every pure-remoteness gate; identity-specific sites (cookie fetch, cwd factory, network policy, MCP relay log label) keep the specificisE2B/isDaytonaflags. E2B's relay dir is${cwd}/.agenta-tools, polled via the sandbox FS API — the E2B cwd is never geesefs-mounted, unlike Daytona/local.workspace.ts: gates onisRemoteSandbox(was Daytona-only) so E2B also gets sandbox-FS-backed harness file writes, plus path-traversal containment (assertContainedfor host paths,assertContainedPosixfor remote) before every write.e2b-keepalive.ts(new): since E2B has no built-in idle-based timeout like Daytona,startE2BKeepaliverefreshesSandbox.setTimeouteverytimeoutMs/3for the life of the session, giving it Daytona-like idle semantics instead of a hard wall-clock cutoff.Tests / notes
sandbox-agent-e2b-keepalive.test.ts,sandbox-agent-e2b-provider.test.ts,sandbox-agent-e2b-run-plan.test.ts, plus updates tosandbox-agent-workspace.test.tsandsession-mcp-layering.test.ts.chore/add-claude-e2b(its PR targets this branch, notbig-agents).chore/add-codex-e2bandchore/add-opencode-e2breuse this E2B plumbing but are stacked on their respective harness branches instead.