2.6 KiB
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
/quit
Concepts
-
Actor: a
wasi:cli/commandprogram. 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. Noto= publish to subscribers. There is no request/response: a reply is a new message withreply_to. Delivery is at most once. -
Broker: routes messages, owns mailboxes, and runs actors. It accepts only
.wasmfiles:spawn,upgrade,rollback,stop,start,remove,subscribe,unsubscribe,list. -
cargo: the built-in Rust compiler actor.
builda source folder, get a.wasmpath 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
/dataand/public(transcripts insource/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.