A live governance layer for swarms of autonomous AI agents.
Agents do real work; an independent Warden authorizes, denies, or escalates every action against written policy, and records an immutable, regulator-readable audit trail. When an agent tries to break the rules, the Warden catches it — live. The whole system is visualized as a living hive: agents are bees, the Warden is the comb every bee must pass through, and every decision animates as color (green allow, amber escalate, red deny).
Built at the Claude Build Day (San Francisco, June 13, 2026) on Claude Opus 4.8.
🔴 Live: https://efficient-adventure-production-85e6.up.railway.app — seeded on boot, the hive
renders live. Walkthrough in DEMO.md.
Why this matters. Autonomous agents are capable enough to run real operations — moving money, contacting customers, touching critical systems. They are not deployed in serious, regulated settings for one reason: no one can prove an agent stayed within its authority. THE HIVE makes agents accountable, and therefore deployable: every action passes a governance layer with written policy, human approval gates, and an audit trail an auditor could read.
The live domain is regulated financial collections/servicing — a swarm working a synthetic loan portfolio. The governance layer is the product; finance is just the setting. The architecture is domain-agnostic (see the Guard seam), so the same Warden could govern agents in any domain.
┌──────────────────────────────────────────┐
React + PixiJS hive ◀──┤ SSE /events (allow ▸ green │
(bees + the comb) │ escalate ▸ amber │
▲ │ deny ▸ red) │
│ live events └──────────────────────────────────────────┘
│ ▲ emits every decision
│ │
┌───────┴────────────────────────────────────────────────────────────────────┐
│ Express server (one Railway service: serves web build + API + SSE) │
│ │
│ Worker agents ──propose──▶ Orchestrator ──the ONLY executor──▶ effects │
│ (sim + Opus 4.8) │ │
│ │ dispatch(action) ALWAYS calls ▼ │
│ ┌────────────── THE WARDEN (Guard seam) ──────────┐ │
│ │ guard.authorize(action, context) │ │
│ │ 1. kill-switch gate (halts everything) │ │
│ │ 2. pluggable policy backend ◀── policies.yaml │ │
│ │ → { allow | deny | escalate, policyId } │ │
│ └───────────────┬───────────────────────────────────┘ │
│ │ every decision │
│ ┌──────────────────────────────┼─────────────────────────────┐ │
│ ▼ ▼ ▼ │
│ Append-only audit log Human approval inbox Exception queue │
│ (hash-chained, verifiable) (sensitive actions wait) (recon mismatch) │
│ │ │
│ └──▶ regulator-readable export (JSON + Markdown, integrity attested) │
└──────────────────────────────────────────────────────────────────────────────┘
Vision path: document image ──▶ Opus 4.8 extract ──▶ map to loan ──▶
reconcile via the Warden (payment_post) ──▶ POST or EXCEPTION
Every action an agent wants to take is an Action envelope ({type, agentId, loanId, amount, text, ...}). Agents cannot execute anything — they only propose(). The Orchestrator is
the single executor, and it routes every proposal through guard.authorize(action, context)
before any effect runs. This makes "no unmediated action" true by construction: there is no
other code path to an effect.
guard.authorize does two things in order:
- Kill-switch gate — if the global kill-switch is engaged, nothing is authorized.
- Pluggable policy backend — today a
LocalPolicyEnginethat readspolicies/policies.yaml. Swap it for an external governance API with the sameevaluate(action, context)shape and no agent code changes.
The backend returns { decision, policyId, reason }. Decisions are logged on every call to an
append-only, hash-chained audit log; altering or deleting any entry breaks the chain and is
detected by verify().
| Rule | Policy ID | Behavior |
|---|---|---|
| Transaction scope | POL-SCOPE-001 |
Amount over the agent's scope → deny + escalate |
| Contact frequency | POL-FREQ-001 |
> 2 contacts / rolling 7 days → deny |
| Contact hours | POL-HOURS-001 |
Outside 09:00–18:00 local, Mon–Sat → deny |
| Banned language | POL-LANG-001 |
Outbound text matching banned_phrases.txt → deny (pre-send) |
| Sensitive actions | POL-GATE-001 |
write-off / restructure / bureau-report → escalate (human approval; no self-approval) |
| Data minimization | POL-PII-001 |
Outbound exposes at most last-4 of any identifier → else deny |
| Reconciliation | POL-RECON-001 |
Doc amount must match the ledger → else escalate to exceptions |
- Vision — Opus 4.8 reads a messy, stained synthetic loan statement and extracts amount, reference, account last-4, and date; the amount is then reconciled against the ledger through the Warden. Not basic OCR — extraction + reconciliation + a policy decision in one governed flow.
- Independent adversarial verifier — a fresh-context sub-agent (see
workflow/verify.workflow.js) grades the running system againstRUBRIC.mdand gates completion on two consecutive full-PASS runs. Reports land inverifier_reports/.
thehive/
├── policies/ policies.yaml (written authority) + banned_phrases.txt
├── data/ generate.js → ~5,000 synthetic loans, task set, demo statement images
├── src/
│ ├── guard/ the Warden: guard.js (seam), localPolicyEngine.js (backend), policyTypes.js
│ ├── engine/ orchestrator.js (sole executor), agent.js (propose-only), rogue.js, swarmRunner.js
│ ├── audit/ auditLog.js (append-only hash chain), export.js (regulator report)
│ ├── vision/ visionFlow.js (Opus 4.8 extract → reconcile → governed post)
│ ├── events/ bus.js (SSE fan-out)
│ ├── llm/ anthropic.js (one wrapped Opus 4.8 client)
│ ├── system.js assembles the whole system (used by server + tests)
│ ├── routes.js HTTP API + SSE
│ └── server.js Express app; serves web build + API
├── web/ React + Vite + PixiJS living-hive UI
├── test/ node:test suites — one+ per RUBRIC rule
├── workflow/ verify.workflow.js (adversarial verifier dynamic workflow)
├── verifier_reports/ verifier output
└── BRIEF · RUBRIC · ORCHESTRATION · NOTES · DEMO
cd thehive
npm install # also seeds synthetic data (postinstall)
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env # for Opus 4.8 vision (optional; falls back offline)
npm run build # build the web app (web/dist)
npm start # http://localhost:8080Run the test suite (hermetic — no live API calls):
npm testThe engine runs end-to-end with the visualization removed — the hive is the skin, not the
substance. Set HIVE_OFFLINE=1 to disable live Opus calls and use deterministic fallbacks.
See DEMO.md for the live walkthrough script.
Apache 2.0. Synthetic data only — no real persons, institutions, or identifiers.