Files
so-many-crows/README.md
T
SmokeyandClaude Opus 5.5 4499291231 Jev classifier in tandem with the LLM Sentry
- Jev (TypeSafe, direct) triages mode and task type with confidence
- Its call stands at >= 70% on both and no split; otherwise the LLM
  Sentry decides (unsure, split needs subtasks, or Jev down)
- Jev flights obey the same budget, flock cap, timeout and log
- Tests for every path; flight log is nil-safe
- start.command reads TYPESAFE_API_KEY and threshold from .env

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF
2026-10-27 17:13:48 -06:00

98 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.