surma 0a8e8c2e3c World folder is the source of truth
- actor/<id>/ holds actor.wasm, actor.json, source/, public/, data/, versions/
- the broker boots by scanning actor/; a changed actor.wasm is an upgrade,
  a rejected one stays in versions/ with a reason and the files come back
- /actor hides every data/ folder
- subscriptions live in the subscriber's actor.json
- cargo installs the SDK and points sausage-actor at it; no build limits
- PROTOCOL.md
2026-10-15 11:14:11 +01:00
2026-10-15 11:14:11 +01:00
2026-10-15 11:14:11 +01:00
2026-10-15 10:47:32 +01:00

Sausage

You can see how the sausage is made.

Sausage is a system of actors that you grow by talking to it. Every actor is a WASI program (a .wasm file) with stdin and stdout. Actors send each other newline-delimited JSON messages through a broker. The agent is an actor too: it does inference over HTTP, writes new actors, and can change its own code.

Inspired by Jiti, but with WASM instead of a Lisp image.

Quick start

nix develop
cargo build --release
export SAUSAGE_API_TOKEN=...            # or type it at the prompt
./target/release/sausage init world --api openai-responses \
    --base-url https://api.example.com --model some-model
./target/release/sausage run world

init builds the agent (the first build takes a few minutes) and writes its configuration to world/private/agent/data/config.json. The source contains no endpoint and no token.

In the console:

hello                               → text to the agent
@notes {"type":"add","text":"milk"} → a JSON message to an actor
@agent what actors exist?           → text to an actor
/deploy notes examples/notes        → build with cargo, then spawn or upgrade
/list                               → list actors
/await agent 300                    → wait for the next message (scripts)
/quit

Concepts

  • Actor: a wasi:cli/command program. It reads messages on stdin and writes messages on stdout. Logs go to stderr.

  • Message: {"id", "from", "reply_to"?, "body"} on stdin; {"to"?, "id"?, "reply_to"?, "body"} on stdout. No to = publish to subscribers. There is no request/response: a reply is a new message with reply_to. Delivery is at most once.

  • Broker: routes messages, owns mailboxes, and runs actors. It accepts only .wasm files: spawn, upgrade, rollback, stop, start, remove, subscribe, unsubscribe, list.

  • cargo: the built-in Rust compiler actor. build a source folder, get a .wasm path back. Other actors can add other languages.

  • Filesystem of each actor:

    • /data: private state
    • /public: its public files
    • /actor/<id>/{public,source,status.json,stderr.log}: every actor, read-only

    A write becomes visible when the writer closes the file (commit on close).

  • Upgrade: the broker tests the candidate on a copy of /data and /public (transcripts in source/tests/*.jsonl). Then it holds new messages, stops the old version, starts the new one, and delivers the held messages. A new version that crashes 3 times in 30 seconds is rolled back.

See DECISIONS.md for every design decision and SPIKE.md for the spike results.

S
Description
No description provided
Readme
1.4 MiB
Languages
Rust 98.9%
Nix 1.1%