Skip to content

feat(terminal): add E2B cloud sandbox backend - #18348

Open
berkantay wants to merge 2 commits into
NousResearch:mainfrom
berkantay:feat/e2b-terminal-backend
Open

feat(terminal): add E2B cloud sandbox backend#18348
berkantay wants to merge 2 commits into
NousResearch:mainfrom
berkantay:feat/e2b-terminal-backend

Conversation

@berkantay

@berkantay berkantay commented May 1, 2026

Copy link
Copy Markdown

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

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • tools/environments/e2b.py — New E2BEnvironment class implementing BaseEnvironment with file sync, CWD tracking, session snapshots, and interrupt support. Uses beta_pause() for persistence and Sandbox.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 and e2b_template to 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 — Default e2b_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 — Added e2b_template env 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

  1. pip install 'hermes-agent[e2b]'
  2. Set E2B_API_KEY in ~/.hermes/.env
  3. hermes setup → select "E2B" → configure template and persistence
  4. hermes doctor → verify E2B checks pass
  5. hermes → run commands — they execute in E2B cloud sandboxes
  6. Exit and re-enter — persistent sandbox resumes from pause

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 (Darwin 24.6.0)

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/tools Tool registry, model_tools, toolsets tool/terminal Terminal execution and process management tool/file File tools (read, write, patch, search) tool/code-exec execute_code sandbox labels May 1, 2026
@alt-glitch alt-glitch added the comp/dashboard Web dashboard / control panel UI (dashboard/, landing) label Jun 27, 2026
@peterkong1024

Copy link
Copy Markdown

@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!

@teknium1

Copy link
Copy Markdown
Contributor

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 tools/terminal_tool.py:1216 and dispatch currently moves from Daytona to SSH at tools/terminal_tool.py:1514-1523.

Problems

  • This branch is against base 75e1339d4c, while current backend integration has moved substantially. Config propagation now lives in hermes_cli/config.py:6798-6884; file and code-execution construction independently route through tools/file_tools.py:1069-1150 and tools/code_execution_tool.py:661-710. The E2B wiring needs a targeted salvage through these current paths.
  • The PR changes no documentation, although the current terminal-backend inventory and persistence contract are documented at website/docs/user-guide/configuration.md:111-135.

Suggested changes

  • Re-integrate E2B through the current config bridge, backend/CWD classification, terminal, file, and execute-code construction paths, with focused integration tests for each.
  • Add E2B credentials, template, and persistence documentation alongside Modal and Daytona.

Automated hermes-sweeper review.

@berkantay
berkantay force-pushed the feat/e2b-terminal-backend branch from 44aef0d to e93a850 Compare July 12, 2026 21:30
@berkantay
berkantay requested a review from a team July 12, 2026 21:30
@berkantay

Copy link
Copy Markdown
Author

Rebased onto current main and re-integrated end-to-end — the PR is now MERGEABLE (base 7b5ba2054).

What changed since the review

The branch was cut against an old base, and in the meantime main removed the vercel_sandbox backend (which the original wiring mirrored) and the environments/ env-config model. So this is a clean re-integration modeled on Daytona, the surviving cloud backend, rather than a straight rebase.

The core provider (tools/environments/e2b.py) still matches the current BaseEnvironment contract unchanged (_stdin_mode="heredoc", FileSyncManager, init_session) — the only addition to it is a lazy-install hook.

Re-wired through the current paths

  • Terminal dispatch_create_environment, _CONTAINER_BACKENDS, CWD classification (/home/user default), SDK + E2B_API_KEY requirement check (tools/terminal_tool.py)
  • Config bridge & defaultse2b_template / TERMINAL_E2B_TEMPLATE (hermes_cli/config.py, cli.py, gateway/run.py)
  • File & code-execution constructiontools/file_tools.py, tools/code_execution_tool.py (container_config + backend classification)
  • Backend classificationagent/prompt_builder.py, tools/approval.py, tools/skills_tool.py, tools/env_probe.py
  • UX — setup wizard (backend picker + template chooser + API key), doctor, status, web config select, tips
  • Packaging[e2b] extra + lazy dep (terminal.e2b → e2b==2.10.0) + uv.lock

Docs

Added an E2B backend section (credentials, template, pause/resume persistence), overview-table row, config sample, and troubleshooting entry in website/docs/user-guide/configuration.md, alongside Modal and Daytona.

Tests

  • 19 E2B unit tests pass (tests/tools/test_e2b_environment.py)
  • 422 setup / web_server / config-cwd-bridge tests pass
  • All touched modules byte-compile

Thanks @peterkong1024 and @teknium1 for the pointers to the moved paths — ready for another look.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 12, 2026
@berkantay
berkantay force-pushed the feat/e2b-terminal-backend branch from e93a850 to 31875df Compare July 14, 2026 10:10
@OndrejDrapalik

Copy link
Copy Markdown
Contributor

Hey, @teknium1 would you be able take a look at this? Thanks!

@alt-glitch alt-glitch added comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery tool/skills Skills system (list, view, manage) sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages comp/dashboard Web dashboard / control panel UI (dashboard/, landing) area/config Config system, migrations, profiles and removed comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/tools Tool registry, model_tools, toolsets sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 16, 2026
@berkantay

Copy link
Copy Markdown
Author

@alt-glitch i've fixed conflicts could we review again?

@alt-glitch alt-glitch added the sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages label Jul 22, 2026
@berkantay

Copy link
Copy Markdown
Author

Hey @teknium1 can you take a look at this PR? Thanks !!

@max-sudolabs
max-sudolabs force-pushed the feat/e2b-terminal-backend branch from c33bbd5 to dd65d3d Compare August 19, 2026 17:49
@max-sudolabs

Copy link
Copy Markdown

Summary

This 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

  • Added an E2B environment with create, connect, pause, resume, kill, and timeout handling.
  • Integrated E2B with terminal, file, and code-execution tools.
  • Added workspace file synchronization and command cancellation.
  • Added persistent and ephemeral sandbox lifecycle support.
  • Integrated E2B configuration with setup, doctor, status, gateway, and shared environment helpers.
  • Added profile-scoped credential isolation.
  • Updated dependencies and user/developer documentation.

Validation

  • Added mocked tests covering sandbox lifecycle, failure handling, command cancellation, file sync, configuration, and secret isolation.
  • Targeted Hermes test suites, Ruff, compilation, lockfile validation, and diff checks pass.
  • Live E2B smoke testing verified command execution, file persistence, pause/resume, and sandbox cleanup.

@max-sudolabs

Copy link
Copy Markdown

@berkantay Hi, could review this PR once again. It's now up-to-date to the current E2B and Hermes version.

@berkantay

Copy link
Copy Markdown
Author

cc @teknium1

@alt-glitch alt-glitch added the backend/file-sync File sync across remote backends label Aug 19, 2026

@andrexibiza andrexibiza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread tools/environments/e2b.py
{"path": remote_path, "data": Path(host_path).read_bytes()}
for host_path, remote_path in files
]
self._require_sandbox().files.write_files(payload)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, I will take a look on that and commit updates

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

@alt-glitch alt-glitch added comp/tools Tool registry, model_tools, toolsets and removed backend/file-sync File sync across remote backends comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/tools Tool registry, model_tools, toolsets labels Aug 20, 2026
max-sudolabs and others added 2 commits August 21, 2026 15:02
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.
@max-sudolabs
max-sudolabs force-pushed the feat/e2b-terminal-backend branch from dd65d3d to add4264 Compare August 21, 2026 14:26
@alt-glitch alt-glitch added P4 Best-effort: we will get to it when we get to it (no commitment) and removed P3 Low — cosmetic, nice to have labels Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P4 Best-effort: we will get to it when we get to it (no commitment) sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/code-exec execute_code sandbox tool/file File tools (read, write, patch, search) tool/skills Skills system (list, view, manage) tool/terminal Terminal execution and process management type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants