Agents generate code now. Somebody has to run it. riz runs it behind three independent walls — a WASI capability sandbox, an OS process boundary with an always-on safety profile, and a host-side resource broker — so "the model wrote it" stops being a production risk. And it all holds for agents too: MCP tool calls and the built-in A2A agent's tool executions dispatch through the same guards and sandbox — no side door.
runtime = "wasm" runs a
wasm32-wasip1 module under wasmtime with
no filesystem and no network unless you grant them — and it's real compute,
not a toy: the shipped example validates and prices an order entirely inside the sandbox,
with sub-millisecond cold starts.
Beneath the WASI wall, every handler process — every runtime, not just WASM —
gets the always-on safety profile: RLIMIT_CORE=0,
file-descriptor and process caps, dies-with-host, no privilege escalation.
Two walls before your code even matters.
wasm_orders_prices_a_valid_order ·
child_with_allowlist_can_read_allowed_path_only ·
child_inherits_always_on_caps
request ↓ WASI capability check deny-by-default fs: no grant → denied net: no grant → denied ↓ your .wasm runs sub-ms spawn ↓ host safety profile always-on rlimits · PDEATHSIG · no-new-privs ↓ response
The classic sandbox trade-off is "safe but useless." The riz broker deletes it:
a [function.x.capabilities] grant lets the guest run
parameterized Postgres queries through the host — Neon, Supabase, RDS,
or any PG is one config row.
READ ONLY transactions — Postgres refuses writes, not string inspectionwasm_guest_brokers_pg_through_capability_grants — the full chain,
riz → wasm child → guest → broker → PG wire, in CI
# credentials live HERE, host-side — never in guest memory [resources.pg.main] dsn_env = "RIZ_PG_MAIN_DSN" # Neon / Supabase / RDS / any PG [function.orders] runtime = "wasm" handler = "./orders.wasm" timeout_ms = 5000 # the grant — the guest can do THIS and nothing else [function.orders.capabilities.db] type = "pg" resource = "pg.main" mode = "read-only" call_timeout_ms = 1500 rate_per_sec = 50
guard_in screens every event before the handler:
allow it, scrub it, or deny with your status — the handler never runs on deny.
guard_out sweeps every response before bytes leave:
redact PII, replace the envelope, or block it.
The property nobody else has: the same guard module wraps Bun, Node.js, Python, Rust, Go, and WASM handlers identically — write your policy once, in any language that compiles to WASM, and every runtime obeys it. And it fails closed: a policy that can't run never silently allows traffic.
one_wasm_guard_protects_every_runtime — allow, deny, mutate,
SSN redaction, and fail-closed, across runtimes, in CI
# riz.toml guard_in = "./guards/validate.wasm" guard_out = "./guards/redact.wasm" # verdicts {"action":"allow"} {"action":"allow", "event":{ …scrubbed… }} {"action":"deny", "statusCode":451, "body":"…"} # guard_out, seen in CI: "ssn":"123-45-6789" → "ssn":"***-**-****"