DEVELOP

The Guest ABI

The fixed binary contract between WASM guest programs and the Samoza runtime.

The Guest ABI is the binary interface between WASM guest programs and the Samoza runtime. It defines the set of host-imported WASM functions and guest-exported entry points that constitute the fixed contract.

Every non-UI space (:IO, :DATA, :CHAT, :CALL) executes a WASM guest compiled with TinyGo. The Guest ABI is the syscall table — minimal, stable, and the only way guest code reaches the runtime.

What the ABI covers

The Guest ABI specifies only the WASM host-imported functions and guest-exported entry points. It does not cover:

  • Construction-time concerns (space creation, path wiring, agent registration) — those belong to the MEX format.
  • Domain-specific convenience wrappers (car control, vision typed structs) — those belong to the Guest Library.

See the boundaries reference for the full discussion.

Modules

The ABI is organised as modules. A guest can only use modules its declared capabilities permit.

Core — universal, every WASM space

ModulePurpose
Lifecycleon_init, on_process, on_close, memory model
SystemLogging, sleep, yield, self-emit
NetworkMessage passing between spaces
CapabilitiesCapability model — declaration and enforcement

Extended — software services, cross-cutting

ModulePurpose
DataKey/value storage
AgentsDF, AF, LLM agent invocation
EventsComputed events from recognizers
Intelligence CacheLLM response caching, semantic lookup

Device — physical hardware I/O

ModulePurpose
SensorsUnified subscribe/read for all inputs
ActuatorsUnified lock/command/release for all outputs
AudioMicrophone input and speaker output streaming

Sensors is generic: subscribe/read interface, sensor types are extensible strings, no built-in device knowledge in the ABI itself, all data is JSON.

Actuators is generic: lock/command/release interface, actuator types are extensible strings, all actions are JSON.

Audio has its own module because it’s a continuous byte stream that doesn’t fit the sensor read/poll pattern or the actuator lock/command pattern.

UI spaces are not covered by the Guest ABI. They run in the browser, in zdesk iframes, against a separate JavaScript surface.

Space types and the ABI modules they use

Space typeExecutionKey ABI modules
:UIBrowser (HTML/JS)(not in Guest ABI)
:IOWASMsensors, actuators, events
:DATAWASMdata
:CHATWASMintelligence-cache, agents
:CALLWASMagents, events

How a guest interacts with the ABI

A guest program does three things:

  1. Exports the lifecycle entry points: on_init, on_process, on_close. The runtime calls these.
  2. Imports the host functions it needs: sys.Log, net.SendMessage, data.Get, etc. The guest calls these.
  3. Declares its capabilities in the topology — sys.log, net.emit_to, data.read, etc. The runtime enforces the declaration at call time.

A capability the guest doesn’t declare cannot be called — zrun rejects the import at instantiation.

Error conventions

ABI functions use a single pattern:

Return code (int32): 0 = success, negative = error, positive = bytes/count.

Host ABI functions uniformly use int32 return codes. Higher-level (value, error) pairs are a Guest Library concern, not an ABI one.

Import paths

All ABI packages live under:

github.com/anrl/samoza/components/zrun/guest/abi/

Sub-packages:

abi/net      — Network messaging
abi/data     — Key/value storage
abi/node     — Node primitives
abi/sys      — System functions
abi/ic       — Intelligence cache
abi/agent    — Agent invocation
abi/mem      — Memory management
abi/z        — Low-level primitives (rarely used directly)
abi/sys/io   — Stream I/O (audio capture/playback)

Compilation

Guest programs compile with TinyGo targeting WASI:

tinygo build -target wasi -scheduler=none -opt=z -o core.wasm .

Constraints:

  • No fmt package (bloats binary significantly).
  • Use encoding/json for serialization.
  • Use strconv for number-to-string conversion.
  • sys.Log() takes exactly one string argument.
  • main() must exist but should be empty.

Why an ABI

Three reasons:

Stability. The set of imports/exports is fixed. A guest compiled today runs against a runtime built tomorrow without recompilation.

Auditability. Every external action a guest can take is a single import call. The capability list is the audit surface.

Substitutability. Anything that compiles to the ABI runs. TinyGo today, Rust tomorrow, an Anglish-generated guest the day after — the runtime doesn’t care.

See also