Skip to main content
Handlers express orchestration; CEL expresses conditions and field math. When you genuinely need algorithmic work — bounded iteration, aggregation, parsing, structured rendering — a compute module runs it deterministically in a sandbox, without giving up replay or verification.

Declaring a module

Modules are declared in policy.yaml, with their contract stated up front:
policy.yaml
The module itself is ordinary Python with one required shape — def handle(input) taking a dict and returning a JSON-compatible dict. The harness owns all transport; author code never reads stdin, writes stdout, or touches bindings:
modules/renderer.py
For compiled modules, declare kind: wasm instead:
Python modules run on the embedded CPython-WASI interpreter (shipped in the binary, executed through Wasmtime — no local Python needed); kind: wasm runs your compiled module through the same engine. Either way:
  • the declared digest pins the exact bytes into the bundle at compile time
  • execution is metered by the declared limits
  • the sandbox has no I/O — no filesystem, network, clock, or randomness
Same input, same output, forever — which is what makes module calls replayable.

Calling a module

A handler runs its rules: before deciding what to do; a compute-module rule runs there and stores its result in computed.*, which lives only for that handler:
nodes.yaml
The rules that keep this honest, all verified at boot:
  • input values are simple explicit paths rooted in payload, entity, event, or computed — no expressions smuggled in.
  • into must target computed.*. Module output is handler context, not state: persisting it requires an explicit data_accumulation write, with its own owner.
  • A module row cannot emit, advance state, run actions, fan out, or touch entity state — it computes a value, full stop.
  • An unconsumed into binding is a boot error: if nothing downstream reads the value, the declaration is dead and verify says so.

When to reach for one

A compute module is an escape hatch that stays inside the model: logic beyond what rows can express, still deterministic, still verified, still replayable.