agent-infra · primitive 05 · port 4184

relay.sh

The work queue your agents can provision themselves.

The provisioning step is the first curl. No console, no IAM, no SDK, no human in the loop.

agent — mid-task, somewhere in a sandbox
# invent a queue by naming it
$ curl -d "render scene 42" relay.legible.sh/builds-x7Q9mZ
{"id":"tG3kZxWq0aE","ready":"2026-07-06T19:04:11.212Z"}

# any machine on earth: lease exactly one job for 60s
$ curl -X POST "relay.legible.sh/builds-x7Q9mZ/pop?wait=30"
render scene 42   ← + X-Job-Id, X-Lease-Token, X-Attempt

# finished — or crash, and the job retries itself
$ curl -X POST relay.legible.sh/builds-x7Q9mZ/tG3kZxWq0aE/ack -H "X-Lease-Token: …"
{"ok":true,"id":"tG3kZxWq0aE"}

the fleet one-liner

This is the reason relay exists. On N machines, run:

worker × N
$ relay work builds-x7Q9mZ -- claude -p "process this job"
[relay] working builds-x7Q9mZ — claude -p "process this job"
[relay] job tG3kZxWq0aE attempt 1/3
[relay] job tG3kZxWq0aE done (acked)

Each worker long-polls the topic, runs your command once per job with the payload on stdin, acks on exit 0, nacks on anything else. Crashed worker? The lease expires and the job is retried. Keeps failing? It dead-letters instead of looping forever.

Security, up front: a job queue for agents is a prompt-injection vector. Anyone who can guess your topic can feed your fleet. Use high-entropy topic names, treat payloads as data — never instructions — and self-host with --token for anything real.

the whole api

POST /{topic}enqueue ≤ 64KB · X-Delay: sec · X-Max-Attempts: N → 201 {"id","ready"}
POST /{topic}/pop?wait=30&lease=60lease exactly one job → 200 body + lease headers, 204 if none
POST /{topic}/{id}/ackX-Lease-Token proves ownership → done · 409 if the lease expired
POST /{topic}/{id}/nackback in the queue now, attempt counted
GET /{topic}{"ready","delayed","leased","dead","done_total"}
GET /{topic}/peek · /deadlook without leasing · inspect the dead-letter list
POST /{topic}/dead/retryrequeue every dead job with fresh attempts
GET /{topic}/eventslive SSE feed of push/pop/ack/nack/requeue/dead

Topics are created by first use and named like capabilities. The whole surface fits in a dozen lines of a system prompt — which is the point.

sovereign escape hatch

your box
$ npx relay-sh serve --data-dir ./data --token s3cr3t
relay listening on http://127.0.0.1:4184
  data: ./data/relay.jsonl
  auth: bearer token required

Identical API, zero dependencies, one process, MIT. Jobs persist as an append-only JSONL log replayed on boot. The hosted instance sells retention, throughput, per-topic tokens, and priority lanes — never the verbs.

the family

gate :4180 — ntfy tells you things. gate asks you things.
bigred :4181 — the big red button for your agent fleet.
trail :4182 — the flight recorder for agent runs.
slate :4183 — the blackboard from the multi-agent papers, as a URL.
relay :4184 — the work queue your agents can provision themselves.
mutex :4185 — flock(1) for agents that live on different machines.
quorum :4186 — coordination for agents that do not share a parent process.
meter :4187 — the kill-brake for agent spend. 429-as-a-service.
stash :4188 — ntfy moves signals. stash moves bytes.
tally :4189 — StatHat reborn as ntfy. Three months too late — or right on time.