Spaces and topologies
The two units of computation in Samoza OS — what a space is, what a topology is, how they relate.
Samoza OS runs Spaces. A space is a sandboxed WebAssembly process with a typed role. Spaces are arranged into Topologies — named collections that get deployed, scheduled, and managed as one.
A Space is a typed sandbox
Every space declares a type at creation time. The type is a contract: it says what kind of work the space does, what runtime services it can use, and what the compiler/runtime should validate.
| Type | Role | Where it runs |
|---|---|---|
:UI | User interface — dashboards, panels, control surfaces | Browser (HTML/JS in a zdesk iframe) |
:IO | Sensors, devices, streams | WASM in zrun |
:DATA | Persistence — key/value, blobs, files | WASM in zrun |
:CHAT | LLM-backed reasoning | WASM in zrun |
:CALL | External services | WASM in zrun |
The non-UI types (:IO, :DATA, :CHAT, :CALL) all execute as WebAssembly guests against the Guest ABI. UI spaces are a special case: their declarations are still part of the topology, but the runtime is the browser.
What lives inside a space
A space is the unit of isolation. Each one gets:
- Its own WASM memory.
- Its own capabilities — exactly what it declared, no more.
- Its own message queue.
- Its own lifecycle hooks (
on_init,on_process,on_close). - A unique name and instance ID, so messages can target it.
Two spaces in the same topology cannot reach into each other’s memory. They communicate only through messages, sent via paths.
A Topology is a named graph
A topology is a YAML (or MEX manifest) that says:
- Which spaces exist.
- Which paths connect them.
- Where each space’s WASM (and assets, for UI) lives.
- Optionally: a spatial world layout, AI agent config, capability grants.
A minimal topology:
apiVersion: samoza/v1
kind: Topology
metadata:
name: hello-samoza
spaces:
- name: dashboard
type: UI
mex: ./build/dashboard.mex
- name: store
type: DATA
mex: ./build/store.mex
path: /metrics
paths:
- from: dashboard
to: store
name: read-store
When you topo submit this, zrms decides which zhost runs each space, zrun instantiates the WASM, and zmesh registers each space’s location so messages can route.
The Space–Path Graph
Together, the spaces and paths form a directed graph — the Space–Path Graph (SPG). The SPG is what zrms schedules, what zrun instantiates, and what the runtime tracks for failure detection and recovery.
A topology’s SPG is the same shape whether you wrote it by hand in YAML, generated it from an Anglish declaration, or produced it from some future authoring tool. The runtime doesn’t care how the graph got there; only what it says.
Lifecycle of a space
declared in topology
│
▼
zrms picks a zhost
│
▼
zrun loads the WASM
│
▼
on_init() runs ← guest entry point
│
▼
on_process() called ← per message / event
│ (loops)
▼
on_close() runs ← stop signal received
│
▼
runtime cleans up
on_init, on_process, and on_close are exported by every WASM guest. The runtime calls them in order; the guest does work in response. Between calls, the space is just memory waiting for a message.
Capabilities
A space cannot do anything its topology didn’t declare. Capabilities are listed up front:
spaces:
- name: store
type: DATA
capabilities:
- data.read
- data.write
- sys.log
zrun enforces this at the ABI boundary — a space without data.write cannot persist data, full stop. See the capabilities reference for the full set.
Why this model
Two reasons.
Isolation by default. A space can only do what its capabilities allow, can only talk to spaces it has paths to, and runs in its own WASM sandbox. Crashes don’t propagate; misbehaviour is bounded.
Locality of placement. The scheduler can move spaces around without changing the topology. A UI surface can run on a tablet today and an industrial display tomorrow; an IO space can live on the edge node nearest the sensor it reads. The topology declares what, not where.