Architecture
OpenShell governs what agents can do in two ways: it instruments the kernel to enforce policy on every file access, system call, and network connection at runtime, and it uses formal verification to check what a policy change would allow before it is applied.
- Kernel-level enforcement. Each agent runs in an isolated sandbox. Kernel controls confine which files it can access and which system calls it can make, and every network connection passes through a policy check before it leaves the sandbox. OpenShell supplies credential placeholders to agents and adds real credentials only to requests bound for approved endpoints.
- Formally verified policy changes. Before a policy change is approved, OpenShell uses formal verification to flag risky new access it would grant, such as reaching a new host with credentials or calling a new API method, so those changes wait for human review.
The gateway is the control plane: it manages the lifecycle of sandboxes and provides connectivity and management of sandboxes to end users and operators. When you create a sandbox, its compute driver provisions a workload and a separate supervisor, establishes their protected channel, and builds the isolation boundary; the supervisor confirms that boundary before starting the agent and then connects back to the gateway for policy, credentials, logs, and interactive sessions.
What Each Piece Does
Inside the Sandbox Boundary
The supervisor and sandbox sit on opposite sides of the boundary. The supervisor is trusted and makes the decisions. The sandbox shares the boundary with the untrusted agent, so it never makes policy decisions. It reports what the agent is trying to do and lets the supervisor decide.
The sandbox launches the agent as an owned child and provides exec, terminal streams, signals, process status, and loopback forwarding. In the current Linux backend, the workload uses one non-root identity and no Linux capabilities. Landlock limits filesystem access; seccomp user notification stages network operations. The sandbox identifies the calling executable from trusted process observations.
Mediated Channel
The supervisor and sandbox talk over the OpenShell Sandbox Protocol: one HTTP/2 connection authenticated with TLS and a sandbox JWT that carries many independent streams. The compute driver picks the transport: a Unix socket for Docker and Podman, TCP for Kubernetes, or vsock for MicroVM. Authentication and protocol behavior are the same on all of them. The supervisor presents a sandbox-specific credential, as described in How Components Authenticate.
Each TCP connection gets its own stream with its own backpressure, so a slow download can’t block DNS, exec, or process control.
Together these mean the agent can’t run before its controls are confirmed, signals and exec reach only this sandbox’s processes, and the agent can’t get around TCP or DNS mediation.
How a network request travels
- The agent opens a TCP connection or makes a DNS lookup.
- The sandbox identifies the calling program.
- The request travels over the Sandbox Protocol to the supervisor.
- The supervisor checks it against policy and adds any credentials policy allows.
- If allowed, the supervisor opens the real connection and relays traffic.
The mediated channel to the supervisor is the workload’s only allowed egress path. The outer fence denies everything else, so the agent can’t reach a service, the gateway, DNS, or another private address directly.
Agent traces
When an operator enables the
agent trace relay,
the sandbox points the agent’s OpenTelemetry SDK at the reserved address
192.0.0.8:4318. Connections to it take the same mediated channel, but the
supervisor answers them itself instead of opening an upstream connection.
It tags each trace batch with the sandbox ID and forwards it to the operator’s
collector. The agent never learns the collector’s address and needs no egress
rule to reach it.
How Each Runtime Builds the Boundary
Every runtime follows the same contract, but each one uses the tools it already has to place the supervisor, connect it to the sandbox, and fence off the network.
The runtime’s job is to build the boundary and prove it’s in place. It never decides whether a request is allowed. That decision always belongs to the shared supervisor and policy engine, which is why the same policy behaves the same way everywhere.
Runtimes can differ in how they report readiness and which features they support. Each one advertises its capabilities so the gateway knows what it can do.
How Components Authenticate
Three connections tie a sandbox session together. The gateway signs the session’s gateway and sandbox JWTs, each bound to that sandbox and generation.
The supervisor verifies the gateway’s TLS certificate with its CA. User client certificates and private keys stay outside both the supervisor and workload; the gateway JWT authenticates supervisor RPCs.
Getting the first credential
The gateway prepares session credentials for each sandbox generation and delivers them through trusted launch provisioning:
- Docker, Podman, and MicroVM. The driver supplies the dedicated supervisor with private credential files.
- Kubernetes, dedicated supervisor. The driver mounts the preissued credential bundle from a Secret into the supervisor pod.
- Kubernetes, shared supervisor. Each sandbox’s credential bundle arrives in its assignment over the authenticated supervisor-host stream.
A separate IssueSandboxToken exchange accepts a compute-driver bootstrap
identity. On Kubernetes, the driver validates a projected ServiceAccount token
and its pod and owner identity. The gateway compares the driver and runtime
identity with its stored sandbox record before returning a gateway JWT. This
exchange is not required for supervisors provisioned with a credential bundle.
Gateway and Sandbox JWTs
The gateway issues a pair of JWTs for each run of a sandbox:
- Gateway JWT. Authenticates the supervisor’s sandbox-specific calls to the gateway. It allows only the calls a supervisor needs, such as fetching policy, pushing logs, and relaying sessions. It is not a user credential and can’t manage other sandboxes.
- Sandbox JWT. Authenticates boundary opening and the supervisor’s control and mediation streams to the sandbox. The sandbox holds only the gateway’s public key, so it can verify the token but can never create one.
Each token works only on its own connection. Both are bound to one sandbox and one run of that sandbox, called a generation. Restarting a sandbox starts a new generation with fresh tokens and fresh TLS certificates, and the old ones stop working.
Shared Kubernetes supervisors also use a separate, gateway-scoped supervisor-host JWT to receive assignments. The pool’s replicas share this token, which authorizes only the host assignment stream. The gateway checks assignment ownership separately, and each assigned sandbox still uses its own session JWTs. See Multi-tenant Supervisor.
Renewing and revoking
The supervisor keeps its session tokens in memory and renews both together before they expire. Renewal works only while the sandbox still exists, so deleting a sandbox ends that sandbox’s session.
Shared deployments, such as Kubernetes, should set gateway_jwt.ttl_secs so
tokens expire. Local single-user gateways can leave it unset, which issues
tokens that last for the life of the sandbox run.
What the agent can see
The agent shares its side of the boundary with the sandbox, so the sandbox holds nothing worth stealing: no gateway signing key, no gateway JWT, and no provider credentials. It can verify that it’s talking to the right supervisor, but it can’t impersonate one.
If the supervisor disconnects, the sandbox freezes the agent. The same supervisor process can reconnect and resume it within the recovery window. In a shared Kubernetes supervisor pool, the gateway can authorize a replacement supervisor with a signed takeover grant for that sandbox generation and a higher ownership epoch. When the replacement confirms the boundary, a runtime that supports takeover revokes the previous owner’s access and resumes the agent. Valid session credentials alone do not authorize takeover. If recovery does not complete before the deadline, the runtime terminates the workload.
Working With Your Existing Infrastructure
OpenShell plugs into the tools you already use, including container runtimes, schedulers, secret stores, identity providers, image pipelines, storage, and device plugins. The gateway and supervisor define how OpenShell behaves. Drivers translate that behavior into whatever your platform understands and report back what happened. This keeps platform-specific details out of the core control plane and the policy model.