2026-10-28 09:24:14 -06:00
2026-10-27 17:31:53 -06:00
2026-10-27 17:31:53 -06:00

So Many Crows

A flock of AI agents. Hand it a todo list; a Sentry crow triages each item, crows fly, and trust is earned over time.

Version one: command-line, text-only crows. No web, files, or APIs until each has guardrails.

Run

go build -o crows .
./crows run todo.txt            # offline mock brain (no key needed)
ANTHROPIC_API_KEY=... ./crows run todo.txt   # real crows (Claude)
./crows trust                   # trust ledger
./crows log -n 20               # flight log

Optional: CROWS_MODEL overrides the model. Results land in todo.crows.md; state lives in .crows/.

Web server

cd ui && npm install && npm run build && cd ..   # builds the UI into ./web
./crows serve                   # localhost:8080; API + Server-Sent Events (SSE); Ctrl-C to stop

The server runs the same pipeline as crows run, but items fly in parallel and approvals come over HTTP. EVENTS.md is the contract for events and the API:

curl -XPOST localhost:8080/api/lists -d '{"text":"- [ ] What is a crow","requester":"me"}'
curl -N "localhost:8080/api/events?list_id=<id>"        # replays the list's events so far, then streams
curl -XPOST localhost:8080/api/verdicts -d '{"item_id":"<id>-1","target":"triage","approve":true}'
curl localhost:8080/api/trust
  • Item IDs are <list_id>-<n>, numbered from 1 in list order.
  • Approvals left unanswered for 10 minutes count as rejected (verdict: timeout). -approval-timeout changes this for testing.
  • A flooding requester gets 429 with message and cooldown_s; any list of theirs that is still flying also gets requester.pranked.
  • UI development: run crows serve, then cd ui && npm run dev (Vite proxies /api). The crow art is art/crow.svg; the UI's CrowView mirrors RIVE_CONTRACT.md, so a Rive-backed view replaces the SVG stand-in later.
  • POST bodies are capped at 64 KB. Static files are served from ./web when that folder exists.

Nests

A nest is a room where a team of crows works together. Create one with its core crows; jobs in that nest use the core first and borrow from the rest of the flock when they need more (a murder of 3 in a 2-crow nest borrows one). The Sentry and Elder serve every nest.

curl localhost:8080/api/nests                     # {"roster": [...], "nests": [...]}
curl -XPOST localhost:8080/api/nests -d '{"name":"Launch copy","crows":["Pepper","Inky"]}'   # 201, nest_id "launch-copy"
curl -XPOST localhost:8080/api/lists -d '{"text":"- [ ] Should we launch on a Tuesday","nest_id":"launch-copy"}'
./crows run todo.txt -nest launch-copy
  • The default nest is todo, with an empty core: crows come from the whole flock and are never "borrowed".
  • crow.flying carries borrowed: true for a crow from outside the nest's core.
  • Names are 1–40 characters; nest_id is the name as a slug and must be unique (409 on a clash). 1–8 roster crows, no repeats, at most 20 nests. Nests are saved in .crows/nests.json.

Jev triage (optional)

With TYPESAFE_API_KEY set, the Sentry asks Jev (TypeSafe's classifier) for mode and task type first. Jev's call stands when both answers reach CROWS_JEV_THRESHOLD (default 0.7) and no subtasks are needed. Otherwise the LLM Sentry decides: when Jev is unsure, when it calls a split (the LLM writes subtasks), or when Jev fails. The plan's reason shows Jev's confidence, and the flight log records each Jev call.

How an item flies

  1. Sentry classifies it: solo (one crow), split (2–4 subtasks in parallel), or murder (3 crows answer independently).
  2. Split and murder results go to the Elder, who merges them and flags disagreement.
  3. You approve or reject, depending on trust.

Trust ladder

Level Triage Output
Stranger you approve you approve
Regular you approve auto-accepted, marked unreviewed
Trusted runs on its own runs on its own
  • Promotion: 10 clean approvals in a row (the flock as a whole needs 20).
  • Demotion: one rejection drops a level.
  • A crow's level blends its own record with the flock's record for that task type, so new crows start on the flock's reputation.
  • The Sentry earns triage trust separately, per task type.
  • The least-trusted crow on a job sets the approval bar.

Guardrails (guardrails.go)

Guardrail Default
Crows in flight 5
Murder size 3
Items per list 20
Subtasks per split (depth 1, never re-split) 4
Tokens per item / per list 20,000 / 100,000
Crow timeout 60s
Requests per minute per requester 5
Cooldown 30s, doubling per strike, max 1h

Fail-safe: any answer other than y, including no input, is a no.

Abuse

Flooding the flock earns a mild prank message and a cooldown. Strikes fade one per clean day. Nothing destructive, nothing public.

S
Description
because we shant be calling it a murder in polite society.
Readme
687 KiB
0 Stars 1 Watchers 0 Forks
Languages
Go 89.1%
TypeScript 9.4%
HTML 1%
Shell 0.5%