Sandboxing

Every agent turn in Diminuendo executes inside an isolated sandbox — a short-lived compute environment with its own filesystem, network namespace, and process tree. The gateway itself never creates, provisions, or enters a sandbox. It delegates entirely to Podium, which orchestrates the execution environment and reports lifecycle events back through the WebSocket event stream. The gateway’s role is narrower and more disciplined: it tracks state, enforces security policy at the protocol level, and broadcasts lifecycle events to subscribers. This architecture is a deliberate separation of concerns. The gateway is a control plane. Podium is the data plane. The sandbox is the execution boundary. Each layer has a single owner, and the responsibilities do not overlap.

Architecture

Client
  |
  v
Gateway (Diminuendo)
  |  Tracks sandbox state via events
  |  Enforces security profiles for automations
  |  Broadcasts lifecycle events to subscribers
  |
  v
Podium (Coordinator)
  |  Creates compute instances
  |  Provisions Docker / E2B containers
  |  Manages agent processes inside containers
  |  Emits sandbox lifecycle events
  |
  v
Sandbox (Docker / E2B microVM)
  |  Isolated filesystem, network, processes
  |  Chronicle workspace mounted at /workspace
  |  Agent tools execute within the container boundary
The gateway never SSH-es into a sandbox, never mounts filesystems, and never spawns processes inside containers. Its sole responsibility is relaying sandbox lifecycle events to clients and enforcing security policy at the protocol level. All container orchestration belongs to Podium.

Sandbox Lifecycle

A sandbox follows a four-phase lifecycle, each phase tracked through gateway events. The progression is linear — there are no backward transitions, no retry loops at the sandbox level. A failed sandbox is torn down; a new one is provisioned from scratch.
1

Init

When a session starts its first turn, Podium creates a compute instance and begins provisioning a sandbox. The gateway receives a sandbox.init event and broadcasts it to subscribers.Gateway event: sandbox_init — includes the provider name (e.g., "e2b", "docker")
2

Provisioning

The sandbox is being set up: installing dependencies, configuring the environment, mounting the Chronicle workspace. Podium emits progress events that the gateway relays.Gateway event: sandbox_provisioning — includes phase (e.g., "creating", "configuring", "installing_deps") and an optional message
3

Ready

The sandbox is fully provisioned and the agent can execute tools. The gateway broadcasts sandbox_ready and updates session metadata so clients can display sandbox status.Gateway event: sandbox_ready
4

Removed

The sandbox has been torn down — because the session was deactivated, the turn completed, or a timeout fired. The gateway broadcasts sandbox_removed with a reason.Gateway event: sandbox_removed — includes reason (e.g., "session_deleted", "timeout", "manual") and an optional message

Sandbox State in the Gateway

The gateway tracks sandbox state in two places, ensuring that both late-joining clients and tenant-wide dashboards have a consistent view.

State Snapshot

When a client joins a session (join_session), the state_snapshot response includes a sandbox field:
{
  "type": "state_snapshot",
  "sessionId": "...",
  "session": { "..." },
  "sandbox": {
    "status": "ready",
    "provider": "e2b"
  }
}
If no sandbox exists — the session has not been activated or has been deactivated — sandbox is null.

Session Updates

Sandbox lifecycle changes are broadcast as session_updated events to the tenant topic, so all connected clients — not just those joined to the session — see the sandbox status in their session list:
// From src/session/handlers/sandbox.ts
yield* ctx.publishTenantEvent({
  type: "session_updated",
  session: {
    id: ctx.sessionId,
    sandbox: { status: "ready" },
  },
})

Sandbox Providers

Podium supports multiple sandbox providers. The gateway is provider-agnostic — it relays events regardless of which provider created the sandbox.

E2B microVMs

Cloud-hosted microVMs via the E2B platform. Each sandbox receives a dedicated VM with its own kernel, filesystem, and network stack. The isolation is hardware-enforced: the guest kernel is distinct from the host. Used for production workloads requiring strong isolation guarantees.

Docker Containers

Local or cloud Docker containers for development and testing. Lighter-weight than microVMs — containers share the host kernel — but sufficient for local development stacks and CI environments where the threat model does not include malicious tenants.
The E2B_API_KEY and E2B_DOMAIN environment variables configure the E2B provider. For Docker, Podium uses the local Docker daemon.

File Access Through Sandboxes

Clients access files in the agent’s workspace through the gateway, which proxies requests to Podium’s file API. The gateway is a relay, not a cache — every file operation reaches Podium in real time.
Client MessageGateway ActionPodium API
list_filesProxy to PodiumGET /api/v1/instances/{id}/files
read_fileProxy to PodiumGET /api/v1/instances/{id}/files/{path}
file_historyProxy to PodiumGET /api/v1/instances/{id}/files/{path}/history
file_at_iterationProxy to PodiumGET /api/v1/instances/{id}/files/{path}/at/{n}
All file operations require an active Podium instance (and therefore an active sandbox) for the session. If the session is inactive, the gateway rejects file access with an error. Chronicle provides the versioned filesystem layer inside the sandbox. Every file modification creates a new iteration, enabling clients to browse version history and read files at any historical point. See Chronicle Integration for details.

Security Profiles for Automations

Interactive sessions run with the user watching — the human can intervene if the agent does something unexpected. Automation runs are unattended, which demands stricter sandboxing. Each automation carries a security profile that Podium enforces at the container level.

Profile Definitions

ProfileNetworkFilesystemUse Case
restricted (default)No outbound except LLM providerRead-write within /workspace onlyCode analysis, test running, file review
networkedOutbound via egress proxy with domain allowlistRead-write within /workspace onlyGitHub API access, external service monitoring
customAdmin-configured policyAdmin-configured policySpecial integrations (requires automation:admin permission)
The gateway validates security profiles at automation creation time and passes them to Podium when starting a run:
// AutomationEngine passes security context to Podium
yield* sessionRuntime.startTurn({
  sessionId: runSessionId,
  tenantId: identity.tenantId,
  agentType: automation.agentType,
  text: automation.prompt,
  metadata: {
    automationId: automation.id,
    runId: run.id,
    securityProfile: automation.security?.profile ?? "restricted",
    isUnattended: true,
  }
})

Filesystem Isolation

The container filesystem is restricted to exactly what the agent needs. Nothing more is visible; nothing less would be functional:
Container filesystem:
  /workspace/          <-- Chronicle workspace for this tenant+session
  /tmp/                <-- Ephemeral scratch space (size-limited)
  /                    <-- Read-only base image (agent runtime, tools)

NOT visible:
  /data/tenants/       <-- Gateway SQLite databases
  /data/sessions/      <-- Other sessions' databases
  Other tenants' workspaces
The gateway’s control-plane databases (registry.db, session.db) are never mounted into any sandbox. They reside on the gateway’s local filesystem, physically separate from the container mount namespace. This is not a policy — it is a topological fact. The databases exist in a namespace the container cannot see.

Permission Requests in Sandboxes

When an agent inside a sandbox encounters a sensitive operation, it emits question_requested or permission_requested events. The gateway:
  1. Broadcasts the event to all session subscribers
  2. For automation runs: transitions the run to waiting status and creates an inbox item
  3. Waits for the user to respond via answer_question
Automation runs never auto-approve sensitive operations — all permission requests require human confirmation, even for restricted profile runs. If a run remains in waiting status beyond a configurable timeout, it is canceled. There is no “YOLO mode” for unattended execution.

Sandbox Lifecycle During Shutdown

When the gateway shuts down gracefully:
  1. The server_shutdown event is broadcast to all session topics
  2. Active Podium connections are closed
  3. Podium instances are stopped via DELETE /api/v1/instances/{id}
  4. Sandboxes are torn down by Podium as a consequence of instance deletion
On ungraceful shutdown — process crash, OOM kill — the stale session recovery mechanism runs on startup and resets all non-idle sessions to inactive. The Podium instances associated with those sessions will have already been reclaimed by Podium’s own timeout mechanism. The system converges to a consistent state without manual intervention.

Configuration

VariableDefaultDescription
E2B_API_KEY""API key for E2B sandbox provider
E2B_DOMAINe2b-dev.igent.devE2B domain for sandbox URLs
PODIUM_URLhttp://localhost:5082Podium coordinator URL (manages sandbox lifecycle)
The gateway does not provision sandboxes itself. All sandbox configuration flows through Podium. The E2B_API_KEY is passed to Podium (via instance environment variables or Podium’s own configuration) — the gateway stores it for configuration validation and health reporting, not for direct E2B API calls.

Responsibility Matrix

The division of labor between gateway and Podium is strict and unambiguous:
ResponsibilityGateway (Diminuendo)Podium
Create sandboxNoYes
Provision dependenciesNoYes
Mount Chronicle workspaceNoYes
Enforce network policyNo (defines policy)Yes (enforces at container level)
Track sandbox stateYes (via events)Yes (source of truth)
Broadcast lifecycle eventsYesNo (emits raw events)
File access proxyYesYes (serves file API)
Stop sandbox on session deleteYes (calls Podium API)Yes (executes container teardown)
Recover after crashYes (resets stale sessions)Yes (reclaims timed-out instances)
The gateway never reaches into the data plane. Podium never broadcasts to clients. Each system stays within its boundary, and the event stream is the only contract between them.