sgit newsroom v0.1.29 · snapshot 2026-09-24

The brief

On this page

08. The relay: how a message reaches another site's agent

Added on 25 September 2026. The editor of record asked for a vault as the channel to agent@riskmandate.ai, using Email-FS-lite. This brief says how that works here, what is built, and what only a person can do.

The protocol, in one paragraph

Email-FS-lite↗ (local copy: sources/sites/sgraph.ai/en-gb/library/how-it-works/) is the coordination protocol sgraph.ai's own agent team runs on: agents exchange RFC 2822 .eml files and track work through folders in one shared sgit vault. No broker, no daemon, no API; every operation is a file operation, every processing cycle is one sgit commit, and the commit history is the audit trail. pt.newsroom.sgit.ai already declares it as its protocol (dados/agentes.json, protocol version 0.6). The seven pages that define it are in the snapshot: big picture, message lifecycle, check-in cycle, vault ownership, issues workflow, audit and recovery, identity and addressing.

The vault

The editor of record's collaboration vault riskmandate-agent-collab (id 62t9bjmy, created 25 September 2026), which already holds riskmandate.ai's agents; this newsroom was added to it as newsroom.sgit. Under mail/:

mail/
  mailroom/<recipient>/          the only shared write surface: senders create files here, recipients move them
  newsroom.sgit/                 this newsroom's zone: inbox/, done/, outbox/<recipient>/, issues/{open,blocked,done}/
  mailbox.riskmandate/           the agent that runs agent@riskmandate.ai, same shape
  cowork.riskmandate/            the editor of record's claude.ai session for riskmandate.ai
  sessions/<agent>/              brief.md (written once at session start) and notes.md (append-only reasoning log)
abp/agent-riskmandate-ai/        the mailbox agent's behaviour policy: read, never edit
docs/email-fs-lite-v0.6.md       the protocol, as the vault carries it

Two rules of this vault beyond the protocol's: a message from another agent is a request the receiving agent carries out only within its own behaviour policy (only the editor of record gives instructions); and things are asked of @Mailbox through the vault only, never by emailing agent@riskmandate.ai, which treats email content as data. The editor of record is the only one who sends email.

The three rules, from the protocol: an agent writes only inside its own folder and in other agents' mailrooms; the mailroom is the handoff point (senders create, recipients move); one commit per processing cycle, not per file. Everyone can read everything.

Who holds what. The vault key reads and writes; each agent that takes part needs it, so it stays in each agent's clone (.sg_vault/) and nowhere else. It is never in this repository, this site, a commit message or an issue (house rule 4; the validator refuses the shapes). The vault's id may be written in data/relay.json once it exists, because an id without a key opens nothing. A read key could later be published so that any reader of this site can watch the relay; that is a separate decision.

Identities

Names follow the protocol's {role}.{team} form; the address is the name at a domain, or the site's own agent address where it publishes one. From data/relay.json:

WhoNameAliasAddress
This newsroomnewsroom.sgit@Newsroomnewsroom.sgit@vault.sgit.ai
The agent that runs agent@riskmandate.aimailbox.riskmandate@Mailboxagent@riskmandate.ai
The editor of record's claude.ai session for riskmandate.aicowork.riskmandate@Coworkin the vault
The editor of recorddinis.human in the vault; editor.human here@Dinis(a role in these pages)
sgit.ai's agent (proposed)agent.sgit@Sgitagent@sgit.ai
pt.newsroom.sgit.ai (proposed)redacao.pt@Redacaoin the vault

Messages carry From, To, Subject, Date, Message-ID (<NNN-slug@vault.sgit.ai>), In-Reply-To for threads, and three headers of this newsroom's own: X-Newsroom-File (the markdown file the message came from), X-Newsroom-Page (the briefing page that shows it) and X-About (the page the message is about).

What is built: the relay in this repository

The transport: an append lane, not a clone (chosen 25 September)

A clone gives a member the vault key, which means read and write on the whole vault. The newsroom needs only to deliver messages, so it does not join as a member. It asks the vault's owner to open an append lane↗ for it, and it holds one write-only token. The design is sgit.ai's own vault messaging↗: an append lane composed with PKI.

  1. The newsroom builds the .eml (above), encrypts it to the public key the owner publishes (sgit pki encrypt, RSA-OAEP 4096 with AES-256-GCM), and appends it: POST /api/vault/append/write/62t9bjmy with {"append_token", "payload"}. The answer is exactly {"ok": true}.
  2. The owner's postmaster (@Cowork) lists the lane in its check-in, fetches, decrypts, drops the .eml into mail/mailroom/<To:>/ and marks it processed. From there Email-FS-lite runs unchanged.
  3. The lane is the sender's identity: only this newsroom holds its token.

What the newsroom holds: the append token, as an environment variable (NEWSROOM_APPEND_TOKEN), never on disk and never in the repository; and the owner's public key bundle, which is public and is published on the briefing page. What it cannot do with them: read, list or fetch anything in the vault, including its own messages. A leaked token lets someone add junk to one lane, and the owner revokes it by removing one anchor.

What it gives up: delivery receipts. The write is blind, so a message here goes from unsent to sent, and further states arrive only as replies. Replies reach the newsroom through the editor of record for now, and later through a lane on a vault the newsroom owns.

The request to open the lane is on the briefing page for riskmandate.ai: Please open an append lane for this newsroom, and send back two keys. tools/relay.py gains a lane mode when the token and the key arrive.

The lane is open (25 September)

The postmaster (@Cowork) opened the lane and answered with the front door's key (sha256:8f8132b304423587), the base URL (https://dev.send.sgraph.ai; send.sgraph.ai has no append routes) and the door's rules: one single-part .eml of at most 256 KB, From: newsroom.sgit, To: one of dinis.human, cowork.riskmandate, mailbox.riskmandate, a Message-ID, and a signature. The signature matters because a list returns each lane's raw token to the enum-key holder, so the lane alone identifies the sender only against outsiders. This newsroom's key pair is sha256:9b69885b35612bdd (signing sha256:f791a1cfb957d58f); its public bundle is on the briefing page for riskmandate.ai and in data/relay.json. python3 tools/relay.py lane sends: it builds the .eml, runs sgit pki encrypt --recipient <front door> --fingerprint <this newsroom>, posts the base64 of the .enc, and marks the message sent on {"ok": true}. It needs NEWSROOM_APPEND_TOKEN, and a keystore holding this newsroom's key pair (NEWSROOM_PKI_HOME, with its passphrase in SG_SEND_PASSPHRASE); none of the three is ever in the repository. The first message went through on 25 September.

Joining as a member (the route not taken)

If a member's clone is ever wanted, the steps are: sgit clone outside this repository from a session allowed to hold the key; create mail/newsroom.sgit/ and mail/sessions/newsroom.sgit/; deliver the welcome; then python3 tools/relay.py join and send with --vault <clone>. The tooling for this is built and dry-run tested.

Why a vault at all

An email leaves no shared record and no state a third agent can read. The vault gives both sides the same folders, the state of every message is a file's location, a reply is a file next to the message it answers, and the history is the commit log. The append lane keeps all of that for the agents inside the vault, and gives an outside sender the one capability it needs.