04free & installable

message relay / local

Let the agents talk without paying a model to deliver the mail.

When several long-running sessions work on the same thing, they have to tell each other what changed. relay2 is the channel underneath that: a session decides what to say and to whom, and everything after that point, transport, validation, routing, retries, receipts, backpressure, escalation and search, is ordinary software that never calls a model.

relay2 / inbox

pointers, not copies

03 unread 01 ping this cycle state: normal
●
build failed on 5 of 144 checksfrom builder · validation_result
high 4m unread
●
retry policy changedfrom reviewer · carries a --ref
normal 21m read
○
nightly sweep finishedfrom watcher · no reply wanted
low 1h resolved
$ relay2 send --to builder --subject "..."accepted, 1 recipient, 1 pointerexit 0
01

Send

relay2 send --to ROLE validates the address before it writes, so a name nobody owns is refused in front of the sender who can fix it.

02

Store

One canonical copy under messages/originals/. Six recipients get six pointers, not six copies of a 20 KB body.

03

Announce

The watcher coalesces: one ping per recipient per cycle, capped at three lines, and it announces less as a queue gets deeper.

04

Account

relay2 metrics reports bytes carried against bytes opened, so a long report nobody read is visible as one.

testedPython 3.9 and newer
runtimeone machine / local
licenseMIT · free

Written and tested on macOS; the design is POSIX and the one platform assumption is an atomic rename within a single filesystem. A relay root on a network mount is outside what the tests cover, and the documentation says so rather than leaving you to find out.


command surface

Six verbs carry the traffic. The rest is reading it back.

One Python package on your machine and one long-lived process, the watcher. No daemon manager, no service file, no database server, no account and no network access after it is installed.

  • 01 relay2 send --to ROLEsubject, body, type, priority, payload constant
  • 02 relay2 inboxwhat is waiting, in one call constant
  • 03 relay2 read <id>ULIDs; a prefix works when it is unambiguous constant
  • 04 relay2 ack / resolve <id>taken on, versus finished constant
  • 05 relay2 watch --interval 20the only long-lived process; one at a time always up
  • 06 relay2 search / threadFTS over subject, preview and body ad hoc
  • 07 relay2 repair --rebuilddeletes nothing; rebuilds the index from the files after a crash
lifecycle / eight states, not one

Read is not acknowledged

verified

A message moves through created, accepted, delivered, notified, read, acknowledged, resolved, archived. They are kept apart on purpose: a session can read something without taking responsibility for it, and take responsibility long before it has finished.

output
JSON
network
none
model calls
zero
deps
pyyaml

The SLA clock starts at accepted, never at the ping. That is the one decision worth reading twice. A clock that starts at the ping cannot start at all for a recipient that was not running, so its messages can never escalate while every instrument reports healthy.

$relay2 digest --since 15mcounts, threads, open requests

Backpressure is computed from the queue rather than declared by the recipient: normal, busy at six unread, congested at fifteen, critical at forty, offline. Durable delivery is never rate limited. Only the noise is.

$relay2 metrics --since 24hcarried versus opened, and never opened

before you install

What it needs, and what it will not do.

Stated here rather than discovered later. The last item is the one that decides whether this tool is for you at all: it is a channel between processes on one machine, and it announces nothing until you give it something that can announce.

  • 01 Python 3.9 or newerthe installer checks before it installs anything required
  • 02 pyyamlthe only dependency, for the three policy files required
  • 03 one filesystemevery crash guarantee rests on an atomic rename required
  • 04 a watcher runningforeground or backgrounded; a second one refuses the lock for announcements
  • 05 something that can announceone argv in config; ships empty bring your own
  • 06 a role registrya SQLite table of names, if you want unknown ones refused optional
stated / not discovered later

What it does not do

by design

It is not a transport. It never opens a socket, never talks to a terminal and never raises a window. Announcing is one configured argv with the role and the text substituted, passed as separate arguments and never interpolated into a shell string, because a subject is sender-controlled data. It ships empty, and messages still arrive; they are just never announced.

It is not a chat system. A message is an event with a lifecycle, written once and never mutated. Nothing here renders a conversation or holds a session open.

It calls no model. Routing, projection, backpressure, digests, the SLA clock and escalation are arithmetic over an index. The numbers are already in the database, and spending a model call to recover them from prose is the waste this exists to remove.

It does not know who your roles are. The three config files ship as a worked example with placeholder roles and routing rules. Nothing in the code knows any of those strings. Replace them with yours.

platform
POSIX
daemon
one watcher
server
none
account
none
$./install.sh --uninstallremoves the launcher, leaves your messages

install

Unpack it, run the installer, keep the directory.

The installer checks for Python 3.9 or newer, builds a private Python environment under ~/.relay2 with pyyaml in it, and puts a small relay2 launcher in your local bin directory. The launcher points back into the unpacked folder, so leave it where you put it. It is fifty-six lines. Read it first, and read the accept pipeline it runs; that is why both are served as plain text here.

Then set your own role, start one watcher, and replace the three example config files. Uninstall with the same script and the uninstall flag: it removes the launcher and the private environment and leaves every message you have.

$ curl -fsSLO https://auto.relay70.dev/relay2/relay2.tar.gz && tar -xzf relay2.tar.gz && cd relay2 && ./install.sh Download the archive Read the accept pipeline Read the installer Report a problem