Components
A whole-system picture before you install anything — where the boxes live and what travels between them — then the three components you deploy and the images that carry them.
Exo splits into two planes, and you run both. The control plane is a Deployment you stand up and log into — it holds your configuration and serves the UI. The runtime lives in your Kubernetes cluster(s): the Exo Operator and the pods it reconciles from your agentkube.io CRDs. The two never share a network — the Operator opens a single outbound WebSocket to the control plane, and everything travels over it, from rendering an agent's status to attaching a browser shell.
The control plane
Before diving into the details, here's the full picture. The control plane is where you log in and manage things. Your Kubernetes cluster is where agents actually run. One connection links the two.
Exo · Control Plane
Self-hosted · platform namespaceExo Operator cluster
agentkube-system + your namespacesThe control plane never connects into your cluster. Every interaction — rendering an agent's status in the UI, attaching a shell, dispatching an agent invocation — travels back along the same WebSocket that the Exo Operator opened on startup.
Network Flow
The connection multiplexes several conceptual streams onto one transport:
- Snapshot & Delta frames — the Exo Operator describes what's running and pushes changes within a second of the underlying event.
- Heartbeats — keep-alive at a regular cadence; the control plane marks a deployment
degradedif they stop andofflineif they don't return within the eviction window. - Shell I/O — when a user attaches to an agent shell, frames carrying
shell_open,shell_input,shell_output, andshell_resizeflow over the same wire, keyed by agrant_id. - Agent invocation & pod control — the control plane asks the Exo Operator to ensure an Agent exists (
ensure_pod) or to dispatch a system-mode run (invoke_agent); results return on the same wire. - Session events — audit-quality SessionEvent frames with hash-chain integrity, redaction applied agent-side before they ever cross the wire.
Data flows
Three flows worth recognising before you debug anything:
- Discovery flow: the Exo Operator boots →
Hello→Snapshot→ continuousDeltaframes. New agents appear in the dashboard within one second of their pod becoming ready. - Shell flow: user clicks "Open shell" → control plane issues a
grant_id→shell_openon the wire → browserxterm.jsattached over WebSocket to the control plane → I/O proxied to the agent's container. - Reconcile flow: you
kubectl applyanAgent(or Tool) → the operator reconciles it into a pod / Service / Secret → status is written to the CR's.statusand pushed to the dashboard as a Delta.
Three components
Exo isn't a single container. A working install is three components — the CRDs, the operator, and the platform — and a small set of published images the operator pulls at runtime.
- CRDs. The
agentkube.iocustom resource definitions. Registering them is what lets you author agents and tools as Kubernetes objects. See CRD overview. - Operator. The
agentkube-manager— a controller-runtime operator (Deployment + RBAC + admission webhook) that reconciles the CRDs into running pods and, optionally, connects out to the platform. See Deploying the manager. - Platform. The Exo backend with the UI embedded in the same binary, plus PostgreSQL. This is the dashboard, the identity layer, the audit store, and the control plane the Exo Operator phones home to.
Topologies
- All-in-one. Platform + operator + CRDs in one cluster. The quickstarts and a default
exo-installland here. - Hub-and-spoke. One platform cluster; many Exo Operator clusters, each in managed mode connecting back over a single outbound WebSocket. Each spoke is its own deployment in the dashboard.
- Local-only. Operator + CRDs with no platform — fully unmanaged, agents run but nothing phones home. Good for dev and air-gapped edge.