Trim the harness to what it needs to keep going
Host: - test first: a new version is tested where it lies; only an installed version goes to versions/, and instances run from there - data/ and public/ are shared by all versions; no snapshots; rollback restores code only - no re-delivery, status.json, list, remove/archive, smoke test, data/ hiding, or stdin timeout; rollback needs a version - supervisor.rs split out; one place for installing a version - init only writes the agent folder; run installs it like any actor - console: @actor, text to the agent, /help, /quit Agent: - every text goes out as a broadcast; 5-line prompt; 5 tools that describe themselves; turn.json only marks an active turn Docs: PROTOCOL.md, README.md, DECISIONS.md, AGENTS.md rewritten. Examples: only notes and notes-v2.
This commit is contained in:
@@ -2,64 +2,59 @@
|
||||
|
||||
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.
|
||||
Sausage is a world of small programs ("actors") that you grow by talking to
|
||||
it. Each actor is a WASI program with stdin and stdout. Actors send each other
|
||||
JSON messages, one per line, through a broker. The agent is an actor too: it
|
||||
writes new actors in Rust, builds them, tests them, starts them, and can
|
||||
change its own code.
|
||||
|
||||
Inspired by [Jiti](https://ghuntley.com/lisp/), but with WASM instead of a
|
||||
Lisp image.
|
||||
## Start
|
||||
|
||||
## Quick start
|
||||
You need [Nix](https://nixos.org/download) with flakes.
|
||||
|
||||
```sh
|
||||
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
|
||||
nix run -- init # creates ./world and builds the agent (a few minutes)
|
||||
nix run -- run # starts the world and a console
|
||||
```
|
||||
|
||||
`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.
|
||||
`init` asks for the API shape (`openai-responses` or `anthropic-messages`),
|
||||
the base URL, the model, and the token. It reads `SAUSAGE_API`,
|
||||
`SAUSAGE_BASE_URL`, `SAUSAGE_MODEL`, and `SAUSAGE_API_TOKEN` first. The
|
||||
values go to `world/actor/agent/data/config.json`. Both commands take another
|
||||
folder as an argument, for example `nix run -- run my-world`.
|
||||
|
||||
In the console:
|
||||
|
||||
```text
|
||||
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)
|
||||
write an actor "notes" that stores notes, and start it → text to the agent
|
||||
@notes {"type":"add","text":"milk"} → a JSON message to an actor
|
||||
@agent hello → text to an actor
|
||||
/quit
|
||||
```
|
||||
|
||||
## Concepts
|
||||
## The world folder
|
||||
|
||||
- **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
|
||||
The folder is the source of truth. Every actor lives in `world/actor/<id>/`:
|
||||
|
||||
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.
|
||||
```text
|
||||
actor.wasm the current version
|
||||
actor.json installed version, running, subscriptions
|
||||
source/ the source of the current version
|
||||
public/ files that the actor publishes
|
||||
data/ the actor's state
|
||||
stderr.log what the actor and the broker write about it
|
||||
versions/<n>/ every installed version: actor.wasm, source/, meta.json
|
||||
```
|
||||
|
||||
See [DECISIONS.md](DECISIONS.md) for every design decision and
|
||||
[SPIKE.md](SPIKE.md) for the spike results.
|
||||
To add or replace an actor by hand, put an `actor.wasm` (and its `source/`,
|
||||
with the tests in `source/tests/`) into its folder. Then restart the world or
|
||||
send `@broker {"type":"scan"}`. The broker tests the file before it uses it.
|
||||
If the tests fail, the old version keeps running, and `stderr.log` says why.
|
||||
|
||||
## More
|
||||
|
||||
- [PROTOCOL.md](PROTOCOL.md): messages, the filesystem, the broker, `cargo`.
|
||||
Read this to write an actor in any language.
|
||||
- [`sdk/`](sdk/): `sausage-actor`, the SDK for Rust actors.
|
||||
- [`examples/notes`](examples/notes): a small actor with a test.
|
||||
- [AGENTS.md](AGENTS.md): how to work on Sausage itself.
|
||||
|
||||
Reference in New Issue
Block a user