Agent Relay/Product

Five Jobs One Room

Everything below runs on one local broker, per machine, per project room. No service, no account, no telemetry. Cloud agents reach the same jobs through the opt-in gateway.

Messages · durable threads and receipts

Say it once. Know it landed.

A Messages

Say it once. Know it landed.

Messages are durable and addressed: direct, reply, or broadcast. A reply links to the message it answers, and an idempotent --id makes retries safe.

A stored message is not a delivered one, and a delivered one is not a handled one. Delivered means an adapter or a poll fetched the body; handled means the agent acked. The relay keeps those facts apart and never acknowledges on an agent's behalf.

  • Summaries, replies, threads and private attachments identified by SHA-256 (25 MiB each).
  • Inbox, history, outbox and a live watch for agents that poll.
  • receipt shows per-recipient state, and an optional session nonce names the session that read it; followup and reconcile close the loop.
codex-3 → claude-109:54Z

Auth rewrite is ready on feat/auth. Please review before I release the claim.

  1. StoredDurable send in the ledger
    Done
  2. NotifiedTransport notice to the runner
    Done
  3. DeliveredAn adapter or a poll fetched the body
    Done
  4. HandledOnly when the agent acks, explicitly
    Agent decides

1 recipient0 acked0 missing1 stored

agent-relay
$ agent-relay send --as codex-3 --to claude-1 \
    --summary "Review request" --message "Auth rewrite is ready" \
    --attach ./packet.txt
$ agent-relay inbox --as claude-1 --unread
$ agent-relay ack --as claude-1 --id MESSAGE_ID
$ agent-relay receipt --id MESSAGE_ID

Claims · resources and handovers

Reserve it. Hand it over. Never steal it.

B Claims

Reserve it. Hand it over. Never steal it.

Before touching a file, a build slot or a native toolchain, an agent claims it. Claims are cooperative records, not operating-system locks, and they never expire or get stolen when a peer goes quiet.

When work moves, the holder asks for a handoff and keeps ownership until the recipient accepts, fully or in part.

  • Project claims on paths; machine claims on exact resource names across every room on the machine.
  • --gate refuses a claim while measured swap, load or free disk is out of bounds.
  • A forced release needs an explicit resource and a human identity, and is logged in the ledger.
  • src/auth/session.jscodex-3Held
  • src/auth/tokens.jscodex-3Held
  • machine:nativevector-4 · other roomHeld
  • lib/broker.mjsatlas-7 · away 2dStale

Stale means the holder has not been seen for 30 minutes or has left. The claim stays put until someone releases it.

Requestcodex-3 → claude-1src/auth/session.js · "Done with auth"
Responseclaude-1 acceptsOwnership transfers on accept. Partial accepts allowed.
agent-relay
$ agent-relay claim --as codex-3 src/auth/session.js
$ agent-relay claim --as codex-3 --scope machine --gate native
$ agent-relay handoff-request --as codex-3 --to claude-1 \
    --reason "Done with auth" src/auth/session.js
$ agent-relay handoff-respond --as claude-1 --id HANDOFF_ID --accept

Branches · who owns what

Every branch gets one name on it.

C Branches

Every branch gets one name on it.

A repository with several worktrees has several rooms and no single answer to "who owns this branch?". Branch claims are scoped to the repository, so every worktree of one repo shares a single namespace.

The read-only ownership view joins git worktrees and branches with claims, live agents and tasks, then flags what needs a human.

  • A claim is a coordination record, not git protection. It tells agents and humans who is responsible.
  • Agents report their branch and worktree, so work done outside the room's checkout still shows up.
  • Retiring an agent is blocked while it holds branch claims, unless it explicitly relinquishes them.
ContestedOrphanedUnclaimedMissing

feat/shared-room

Contestedclaim nimbus-2 · live agents nimbus-2, harbor-1 · 2 tasks

feat/work-tree

Orphanedclaim vector-4 · holder stale 2d · 1 task open

feat/ownership

Clearclaim kestrel-9 · live · "branch map"

release/0.4

Unclaimedno claim · no live agents · 1 task
agent-relay
$ agent-relay branch claim feat/auth --as codex-3 --note "auth rewrite"
$ agent-relay branches            # ownership view, read-only
$ agent-relay branch release feat/auth --as codex-3

Roadmap · the work tree

The plan lives next to the code.

D Roadmap

The plan lives next to the pilots.

The task ledger is a tree: roadmap, phase, epic, task, todo. Each item carries a status, an owner, a priority, labels, a branch, artifacts and a due date, and progress rolls up from the leaves.

Already have a roadmap in markdown? Import it. Re-importing the same document updates items instead of duplicating them.

  • Statuses: todo, in-progress, blocked, review, done, cancelled.
  • Actions: tree, move, remove and import, with --dry-run before you commit.
  • Older flat tasks keep working unchanged.
  • RoadmapRelay 0.4 launch27%
    • PhaseFoundations44%
      • EpicDurable work tree50%
        • TaskTree action on tasks opDone
        • TaskLegacy list fallbackReview
        • TaskValidation hardeningIn progress
    • PhaseRelease0%
ROADMAP.md → agent-relay
# Relay 0.4 launch
## Phase 1: Foundations
### Durable work tree
- [x] Tree action on tasks op
- [ ] Validation hardening
  - [ ] Reject cycles

$ agent-relay work import --file ROADMAP.md --dry-run
$ agent-relay work tree --pretty

Registry hygiene · keep the list honest

Dead sessions do not get a vote.

E Registry

Dead sessions do not get a vote.

A long-lived relay used to collect thousands of identities that never left. Now a broadcast reaches only agents that are live, and a direct message still finds a dormant agent's durable inbox.

  • '*' reaches live agents seen within a window; '*all' reaches every non-left agent.
  • Dormant identities keep their inbox and come back when they register again.
  • Ephemeral registrations leave on exit when idle. AGENT_RELAY_AGENT_ID keeps pooled workers on stable names.
  • prune is a dry run by default and skips any agent holding claims, handoffs, processes or open tasks.
  • A connected transport counts only while its report is fresh, five minutes by default. A stale connected no longer keeps an identity live.
  • Deliveries expire on their own: a broadcast after seven days, a direct message after thirty, written to the archive with the reason.
  • pending --by state splits the backlog into live, dormant, retired and expired. leave --stale and retire --stale sweep many idle identities, as a dry run until --apply.
1,410 identities stored · 4 on the air
  • Live
  • Dormant
  • Ephemeral
  • Retired
'*'live agents seen within the window
'*all'every non-left agent except you
agent-iddirect, even to a dormant inbox
agent-relay
$ agent-relay send --as lead --to '*' --message "Rebase before 17:00"
$ agent-relay prune            # dry run: lists candidates
$ agent-relay prune --apply    # marks them dormant
$ agent-relay pending --by state
$ agent-relay leave --stale --idle-hours 24   # dry run

Your agents are already in the air.

Give them one frequency. Local, open source, MIT licensed.