arizuko

arizukoproducts › Company brain — setup

Company brain — setup

Design your folder tree, wire intake sources, populate facts/, schedule briefs. One team at a time.

prerequisites

1. create the instance

arizuko create corp
cd /srv/data/arizuko_corp
$EDITOR .env
ASSISTANT_NAME=corp-brain
WEB_HOST=brain.example.com
ANTHROPIC_API_KEY=sk-ant-…

# Slack (recommended primary channel)
SLACK_BOT_TOKEN=xoxb-…
SLACK_SIGNING_SECRET=…

arizuko create already generated AUTH_SECRET and SECRETS_KEY in .env — leave those alone.

2. design the folder tree

Sketch the org chart first — it becomes the folder tree. Start with two levels max. Add depth when you hit a real coordination problem (e.g. the SRE oncall rotation needs its own diary, separate from the SRE team). Don’t pre-build folders “just in case.” An empty folder adds nothing and costs a route rule.

Example for a 40-person eng company:

corp/           # root intake triage desk
corp/eng/       # engineering channel + PR review ingest
corp/eng/sre/   # SRE runbooks + Sentry ingest
corp/pm/        # roadmap + Linear ingest
corp/sales/     # deal notes + CRM webhook

3. create the folders and route rules

Create each group folder with arizuko group corp add <jid> <folder>. The <jid> is the source chat that should land in this folder; the route row is written for you.

# create folders (jid first, then folder)
arizuko group corp add 'slack:T-acme/channel/C0ONCALL' corp/eng/sre/oncall
arizuko group corp add 'slack:T-acme/channel/C0ENG'    corp/eng
arizuko group corp add 'slack:T-acme/channel/C0PM'     corp/pm
arizuko group corp add 'slack:T-acme/channel/C0SALES'  corp/sales
arizuko group corp add 'web:corp/intake'               corp/intake

Then the catch-all: an empty match expression matches every message, so anything no other rule claims lands in the intake folder. Hook routes come in step 5, once the tokens exist:

arizuko route corp add '' corp/intake --seq 10

For bulk or GitOps-style edits, declare the same rows in a YAML manifest and arizuko apply corp corp-routes.yaml instead.

Route priority: more specific rules (lower seq) win. The catch-all at corp/intake handles anything that doesn’t match a more specific rule — handy for new webhook sources while you’re still wiring them up.

4. populate each team's facts/

facts/ is the team’s knowledge base. The agent reads it on every relevant turn. Start with what teams actually use: runbooks, decision logs, reference docs. Don’t dump everything — curated, short files beat a wall of stale text.

Three ways to populate:

5. wire webhook sources

Mint a hook token for each external source, then route the token’s JID (hook:<folder>/<label>) to the folder that should handle it:

# Sentry alerts
arizuko token corp issue webhook corp/eng/sre/oncall sentry
# webhook URL: https://brain.example.com/hook/<token>
# Paste into Sentry: Organization Settings → Integrations → Webhooks
arizuko route corp add 'chat_jid=hook:corp/eng/sre/oncall/sentry' corp/eng/sre/oncall --seq -10

# GitHub
arizuko token corp issue webhook corp/eng github
# Paste into GitHub repo → Settings → Webhooks
arizuko route corp add 'chat_jid=hook:corp/eng/github' corp/eng --seq -5

The body arrives verbatim in the target folder; parsing is skill work on the agent side. See webhooks for signature verification and security model.

6. schedule briefs

Scheduled tasks fire a Turn in a target folder on a cron schedule — no host cron, no systemd timer. The scheduler (timed) is part of the stack. There is no dedicated CLI subcommand for tasks; add them in the dashd tasks admin at /dash/, declare scheduled_tasks rows in a manifest for arizuko apply, or ask the agent:

/new schedule briefs
@corp-brain schedule a recurring task:
  folder: corp/eng   cron: "0 9 * * 1-5"
  task: write daily standup summary to facts/briefs/today.md and send to #eng-standup

The agent writes the task row via the schedule_task MCP tool; timed picks it up and fires the prompt on schedule. Examples:

foldercadence (cron)task
corp/eng0 9 * * 1-5write daily standup summary to facts/briefs/today.md and send to #eng-standup
corp/pm0 8 * * 1write weekly roadmap digest to facts/briefs/week.md and send to #pm-digest
corp/eng/sre0 18 * * 5write on-call handoff brief and send to #eng-oncall

Keep the task instruction specific: what to produce, where to write it, where to send it.

7. run

arizuko run corp

Install the systemd unit for production; see getting started for the template.

8. verify

9. per-folder grants

By default, each folder’s agent can read its own facts/, write its diary, and reply on the configured channel; nothing crosses folders. The CLI grant is admin-scoped — it gives a person admin over a folder subtree ('**' makes them an operator):

arizuko group corp grant google:cto@acme.com 'corp/**'

Finer rules — who may interact in a folder, which MCP tools an agent may call, deny effects, cross-folder read — are grant rows managed from /dash/ → Grants. Full rule syntax: grants.

10. observe-mode ingest

For Slack channels where you want context but not replies — general chatter, off-topic channels — route to <folder>#observe. The agent indexes the messages; no Turn fires; nothing gets sent to the channel.

Add the observe route (the #observe fragment on the target makes the agent watch without replying):

arizuko route corp add 'chat_jid=slack:*/channel/C0GENERAL' 'corp/eng#observe' --seq 5

You can also add it in the dashd routes admin UI at /dash/, or declare it in a YAML manifest and arizuko apply.

When the agent in corp/eng is answering a question, it can surface context from the observed #general channel via find_messages without the channel ever knowing.

common issues

Webhook arrives but no Turn fires.
Check the route table matches the hook JID exactly (hook:corp/eng/sre/oncall/sentry for a token issued to corp/eng/sre/oncall with label sentry). Run arizuko get corp routes and compare against the chat_jid in the journalctl ingest log line.
Timed brief fires but the agent sends nothing.
The task instruction probably doesn’t include a send instruction. Edit the task body (in dashd tasks admin) to include “send to #<channel>” or the agent will write the brief to facts/ and stay silent (correct behavior if that’s all you asked).
Agent replies in the wrong folder.
Route priority. Run arizuko get corp routes and check seq values — lower wins. Add a more specific rule with a lower seq via arizuko route corp add to override the catch-all.

go deeper