> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/gym/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/gym/_mcp/server.

# nemo_gym.sandbox.providers.e2b.provider

Sandbox provider backed by the E2B Python SDK.

Works against e2b.dev itself and against any e2b-compatible gateway (point
`connection.api_url`/`connection.sandbox_url` at it).

Two E2B concepts differ from the provider-neutral :class:`SandboxSpec` and are
handled explicitly rather than silently:

**Templates, not images.** E2B starts sandboxes from a pre-built *template*
name or ID, not from an arbitrary registry reference. Because tagged template
names and OCI image references can both contain `:`, the direct
`SandboxSpec.image` shortcut is deliberately limited to unambiguous names in
`[A-Za-z0-9_-]`. Use `provider_options.template` or
`create.template_map` for tagged names, IDs, and image references.

**Resources are fixed at template build time.** `cpu_count`/`memory_mb` are
arguments to the template *build*, so a per-sandbox
`SandboxSpec.resources` cannot be honoured at create time. Requests are
reported once per provider instance (or raise, with `create.strict_resources`)
instead of being dropped quietly.

## Module Contents

### Classes

| Name                                                                                  | Description                                        |
| ------------------------------------------------------------------------------------- | -------------------------------------------------- |
| [`E2BConnectionConfig`](#nemo_gym-sandbox-providers-e2b-provider-E2BConnectionConfig) | Connection settings forwarded to the SDK.          |
| [`E2BCreateConfig`](#nemo_gym-sandbox-providers-e2b-provider-E2BCreateConfig)         | Sandbox creation settings.                         |
| [`E2BCreateError`](#nemo_gym-sandbox-providers-e2b-provider-E2BCreateError)           | Raised when a sandbox cannot be created.           |
| [`E2BExecConfig`](#nemo_gym-sandbox-providers-e2b-provider-E2BExecConfig)             | Command execution settings.                        |
| [`E2BOperationConfig`](#nemo_gym-sandbox-providers-e2b-provider-E2BOperationConfig)   | Retry policy for transient SDK/transport failures. |
| [`E2BProvider`](#nemo_gym-sandbox-providers-e2b-provider-E2BProvider)                 | Provider backed by the E2B Python SDK.             |

### Functions

| Name                                                                                                    | Description                                                      |
| ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [`_config_from_mapping`](#nemo_gym-sandbox-providers-e2b-provider-_config_from_mapping)                 | Build a config dataclass from a mapping, rejecting unknown keys. |
| [`_is_finite_number`](#nemo_gym-sandbox-providers-e2b-provider-_is_finite_number)                       | -                                                                |
| [`_require_e2b_sdk`](#nemo_gym-sandbox-providers-e2b-provider-_require_e2b_sdk)                         | Load the optional SDK through the shared helper.                 |
| [`_validate_nonnegative_int`](#nemo_gym-sandbox-providers-e2b-provider-_validate_nonnegative_int)       | -                                                                |
| [`_validate_nonnegative_number`](#nemo_gym-sandbox-providers-e2b-provider-_validate_nonnegative_number) | -                                                                |
| [`_validate_optional_number`](#nemo_gym-sandbox-providers-e2b-provider-_validate_optional_number)       | -                                                                |

### Data

[`LOGGER`](#nemo_gym-sandbox-providers-e2b-provider-LOGGER)

[`T`](#nemo_gym-sandbox-providers-e2b-provider-T)

[`_API_PARAM_KEYS`](#nemo_gym-sandbox-providers-e2b-provider-_API_PARAM_KEYS)

[`_DIRECT_TEMPLATE_RE`](#nemo_gym-sandbox-providers-e2b-provider-_DIRECT_TEMPLATE_RE)

### API

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BConnectionConfig(
    api_key: str | None = None,
    api_url: str | None = None,
    sandbox_url: str | None = None,
    domain: str | None = None,
    debug: bool | None = None,
    validate_api_key: bool | None = None,
    headers: dict[str, str] | None = None,
    api_headers: dict[str, str] | None = None,
    proxy: str | None = None,
    request_timeout_s: float | None = None
)
```

Dataclass

Connection settings forwarded to the SDK.

Any field left `None` falls back to the SDK's own environment variables
(`E2B_API_KEY`, `E2B_API_URL`, `E2B_SANDBOX_URL`, `E2B_DOMAIN`, ...).

**`api_headers`** `dict[str, str] | None = None`

---

**`api_key`** `str | None = None`

---

**`api_url`** `str | None = None`

---

**`debug`** `bool | None = None`

---

**`domain`** `str | None = None`

---

**`headers`** `dict[str, str] | None = None`

---

**`proxy`** `str | None = None`

---

**`request_timeout_s`** `float | None = None`

---

**`sandbox_url`** `str | None = None`

---

**`validate_api_key`** `bool | None = None`

---

```python
nemo_gym.sandbox.providers.e2b.provider.E2BConnectionConfig.__post_init__() -> None
```

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BCreateConfig(
    template: str | None = None,
    template_map: dict[str, str] = dict(),
    timeout_s: float | None = 3600.0,
    allow_internet_access: bool = True,
    secure: bool = True,
    strict_resources: bool = False
)
```

Dataclass

Sandbox creation settings.

**`allow_internet_access`** `bool = True`

---

**`secure`** `bool = True`

---

**`strict_resources`** `bool = False`

---

**`template`** `str | None = None`

---

**`template_map`** `dict[str, str] = field(default_factory=dict)`

---

**`timeout_s`** `float | None = 3600.0`

---

```python
nemo_gym.sandbox.providers.e2b.provider.E2BCreateConfig.__post_init__() -> None
```

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BCreateError()
```

**Bases:** [SandboxCreateError](/nemo-gym/nemo_gym/sandbox/providers/base#nemo_gym-sandbox-providers-base-SandboxCreateError)

Raised when a sandbox cannot be created.

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BExecConfig(
    default_timeout_s: float | None = 180.0,
    user: str | None = None,
    request_timeout_s: float | None = None,
    background: bool = True,
    reconnect_attempts: int = 2
)
```

Dataclass

Command execution settings.

**`background`** `bool = True`

---

**`default_timeout_s`** `float | None = 180.0`

---

**`reconnect_attempts`** `int = 2`

---

**`request_timeout_s`** `float | None = None`

---

**`user`** `str | None = None`

---

```python
nemo_gym.sandbox.providers.e2b.provider.E2BExecConfig.__post_init__() -> None
```

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BOperationConfig(
    retries: int = 2,
    retry_delay_s: float = 0.5,
    retry_max_delay_s: float = 8.0
)
```

Dataclass

Retry policy for transient SDK/transport failures.

**`retries`** `int = 2`

---

**`retry_delay_s`** `float = 0.5`

---

**`retry_max_delay_s`** `float = 8.0`

---

```python
nemo_gym.sandbox.providers.e2b.provider.E2BOperationConfig.__post_init__() -> None
```

```python
class nemo_gym.sandbox.providers.e2b.provider.E2BProvider(
    connection: nemo_gym.sandbox.providers.e2b.provider.E2BConnectionConfig | collections.abc.Mapping[str, typing.Any] | None = None,
    create: nemo_gym.sandbox.providers.e2b.provider.E2BCreateConfig | collections.abc.Mapping[str, typing.Any] | None = None,
    exec: nemo_gym.sandbox.providers.e2b.provider.E2BExecConfig | collections.abc.Mapping[str, typing.Any] | None = None,
    operations: nemo_gym.sandbox.providers.e2b.provider.E2BOperationConfig | collections.abc.Mapping[str, typing.Any] | None = None
)
```

Provider backed by the E2B Python SDK.

**`_connection`**

---

**`_create`** `= _config_from_mapping(E2BCreateConfig, create)`

---

**`_exec`** `= _config_from_mapping(E2BExecConfig, exec)`

---

**`_operations`**

---

**`_warned_resource_specs`** `set[str] = set()`

---

**`name`** `= 'e2b'`

---

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._api_params() -> dict[str, typing.Any]
```

SDK `ApiParams` for connection-scoped calls; omitted keys fall back to env.

Only `create`/`connect`/`kill` open a connection and accept these.
Everything else runs against an already-connected sandbox -- see
:meth:`_request_params`.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._check_resources(
    spec: nemo_gym.sandbox.providers.base.SandboxSpec,
    template: str
) -> None
```

Surface resource requests E2B cannot honour per sandbox.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._exec_request_timeout() -> float | None
```

Return the E2B 2.36 stream-open timeout for command requests.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._request_params() -> dict[str, typing.Any]
```

Per-request options for calls on an existing sandbox object.

`commands.run`, `files.*` and `is_running` take `request_timeout`
only -- the sandbox already carries the connection config, and handing
them the full `ApiParams` raises `TypeError: unexpected keyword
argument 'api_key'`.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._resolve_template(
    spec: nemo_gym.sandbox.providers.base.SandboxSpec
) -> str
```

Map a spec onto an E2B template.

Precedence: `provider_options.template` -> `create.template_map` ->
an unambiguous direct `spec.image`. `create.template` is used only
when `spec.image` is omitted; an unmapped image must not silently
select an unrelated fallback template.

Building a template from an image is provisioning, not part of starting
a sandbox, so it lives in :mod:`nemo_gym.sandbox.providers.e2b.build`
and never runs on this path.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._run_background(
    sandbox: typing.Any,
    kwargs: dict[str, typing.Any]
) -> typing.Any
```

async

Run a command detached, reattaching by pid if the stream drops.

`commands.run(background=True)` returns as soon as the process has
started, handing back its pid. The command then keeps running inside
the sandbox independently of the stream carrying its output, so losing
that stream -- a gateway rollout, a proxy restart, a network blip --
no longer destroys the command: reattach with `commands.connect(pid)`
and the real exit code still arrives.

Reattaching has two inherent limits:

* **Output emitted while disconnected is lost.** Output already
  received by the previous handle is retained and combined with the
  reattached stream, but the stream is live rather than replayed.
* **The process must still be running.** `connect` raises
  not-found once it has exited, so a command that finishes during the
  gap cannot be recovered.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._sandbox(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> typing.Any
```

staticmethod

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider._with_retries(
    factory: typing.Callable[[], typing.Awaitable[nemo_gym.sandbox.providers.e2b.provider.T]],
    operation: str,
    retry_timeouts: bool = False
) -> nemo_gym.sandbox.providers.e2b.provider.T
```

async

Retry transient failures with exponential backoff.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.aclose() -> None
```

async

No provider-scoped client to close; sandboxes own their connections.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.close(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> None
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.connect(
    descriptor: collections.abc.Mapping[str, typing.Any]
) -> nemo_gym.sandbox.providers.base.SandboxHandle
```

async

Attach to the sandbox described by `descriptor`.

E2B's public connect API applies its default sandbox timeout when none
is supplied, so attaching may renew a sandbox that is close to expiry.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.create(
    spec: nemo_gym.sandbox.providers.base.SandboxSpec
) -> nemo_gym.sandbox.providers.base.SandboxHandle
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.download_file(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    source_path: str,
    target_path: pathlib.Path
) -> None
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.exec(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    command: str,
    cwd: str | None = None,
    env: dict[str, str] | None = None,
    timeout_s: int | float | None = None,
    user: str | int | None = None
) -> nemo_gym.sandbox.providers.base.SandboxExecResult
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.read_file(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    source_path: str
) -> bytes
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.serialize_handle(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    scope: str | None = None
) -> dict[str, typing.Any]
```

async

Return a descriptor for attaching to this sandbox from another process.

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.status(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> nemo_gym.sandbox.providers.base.SandboxStatus
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.upload_file(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    source_path: pathlib.Path,
    target_path: str
) -> None
```

async

```python
nemo_gym.sandbox.providers.e2b.provider.E2BProvider.write_file(
    handle: nemo_gym.sandbox.providers.base.SandboxHandle,
    target_path: str,
    data: str | bytes
) -> None
```

async

```python
nemo_gym.sandbox.providers.e2b.provider._config_from_mapping(
    cls: type[nemo_gym.sandbox.providers.e2b.provider.T],
    value: typing.Any
) -> nemo_gym.sandbox.providers.e2b.provider.T
```

Build a config dataclass from a mapping, rejecting unknown keys.

```python
nemo_gym.sandbox.providers.e2b.provider._is_finite_number(
    value: typing.Any
) -> bool
```

```python
nemo_gym.sandbox.providers.e2b.provider._require_e2b_sdk() -> typing.Any
```

Load the optional SDK through the shared helper.

Keep this small wrapper local so provider unit tests can replace the SDK
without importing or contacting E2B.

```python
nemo_gym.sandbox.providers.e2b.provider._validate_nonnegative_int(
    name: str,
    value: typing.Any
) -> None
```

```python
nemo_gym.sandbox.providers.e2b.provider._validate_nonnegative_number(
    name: str,
    value: typing.Any
) -> None
```

```python
nemo_gym.sandbox.providers.e2b.provider._validate_optional_number(
    name: str,
    value: typing.Any,
    positive: bool
) -> None
```

```python
nemo_gym.sandbox.providers.e2b.provider.LOGGER = logging.getLogger(__name__)
```

```python
nemo_gym.sandbox.providers.e2b.provider.T = TypeVar('T')
```

```python
nemo_gym.sandbox.providers.e2b.provider._API_PARAM_KEYS = ('api_key', 'api_url', 'sandbox_url', 'domain', 'debug', 'validate_api_key', 'he...
```

```python
nemo_gym.sandbox.providers.e2b.provider._DIRECT_TEMPLATE_RE = re.compile('^[A-Za-z0-9_-]+$')
```