Cloud Sandbox Host
A cloud sandbox host moves the Omnigent runner from your laptop to a remote container. Your agent keeps working after you close your laptop, in an isolated environment with cloud compute.
Looking to restrict what your agent can access on the filesystem and network instead? That's Omnibox.
| Local runner | Cloud sandbox host | |
|---|---|---|
| Availability | Stops when laptop closes | Runs independently |
| Compute | Your CPU and memory | Cloud compute |
| Environment | Local files | Isolated, reproducible |
| Best for | Interactive work | Long-running tasks |
Omnigent currently supports Modal, Daytona, Blaxel, Islo, NVIDIA OpenShell, and Boxlite for cloud sandbox hosts.
The hosted-platform comparison below covers Modal, Daytona, Blaxel, and Islo.
OpenShell connects to your selected gateway; Boxlite can use a local micro-VM runtime
or a remote boxlite serve pool.
| Modal | Daytona | Blaxel | Islo | |
|---|---|---|---|---|
| Runner lifetime | 24 hours (platform cap) | No cap (runs until deleted) | 24h max age by default (raise via ttl) | No cap (idle-paused after 15 min when managed) |
| Credential injection | Named secrets (Modal secret store) | Env vars copied from server | Env vars copied from server | Env vars copied from server / gateway profile |
| Free-tier egress | Full egress | Allowlisted domains only | Full egress | Gateway profile controls egress |
Server-managed (recommended)
Configure your server once and anyone on the team can launch a cloud sandbox host from the web UI.
1. Install
pip install 'omnigent[modal]' # for Modal
pip install 'omnigent[daytona]' # for Daytona
pip install 'omnigent[blaxel]' # for Blaxel
pip install 'omnigent[islo]' # for Islo
pip install 'omnigent[openshell]' # for OpenShell
pip install 'omnigent[boxlite]' # for Boxlite
The Islo launcher uses the Islo Python SDK, which ships in the omnigent[islo]
extra and is imported lazily, so only users of the Islo provider need to install it.
The omnigent[blaxel] extra ships the Blaxel Python SDK with the same lazy-import
posture. To launch Blaxel sandboxes from the CLI you also need the
Blaxel CLI (brew tap blaxel-ai/blaxel && brew install blaxel).
2. Set provider credentials
Modal: run modal setup to authenticate, or set
MODAL_TOKEN_ID and MODAL_TOKEN_SECRET on the server.
Daytona: create an API key in the Daytona dashboard (Dashboard > Keys) and set it on the server:
export DAYTONA_API_KEY=dtn_…
Islo: create an API key with the Islo CLI
(islo login, then islo api-key create omnigent --show) and set it on the
server. The SDK exchanges the key for short-lived session tokens and refreshes
them automatically, so the API key is the only required runtime credential:
export ISLO_API_KEY=islo_key_…
Blaxel: log in to your workspace with the Blaxel CLI (bl login your-workspace),
or set the control credentials on the server for a non-interactive process:
export BL_WORKSPACE=your-workspace
export BL_API_KEY=your-api-key
OpenShell: select a gateway with openshell gateway select <name>, or set
OPENSHELL_GATEWAY on the server. The launcher uses that gateway connection and
does not require a separate API key.
Boxlite: local mode requires KVM on Linux and no provider credential. For a
remote boxlite serve pool, set BOXLITE_API_KEY on the server and configure
the pool endpoint in the Boxlite settings.
Provider control credentials stay on the launching process and never enter the sandbox. Web users log in to Omnigent, not the sandbox provider.
3. Configure a provider
Add a sandbox section to your server config YAML (~/.omnigent/config.yaml on a laptop,
/data/config.yaml in Docker). A typical Modal configuration looks like this:
sandbox:
provider: modal
server_url: https://your-server.example.com
modal:
image: ghcr.io/omnigent-ai/omnigent-host:latest # optional, official image by default
secrets: [omnigent-llm] # Modal secrets with LLM API keysSee common settings
for the top-level fields, Modal settings
for the provider block, and host configuration
for host_config. The full cloud sandbox configuration reference
also covers the other providers and lifecycle settings.
4. Launch from the web UI
Start a new session and select New Sandbox in the host picker. The server provisions the cloud host, starts the runner, and connects it back automatically.
CLI
Create and manage cloud sandbox hosts from the command line. The commands are the same across
CLI-capable providers; switch the --provider flag:
omni sandbox create --provider modal # or --provider daytona / blaxel / islo / openshell
omni sandbox connect --provider modal \
--sandbox-id <id> --server <url>
Boxlite supports the server-managed flow but not these CLI bootstrap commands.
For a Blaxel CLI launch, list any credentials the host or agent needs in
OMNIGENT_BLAXEL_SANDBOX_ENV before create. Never include BL_API_KEY or
BL_CLIENT_CREDENTIALS. Blaxel does not expose local callback port forwarding,
so the in-sandbox browser login is skipped automatically.
Stopping connect leaves the sandbox running. Delete it with the provider's
CLI or console when you no longer need it.
Reap stale sandboxes (optional)
By default a managed sandbox lives until its session is deleted (or the
provider's own lifetime cap reaps it). To automatically terminate sandboxes
whose hosts have gone offline and stayed offline, add an optional reaper block
to sandbox:. It is deployment-wide — configure it next to provider (or
providers:), never inside an individual provider entry:
sandbox:
provider: modal
server_url: https://your-server.example.com
reaper: # optional; disabled by default
enabled: true # default: false
terminate_after_offline_days: 30 # default: 30 days
sweep_interval_s: 86400 # default: 1 day
enabled— whether the server starts the reaper loop. Defaults tofalsebecause terminating user compute is destructive; opt in explicitly.terminate_after_offline_days— the minimum number of days since a managed host's last heartbeat before its current sandbox generation may be terminated. Defaults to30.sweep_interval_s— seconds between complete sweeps. Defaults to86400(one day).
Both terminate_after_offline_days and sweep_interval_s must be positive
integers. Setting reaper inside a providers: list entry is rejected at
startup — one loop covers the whole deployment and dispatches each termination
through the provider recorded on the managed host it is reaping.
Reaping detaches only the stale sandbox generation: the session transcript and the durable host binding stay, so the next message to that session can launch a fresh sandbox under the same host identity. A provider termination that fails stays pending and is retried on a later sweep.
The reaper requires a configured host store. If reaper.enabled is true but
no host store is configured, the server logs a warning and the reaper does not
run.
Community sandbox providers
The providers above ship with Omnigent. Beyond them, the server discovers
additional sandbox providers at startup through a plugin registry, so a new
hosting platform can be added as a separate package without changing the
core omnigent package.
An installed provider behaves like a built-in once it's registered: its name is
accepted in the sandbox.provider field, its sandbox.<provider> config block
is validated at server startup, and it's offered as a working option in the web
UI host picker (managed launch is enabled). If the server config names a
provider whose optional package is missing, the server still starts — the
failure surfaces on the launch that needs it, naming the provider.
Configure a contributed provider
Set sandbox.provider to the contributed name and, if the provider declares a
config model, add a matching sandbox.<provider> block:
sandbox:
provider: acme
server_url: https://your-server.example.com
acme:
namespace: sandboxes
The block is validated against the provider's declared config model when the server starts, so a typo or a wrong type fails loudly at startup — with the provider named — rather than erroring on the first managed session. A provider that declares no config model takes no block.
Build a provider plugin
A sandbox provider plugin is a Python package that declares an entry point in
the omnigent.sandbox_providers group. The entry point resolves to a callable
returning a SandboxProviderContribution. Launcher and config-model classes
must live under the omnigent.community.sandbox.* namespace.
# pyproject.toml
[project]
name = "omnigent-acme"
dependencies = ["omnigent"]
[project.entry-points."omnigent.sandbox_providers"]
acme = "omnigent.community.sandbox.acme.plugin:get_contribution"# omnigent/community/sandbox/acme/plugin.py
from pydantic import BaseModel
from omnigent.onboarding.sandboxes.registry import (
SandboxProviderContribution,
SandboxProviderMetadata,
)
class AcmeConfig(BaseModel):
namespace: str = "default"
def get_contribution() -> SandboxProviderContribution:
return SandboxProviderContribution(
name="omnigent-acme",
providers={
"acme": SandboxProviderMetadata(
name="acme",
launcher_class="omnigent.community.sandbox.acme.launcher:AcmeSandboxLauncher",
config_model=AcmeConfig, # optional
managed_token_ttl_s=1234, # optional; falls back to the Modal TTL
),
},
)The launcher subclasses SandboxHostLauncher and, when a config_model is
declared, receives the validated config as a config= keyword argument.
Providers that declare no model keep a zero-argument constructor. When a
provider omits managed_token_ttl_s, its managed-token lifetime falls back to
the conservative Modal default.
Note: A plugin can't shadow a built-in provider name, and its launcher class
must resolve under the omnigent.community.sandbox.* namespace — the registry
rejects it otherwise. A malformed plugin is recorded and skipped rather than
crashing server startup.