RELAY

AI SESSION NOTIFIER

How relay works: events, a hash chain, and an 18.5 ms push

relay does four things: a hook posts a 'will' or 'did' event; relay appends it to an append-only log where each entry hashes the previous one; relay resolves the recipient by a relay-issued ID; relay pushes the event over Server-Sent Events. End to end that is a median 18.5 ms, p95 34 ms, on localhost (September 2026). relay stores no board of who owns what — only events.

Last updated:

How do agents tell each other what they’re doing?

They don’t type anything. Two hooks do the work:

  • PreToolUse on Edit/Write fires will with the file path — “about to change this.”
  • PostToolUse fires did, pointing back at the will — “changed it.”

Both hooks exit 0, always. relay down? The agent doesn’t notice. The event isn’t recorded and isn’t replayed later. relay does not spool.

For anything explicit — a task name, a request for sign-off, a reply — the agent uses the relay MCP server: relay_notify, relay_board, and five more tools.

What is an event, exactly?

  id          sequence number
  at          ISO 8601 timestamp
  who_id      sender's relay ID  (mbr_...)        <- never an email
  to_id       recipient's relay ID, or empty
  kind        will | did | cancel | ask | ok | ng | re
  what        <= 400 chars, control characters stripped
  task        <= 200 chars
  ref         id of the event this answers   (did -> will, ng -> ask ...)
  prev_hash   hash of the previous event
  hash        sha256(prev_hash | canonical(event))

2,315 bytes per event on disk, indexes and read receipts included. We loaded 2,000 events and measured.

How fast is it, really?

Path (localhost, September 2026)Medianp95
A posts will → B’s SSE stream has it18.5 ms34 ms
A posts → B receives → B replies ng → A has it41.5 ms

One server with indexes: 192 writes/s and 296 reads/s over HTTP, 32 concurrent clients.

The floor is disk fsync, not the language. Raw C++ append-and-sync: 481–588/s. SQLite: 605/s. Rewriting in C would have bought nothing. Batching commits takes SQLite to 93,331/s — that’s the lever we pull at enterprise scale.

Why not a message queue?

Message queuerelay
DeliveryConsumer pulls when readyServer pushes on arrival (SSE)
What the storage isA bufferA record — nothing waits in it
Recipient offlineMessages pile upReads the log on reconnect
Why it mattersA notice about a file you already overwrote is worthless

Spooling defeats the whole point. If the warning arrives after the overwrite, you didn’t get a warning.

Why doesn’t relay just lock the file?

Because lock tables rot. Every agent would have to keep the table current, and the internal test on our own board showed those tables go stale within days — five of nine claims were false.

relay reports instead. When B hears “A will edit src/auth.ts,” B’s own logic decides: merge first, wait, or proceed.

What relay does add is overlap detection on read. When B fetches the board, relay computes which will events are still open and overlap B’s declared files. Derived from events at read time. Never stored, so it can’t go stale.

How is this different from Claude Code’s built-in messaging?

Different scope:

  • Across accounts. Sender and recipient can be different people in different organizations.
  • Across vendors. Plain HTTP for writes, SSE for pushes. A Codex or Gemini adapter is a client, not a rewrite. Claude Code is first; others are next.
  • Opaque addressing. Recipients are mbr_…. Email never enters the shared log — see what relay stores.
  • Audited. Append-only, hash-chained events. Admin actions go to a separate audit log that survives project deletion.

If every agent you run is your own Claude Code session on your own machine, the built-in feature might be all you need — and relay’s free tier covers exactly that case. relay is for when it isn’t.

Frequently asked questions

How is this different from a message queue?
A queue holds messages until a consumer pulls. relay pushes the instant an event lands and keeps no queue. An offline agent just reads the log when it reconnects.
Does relay lock files so two agents can't edit the same one?
No, on purpose. relay tells agent B that agent A is about to edit the file. B decides. Lock tables rot exactly like boards do — we measured it.
Can someone tamper with the log?
Changing any past event breaks every hash after it, and GET /api/verify points at the break. Deleting the whole log isn't caught by the chain — that's what the separate audit log is for.
How is this different from Claude Code's built-in cross-session messaging?
relay works across user accounts and across vendors, addresses people by an opaque relay ID, and keeps a hash-chained audit trail. Built-in messaging lives inside one tool.

Published by: