feat(terminal): add E2B cloud sandbox backend - #18348
Conversation
|
@berkantay Hey, really looking forward to E2B sandbox support in Hermes — this is a much-needed feature. Could you rebase against main when you get a chance? The merge conflict is the only thing blocking this from moving forward. Thanks! |
|
Thanks for the E2B backend contribution. The feature premise remains current: E2B is not present on main; the current terminal backend set is visible in Problems
Suggested changes
Automated hermes-sweeper review. |
44aef0d to
e93a850
Compare
|
Rebased onto current What changed since the reviewThe branch was cut against an old base, and in the meantime The core provider ( Re-wired through the current paths
DocsAdded an E2B backend section (credentials, template, pause/resume persistence), overview-table row, config sample, and troubleshooting entry in Tests
Thanks @peterkong1024 and @teknium1 for the pointers to the moved paths — ready for another look. |
e93a850 to
31875df
Compare
|
Hey, @teknium1 would you be able take a look at this? Thanks! |
|
@alt-glitch i've fixed conflicts could we review again? |
|
Hey @teknium1 can you take a look at this PR? Thanks !! |
c33bbd5 to
dd65d3d
Compare
SummaryThis update brings the E2B terminal backend in line with the current Hermes environment architecture and E2B SDK 2.40. Hermes can run locally while delegating terminal commands, file operations, and code execution to an E2B sandbox. The work builds on the original contribution by @berkantay. What changed
Validation
|
|
@berkantay Hi, could review this PR once again. It's now up-to-date to the current E2B and Hermes version. |
|
cc @teknium1 |
andrexibiza
left a comment
There was a problem hiding this comment.
Blocking on the initial state-transfer contract and current-base proof.
[P1] A fresh E2B sandbox can become usable after its initial Hermes-state sync has failed. _ensure_remote_hermes_dir() creates only /home/user/.hermes, then FileSyncManager selects _e2b_bulk_upload() for every upload. E2B write_files() requires each target's parent directory to exist, while iter_sync_files() yields nested credential, skill, and cache paths. FileSyncManager catches the exception, rolls back its metadata, and deliberately does not re-raise, so construction proceeds to init_session() with no committed state; cleanup then treats the sandbox as never initialized and skips sync-back. The inline finding contains the class-level fix and regression shape.
This head is also 380 commits behind current main (f43eabee5f36; merge base 13ce0c5c675). Please restack after fixing this and re-run the E2B integration against the current file/config/runtime seams.
Exact-head CI is not evidence yet: all four workflows are action_required, no jobs were created, and the combined status list is empty. A green current-head receipt is needed after the restack.
| {"path": remote_path, "data": Path(host_path).read_bytes()} | ||
| for host_path, remote_path in files | ||
| ] | ||
| self._require_sandbox().files.write_files(payload) |
There was a problem hiding this comment.
[P1] write_files() does not create missing parent directories. The constructor only creates /home/user/.hermes, but iter_sync_files() can return nested paths below it. FileSyncManager always chooses this bulk callback and catches upload failures without re-raising, so a fresh sandbox can continue through init_session() as “ready” without credentials, skills, or cache. Create unique_parent_dirs(files) before the batch write (the same pattern used by Daytona), or use files.write(). Add a regression using the real FileSyncManager plus a fake E2B filesystem that rejects missing parents; the current tests replace FileSyncManager, so they cannot witness this failure class. E2B documents the batch contract here: https://e2b.dev/docs/sdk-reference/python-sdk/v2.3.2/sandbox_sync#write-files
There was a problem hiding this comment.
Thanks for the review, I will take a look on that and commit updates
There was a problem hiding this comment.
@andrexibiza @berkantay
Thanks for the review! The branch has been updated from current main.
Fixed
- Initial Hermes state sync now fails loudly instead of exposing a partially initialized sandbox.
- Parent directories are created before E2B uploads.
- Replacement sandboxes receive a complete state bootstrap.
- New remote skills and memories sync back safely without overwriting credentials.
- Sandbox pause, kill, reconnect, cleanup, and command cancellation handling were hardened.
- Added regression tests using the real
FileSyncManager.
Verification
- 302 targeted tests passed with no failures.
- Ruff, type checks, lockfile validation, and diff checks passed.
- A live E2B smoke verified upload, command execution, skill/memory sync-back, pause/resume of the same sandbox, and confirmed sandbox deletion afterward.
Co-authored-by: Berkant Ay <berkantay.5@gmail.com>
Fail startup when the initial Hermes state transfer cannot commit, restore agent-created skill and memory sync-back, and fully bootstrap replacement sandboxes. Tighten lifecycle cleanup and add focused regression coverage for sync, cancellation, configuration, and secret isolation.
dd65d3d to
add4264
Compare
What does this PR do?
Adds E2B as a new terminal execution backend (
TERMINAL_ENV=e2b), providing secure isolated cloud sandboxes with pause/resume filesystem persistence via the E2B Python SDK. This follows the same interface pattern as the existing Daytona and Vercel Sandbox backends.Related Issue
N/A — new feature contribution.
Type of Change
Changes Made
tools/environments/e2b.py— NewE2BEnvironmentclass implementingBaseEnvironmentwith file sync, CWD tracking, session snapshots, and interrupt support. Usesbeta_pause()for persistence andSandbox.connect()for auto-resume.hermes_cli/setup.py— E2B added to terminal backend picker with template selector (base, code-interpreter-v1, desktop, or custom), API key prompt, and persistence toggle.tools/terminal_tool.py— E2B branch in_create_environment(),_get_env_config(),_check_e2b_requirements(), container config assembly, and requirements check.tools/file_tools.py,tools/code_execution_tool.py— Added"e2b"to container config conditionals ande2b_templateto config dicts.tools/skills_tool.py— Added"e2b"to_REMOTE_ENV_BACKENDS.tools/approval.py— Added"e2b"to sandboxed-environment bypass sets (2 sites).hermes_cli/config.py— Defaulte2b_template: "base", config display block, env sync mapping.hermes_cli/doctor.py— E2B API key and SDK presence checks.hermes_cli/status.py— E2B template, SDK, and API key status display.hermes_cli/web_server.py— Added"e2b"to terminal backend options list.environments/hermes_base_env.py— Added"e2b"to backend description field.cli.py— Addede2b_templateenv mapping.pyproject.toml— New[e2b]optional dependency (e2b>=2.10.0,<3), added to[all]extra.tests/tools/test_e2b_environment.py— 19 unit tests.How to Test
pip install 'hermes-agent[e2b]'E2B_API_KEYin~/.hermes/.envhermes setup→ select "E2B" → configure template and persistencehermes doctor→ verify E2B checks passhermes→ run commands — they execute in E2B cloud sandboxesChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A