arizuko

Shape an agent system by talking to it. You say what you want; an LLM edits the files that are the system — persona, memory, skills, routing, even an operational fix. The conversation is the console; there’s no separate config screen.

What keeps that safe is the daemon structure. Each part runs in its own compartment — routd routes and authorizes, runed runs the agent, authd issues identity and tokens — behind hard walls: folder scoping, a permission gate on every action, a fresh container per turn. So shaping by language stays inside the permissions you set; it never becomes a black box you can’t audit.

And every change lands as files you own. The config is text you can diff, review in a PR, and roll back with git revert, on your own server. Language makes it easy to shape; the compartments keep it bounded; ownership makes it permanent.

What you build this way is products you own — a Slack team agent, a personal life agent, a company brain. Each is a folder of files: persona, memory, skills, permissions. The same fixed pipeline runs all of them; only the folder and the routing change. Not a chatbot you rent, and not an opaque SaaS agent you tune through a text box.

see it

what you’d build

one shape under everything

It looks like a lot — channels, tasks, webhooks, secrets, delegation. It isn’t. Every one of those is the same six-step pipeline with different folder contents. Trace one Slack mention top to bottom:

Slack @mention in #eng
  → Event          one inbox row
  → Routing        → corp/eng/oncall
  → Agent          folder loaded: persona, skills, memory
  → Authorization  may it read / send / delegate here?
  → Turn           one container run, then it exits
  → State          rows written, files edited
  → reply in the thread

A scheduled task is the same pipeline — the event is a clock tick. A webhook is the same pipeline — the event is a POST. Nothing here is a special case, so the surface stays small: the parts don’t multiply.

Those parts stack into what you run and what you ship:

LayerWhat it isExamples
Primitivesthe conceptsEvent, Routing, Agent, Authorization, Turn, State
ComponentsGo packagesstore, router, auth, runed
Daemonsrunning processesauthd + routd + runed; webd, timed, slakd
Productsagents you installSlack team agent, reality agent, company brain

A product sits at the bottom: the same pipeline, a different folder. That’s why a support agent and a personal life agent run the same code — the difference is what’s in the folder, not the machinery underneath. See the six primitives →

agents as data

An agent is a folder of files the LLM loop reads. The persona is a file. Memory lives on disk. Skills are directories. Config is a file you can diff, review in a PR, and roll back with git revert. The org chart is the folder tree.

Each folder is a wall: corp/sales doesn’t see corp/eng/sre’s memory. Change the persona by editing a file; the next session picks it up. Add a skill by dropping a directory. You can read everything an agent knows, audit it, and swap it out.

Agents need structure the same way people do — enough to know what they can reach, what their job is, and who they answer to. Small parts with one job each give them that: nothing hidden, parts that fit together. A system a person can reason about is one an agent can manage. That rule drives the whole design.

why not a shared assistant?

arizuko gives each team its own agent, memory, channels, and policy on your own host. Config is files. Rollback is git revert.

how it works

A folder is an agent: PERSONA.md, skills/, memory files, and an ACL row. When a message arrives, arizuko starts a Docker container for that folder. The container connects to routd over MCP on a unix socket. Every tool call goes through that socket; the host controls what the agent can reach. Every platform operation is an MCP tool and a REST endpoint — no separate agent API. All state is in SQLite WAL; the container is stateless.

The stack is for agent teams: dozens of messages a day, not consumer-scale traffic. Go binaries, Docker Compose, SQLite WAL, proxyd signing identity headers — no Auth0, no Redis, no Vault.

organize

ingest

coordinate

connect

operate

start small, grow into it

A minimal deploy is the three core daemons (authd, routd, runed) and one channel adapter. Add components as you need them — each is a standalone binary with its own TOML block. There’s no managed control plane; every piece is replaceable.

SetupWhat runsBest for
Minimal authd+routd+runed + one adapter First deployment, one team
Standard + dashd + timed Ongoing ops, scheduled tasks
Multi-team + onbod + crackbox Isolated teams, egress control
Prebuilt recipe Pre-seeded config slack-team, reality — 5 minutes

One tar of /srv/data/arizuko_<name>/ backs up the entire instance: the daemon DBs (routd.db, runed.db, auth.db — all WAL), group folders, per-user memory, secrets, agent files.

show me

# seed the instance directory
arizuko create demo
# /srv/data/arizuko_demo/ now has .env, store/, groups/, ipc/, web/pub/

# pick adapters + tokens
$EDITOR /srv/data/arizuko_demo/.env

# register the first group's inbound JID
arizuko group demo add tg:-123456789 main

# render docker-compose.yml from .env + extras, then bring it up
arizuko run demo
# systemd unit: arizuko_demo (sudo systemctl status arizuko_demo)

# talk to the default group from a browser
arizuko token demo issue chat main   # prints a /chat/<token>/ URL

# or from a script — same endpoint, JSON in / JSON out
curl -X POST https://example.com/chat/<token>/ \
  -H 'Content-Type: application/json' \
  -d '{"text":"hello"}'

go deeper

v0.49.0 · MIT · Go + SQLite (WAL) + Docker · running on krons, marinade, sloth.