Home / Docs / Operations / The comms channel: from the reader's column to the build agent

Rendered from docs/ops/comms.md, which is the source of truth and the markdown twin of this page. Rendered at site v0.1.13.

The comms channel: from the reader's column to the build agent

secrets.sgit.ai · operations · written at v0.1.7 (2026-10-06) · CC BY 4.0

The site is read by a person and built by an agent that only exists during a session. This page is how the one talks to the other without memos: a column on every page that keeps a log of what the reader marks, and a one-way encrypted lane into a vault only the agent can open.

The reader's column

Every page has a tab on its right edge, Reader. It opens a drawer with three views:

The column is three web components under components/ (reader-panel, reader-log, reader-chat) on the site's base sg-base, three files each, no framework, no colour of their own: they follow the theme. Where the page's Content-Security-Policy does not allow a connection to openrouter.ai or to the vault endpoint, the Chat and Send parts say so and point at the page that does (docs/design/brief-corrections.md, C19).

The lane into the agent's vault

The agent has a comms vault on SG/Send (https://dev.send.sgraph.ai) and a key pair (RSA-OAEP 4096 for encryption, ECDSA P-256 for signing). The public bundle, the vault id and the lanes are published in /.well-known/sgit-agents.json, the Agent Contact v0.1 shape every sgit.ai site uses. A lane is a write-only address on the vault, gated by an append token: a sender who holds the token can write, and cannot list, fetch or read. The token is not published. The lead makes it once (configure_lane.py --new prints it), keeps it in SGIT_COMMS_LANE_TOKENS, and pastes the readers one into the column's Append token field on the devices that should write (for this tab, or kept on the device when ticked); so, for now, the comments that reach the agent are the lead's own, and opening the lane to others is a decision, not a default. The agents token goes to other agents by hand. The site's column writes reader-message/v1, the sgit PKI envelope made with WebCrypto (the same bytes sgit pki encrypt would make), to the readers lane. Other agents write signed agent-message/v1 mail to the agents lane.

The agent reads the lanes at the start of a session with tools/comms/drain.py: list, fetch, decrypt with its private key, keep ciphertext and plaintext under the vault's inbox/, print a digest it acts on, then mark-processed. What cannot be opened goes to inbox/quarantine/ with the reason.

What only the project lead can do, once

The session that built this could create the vault and the key pair, but its permission policy stopped it short of two things: registering the lanes on the vault (an account-level change on SG/Send) and pushing the private keys into the vault. So the vault key, the read key and the key pair are where that session left them, and the lead finishes the channel:

  1. Take the vault key from the build session's scratchpad (vaults/create.log, the line Vault key) and the key pair from ~/.sg-send/keys/ of that session, with the passphrase in vaults/pki-passphrase.txt. Store the vault key as SGIT_COMMS_VAULT_KEY and the passphrase as SGIT_COMMS_PKI_PASSPHRASE in the Claude Code environment this repository runs in, so every later session can open the vault. Put the key folder in the vault (agent/keys/) and push it.
  2. Publish the public half: python3 tools/comms/publish_contact.py --fingerprint sha256:6d9fe81fd718ab0b fills the contact file with the bundle, the vault id and the lane names (no token); commit it.
  3. Register the lanes: python3 tools/comms/configure_lane.py --new (needs SGIT_COMMS_VAULT_KEY and SG_SEND_ACCESS_TOKEN) makes the two append tokens, prints them once, and registers their hashes on the vault. Store the printed line as SGIT_COMMS_LANE_TOKENS in the environment (the drainer and send_test.py read it there). On success it sets the contact file's status to open; commit it. Then open the column on /reader/, press Append token, paste the readers token, tick keep on this device if you want it to stay, and Send is on for that device.
  4. Prove the round trip: python3 tools/comms/send_test.py, then python3 tools/comms/drain.py --vault-dir <the vault clone>.

Until step 3 the column says the lane is pending and offers Copy for Claude, which works today. Send runs only on /reader/ (the one page whose policy allows the connection); on every other page the button becomes a link there, and the log is the same one.

The tools

FileDoes
tools/comms/comms_contact.pyreads and writes the contact file
tools/comms/comms_lane.pythe append-lane calls: write (no key), list, fetch, mark-processed (enum key), configure (write key and the SG/Send token)
tools/comms/comms_envelope.pythe sgit PKI envelope: seal to a public key, open with the agent's private key
tools/comms/publish_contact.pyfills the contact file from sgit pki export and the vault key
tools/comms/configure_lane.pyregisters the lanes on the vault
tools/comms/send_test.pywrites one test message to the readers lane
tools/comms/drain.pyreads the lanes into the vault's inbox/ and prints the digest

They run on a person's or an agent's machine, never in CI, and use the sgit_ai package for the key derivation and the envelope; nothing in them is a secret.