architecture

Three tiers. One binary. Everything composable.

Clients talk to the gateway over JSON-RPC 2.0 (HTTP or WebSocket). The gateway composes agents, channels, providers, and plugins on top of a shared core. Each layer is its own crate, each crate is independently usable.

[ CLIENTS ] CLI · macOS app Node.js (napi-rs) TS plugins (IPC) Channels (Telegram, …) HTTP/WS · JSON-RPC 2.0 [ openclaw-gateway ] axum · WebSocket · rate-limit · auth · CORS embedded Vue 3 dashboard at / openclaw-agents runtime · sandbox workflow · tools openclaw-channels routing · allowlist Telegram adapter openclaw-providers Anthropic · OpenAI SSE streaming openclaw-plugins TS bridge (nng) WASM (planned) openclaw-core types · config · sled event store · validation AES-256-GCM credential store · OAuth openclaw-ipc + openclaw-node nng transport · JSON-RPC msgs napi-rs bindings for Node.js
Clients hit the gateway over JSON-RPC. The gateway composes agents, channels, providers, and plugins on top of a shared core.

The crate dependency graph

Read the graph bottom-up. openclaw-core sits at the foundation — every other crate depends on it, none of them depend on anything above it. openclaw-providers + openclaw-ipc sit on the core. openclaw-agents + openclaw-channels + openclaw-plugins sit on those. openclaw-gateway sits on top of everything and embeds openclaw-ui at build time. The CLI ties it all together.

There is no circular dependency, no global state, no hidden coupling. You can swap any layer for your own — or use any single crate in isolation from your own service.

Event-sourced session model

Sessions are append-only logs in sled. Eight event kinds cover everything that can happen during a session.

SessionStarted channel, peer_id MessageReceived content, attachments ToolCalled tool, params ToolResult result, success AgentResponse tokens MessageSent content, message_id StateChanged key, value SessionEnded reason Append-only log in sled · replayable · time-travel debugging · CRDT projection via last-write-wins merge
Every state change is an event. The session is the log; the rendered conversation is just a projection.

Projecting the log into the current state uses last-write-wins CRDT semantics. The same projection is safe to compute in multiple instances in parallel — which makes future clustering straightforward.

Platform sandbox backends

Tool execution is process-isolated. The Rust API stays the same; the backend dispatches by OS at compile time.

[ LINUX ] bubblewrap (bwrap) --ro-bind /usr /usr --ro-bind /lib /lib --bind WS WS --unshare-net --unshare-pid --die-with-parent namespace isolation net + pid + mount workspace-only writes [ macOS ] sandbox-exec (version 1) (deny default) (allow file-read* /usr) (allow file-r/w WS) (deny network*) declarative profile Apple Seatbelt no network · workspace fs [ WINDOWS ] Job Objects CreateJobObject(...) JOBOBJECT_BASIC_LIMITS JOB_OBJECT_LIMIT_PROCESS _MEMORY · _CPU no child escape resource caps CPU + memory limits no UI access
Three platform backends · one capability-based policy (None / Relaxed / Strict).

Three levels — None, Relaxed, Strict — pick the policy. The backend implements it. See the sandbox deep dive for the policy details.

Thread model

Everything async-first via tokio. Shared state lives behind Arc<RwLock<T>>; no global mutable state, no hidden locking. Backpressure via bounded channels at the channel-adapter boundary so a flood of inbound events can't OOM the runtime.

#![forbid(unsafe_code)] is enforced across every workspace crate. There is no unsafe block in openclaw-rs. We rely on well-tested ecosystem crates for the rare cases (rkyv, aes-gcm, nng) where unsafe sits below the surface.

crates

The full inventory

Ten crates. Eight stable today, two partial.

Crate Status Role Links
openclaw-core stable Foundation: types, JSON5 config loader, sled-backed event store, AES-256-GCM credential store, OAuth token management, input validation.
openclaw-ipc stable IPC message types and nng transport — the wire format for the TypeScript plugin bridge.
openclaw-providers stable Anthropic + OpenAI clients with SSE streaming, tool use, and configurable base URLs.
openclaw-agents stable Agent runtime, platform-specific sandbox (bwrap / sandbox-exec / Job Objects), tool registry, node-based workflow engine.
openclaw-channels partial Channel traits + allowlist + routing. Telegram adapter complete; Discord, Slack, Signal, Matrix, WhatsApp planned.
openclaw-gateway stable axum HTTP/WebSocket server with JSON-RPC 2.0 dispatch, rate-limit and auth middleware, embedded Vue 3 dashboard.
openclaw-plugins partial Plugin API + nng-based TypeScript bridge. WASM runtime (wasmtime vs wasmer) under evaluation.
openclaw-cli stable Top-level CLI: onboard, gateway, doctor, status, config, sessions, channels, daemon, completion.
openclaw-node stable napi-rs bindings: AnthropicProvider, OpenAIProvider, NodeEventStore, CredentialStore, ToolRegistry. Pre-built binaries on npm.
openclaw-ui stable Vue 3 + Vite dashboard. Served by openclaw-gateway at /. No external admin to deploy.
next

Ready to deploy it?

The architecture is opinionated — the install isn't. cargo install, openclaw onboard, openclaw gateway run.