What it does
hasky.chat is my Nostr relay, and I made a choice most relay operators don't: anyone can post. Which means I need a bouncer — but one bouncer checking IDs one at a time is slow. HuskGuard is three bouncers working the door at once. SpamWatcher sniffs for airdrop bait and link-stuffing. NipComplianceWatcher checks whether the note is even shaped correctly (all-zeros pubkey? nice try). PolicyWatcher only cares about the genuinely nasty stuff — threats, doxxing — and is deliberately relaxed about everything else, because an open relay should stay open. Each sees only its own lane and gives a verdict with a reason. A Judge waits for all three and rules the moment the last one lands, whatever order they showed up in. It's not a mock — it watches the real relay, and `npm run inject` fires test notes at it so you can watch the swarm argue in real time. Bonus: built on a brand-new laptop that had no Node, Homebrew or Git installed at kickoff.
How the agents run concurrently
Built on @mozaik-ai/core 4.x. Every incoming Nostr note becomes one `relay.event`. Mozaik fans it out to all participants without awaiting anyone, and each watcher's SituationHandler calls runLoop() fire-and-forget with a fresh ModelContext per note — three model calls in flight at once, no coordinator, no shared cursor. Watchers answer via structured output ({ eventId, verdict, reason, confidence }), which is how votes get matched to notes when they land out of order. The Judge is a reaction on `model.answer` that keeps votes in shared RuntimeState and rules when the third vote for a given eventId arrives. The transcript logs millisecond offsets, and the order of the three watchers differs on almost every note — that's the concurrency, visible.
Newsletter
For developers who want to learn how to build self-organizing agents.
Join our online hackathon
Join our online hackathon for building multi-agent systems.