Agent communication

Forge uses a two-layer communication stack: Matrix/Element for humans (phone and browser), and a machine bus (NATS JetStream) for agent-to-agent traffic. Chat requests work; Lenses will govern later; workers execute…

Updated

Architecture

Layer Role Technology
Human UX Phone/browser chat, ops rooms Matrix + Element
Channel gateway Chat ↔ intents and status forge-cursor-bridge matrix adapter
Agent bus Commands, events, peer traffic NATS JetStream on Granite
Cursor worker Headless agents on your laptop forge-cursor-bridge + Cursor SDK (composer-2.5)
Contracts Ingress and worker events forge.chat_intent.v1, forge.agent_event.v1

Lane (v1):

  1. You send !agent … in Element (#cursor room).
  2. Matrix adapter emits envelopes (and logs forge.chat_intent.v1).
  3. Cursor worker runs a local headless agent (not IDE Composer tabs).
  4. Status returns to the room via the adapter.

Future agents subscribe to the same NATS subjects; they do not use Matrix as their primary protocol.

Communication agent (!comm): deterministic KB answers for Forge Intelligence, Platform, and Blueprints handbooks. Deployed via forge-agents on Granite; see Communication agent.

Related: OpenClaw integration, Matrix channel notes.

Hostnames

Hostname Service
matrix.forgedc.net Synapse homeserver (sticky — do not rename)
element.forgedc.net Element Web UI
NATS 127.0.0.1:4222 on Granite only (SSH tunnel from laptop)

Registration is disabled. Accounts are created by an operator on Granite.

Repos

Repo Purpose
forge-agents Canonical channel agents monorepo — communication (!comm), cursor_bridge (!agent), orchestrator, packaging
forge-matrix Synapse, Element, Postgres, NATS compose + Granite deploy scripts
forge-cursor-bridge Deprecated — migrated to forge-agents/packages/cursor_bridge/

Governance and agent catalog: Forge Agents handbook. Orchestrator registry and Granite deploy: orchestrator, forge-agents repo.


1. Matrix + Element on Granite

From your workstation (Code/forge-matrix):

cd forge-matrix
cp .env.example .env
./scripts/generate-secrets.sh
./scripts/bootstrap-synapse.sh
./scripts/install-on-granite.sh

Cloudflare tunnel + DNS (uses CLOUDFLARE_API_TOKEN from forge-knowledge-assistant/.env.local when present):

./scripts/apply-cf-matrix-tunnel.sh
python3 scripts/ensure-matrix-dns.py

Tunnel target is the Precision SSH connector on Granite (CF_TUNNEL_ID in .env).

Create operator accounts

On Granite:

cd ~/forge-matrix
docker compose exec -T synapse register_new_matrix_user \
  -c /data/homeserver.yaml http://localhost:8008 \
  -u forgeadmin -p 'YOUR_PASSWORD' -a --exists-ok

docker compose exec -T synapse register_new_matrix_user \
  -c /data/homeserver.yaml http://localhost:8008 \
  -u cursorbot -p 'BOT_PASSWORD' --no-admin --exists-ok

Create rooms (from laptop, with admin password):

export MATRIX_HOMESERVER=https://matrix.forgedc.net
export MATRIX_ADMIN_USER=forgeadmin
export MATRIX_ADMIN_PASSWORD='YOUR_PASSWORD'
python3 scripts/setup-matrix-rooms.py

Rooms: #cursor, #ops, space #forge-agents. Keep #cursor and #ops unencrypted so the bot can read messages.

Sign in (web or mobile)

  • Element Web: https://element.forgedc.net
  • Homeserver: https://matrix.forgedc.net
  • Username: local part only (e.g. forgeadmin)

Mobile: choose Sign in / I already have an account — not Create account.
If you see Registration has been disabled, the app is on the sign-up path; go back and use Sign in.

Alternatives on phone: open Element Web in the browser, or pair with desktop via Sign in with QR code.


2. WhatsApp relay (Element ↔ WhatsApp ↔ Android Auto)

Optional self-hosted bridge for operating an Element room from WhatsApp (and Android Auto on the relay phone). This is separate from the Cursor/NATS agent bridge.

Piece Role
mautrix-whatsapp Matrix appservice + WhatsApp linked device
@warelay Relay Matrix user (QR login to WhatsApp)
@whatsappbot Bridge command bot

Deploy and verify on Granite — see forge-matrix/README.mdWhatsApp relay bridge:

cd forge-matrix
./scripts/install-on-granite.sh
ssh granite 'cd ~/forge-matrix && ./scripts/verify-whatsapp-bridge.sh'

Operator steps (QR login, !wa bridge, 14-day phone keepalive): ./scripts/whatsapp-relay-setup-guide.sh

Do not bridge #cursor or other agent rooms.

WA queue notify (forge-wa-notify)

Optional service: invite @wanotify to Matrix rooms; each message is summarized via Granite LLM and queued to operator WhatsApp +380935502637 through the existing @warelay portal room (not a second WhatsApp login).

Deploy on Granite — see forge-matrix/README.mdWA queue notify bot and forge-wa-notify/README.md.

Operator WhatsApp commands: wait, details, reply, next, skip, clean (30-minute timeout advances the queue).


3. Cursor bridge on your laptop

Prefer the forge-agents package (migrated from forge-cursor-bridge):

cd forge-agents/packages/cursor_bridge
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env

Edit .env:

Variable Example
MATRIX_HOMESERVER https://matrix.forgedc.net
MATRIX_USER @cursorbot:matrix.forgedc.net
MATRIX_PASSWORD bot password from step 1
MATRIX_ALLOWED_USERS @forgeadmin:matrix.forgedc.net
MATRIX_CURSOR_ROOM #cursor:matrix.forgedc.net
MATRIX_OPS_ROOM #ops:matrix.forgedc.net
CURSOR_API_KEY from Cursor Integrations
CWD_ALLOWLIST /home/YOU/Code/*

CURSOR_API_KEY is required for !agent new even though agents run locally — the SDK authenticates headless runs on your machine.

Run

forge-cursor-bridge matrix-adapter

Or install the user service:

./scripts/install-user-service.sh
systemctl --user enable --now forge-cursor-bridge.service

Commands in #cursor

!agent new /home/you/Code/forgesdlc | Summarize the generator layout
!agent list
!agent send <agent_id> Add a test for the parser
!agent cancel <agent_id>
!agent status <agent_id>
!agent help

4. NATS agent bus (multi-agent)

NATS runs inside the Granite compose stack. It is not on the public internet.

SSH tunnel from laptop:

# forge-matrix/scripts/nats-ssh-tunnel.sh
ssh -N -L 4222:127.0.0.1:4222 granite

In forge-cursor-bridge/.env:

TRANSPORT=nats
NATS_URL=nats://USER:PASS@127.0.0.1:4222

Run adapter and worker (or use matrix-adapter which embeds the worker). Test the bus:

forge-cursor-bridge echo-agent

5. Script reference

Script Repo Purpose
scripts/generate-secrets.sh forge-matrix Fill .env secrets
scripts/bootstrap-synapse.sh forge-matrix Synapse signing key + homeserver.yaml
scripts/install-on-granite.sh forge-matrix rsync + docker compose up on Granite
scripts/apply-cf-matrix-tunnel.sh forge-matrix Cloudflare ingress for matrix/element
scripts/ensure-matrix-dns.py forge-matrix CNAME records
scripts/setup-matrix-rooms.py forge-matrix #cursor, #ops, space
scripts/bootstrap-mautrix-whatsapp.sh forge-matrix WhatsApp bridge config + registration
scripts/verify-whatsapp-bridge.sh forge-matrix Bridge infra checks
scripts/whatsapp-relay-setup-guide.sh forge-matrix QR login + !wa bridge checklist
scripts/nats-ssh-tunnel.sh forge-matrix Local NATS forward
scripts/install-user-service.sh forge-agents (packages/cursor_bridge) systemd user unit

6. Troubleshooting

Symptom Fix
Registration has been disabled (mobile) Use Sign in, not Create account
Login rate limited (429) Wait a few minutes; Synapse rc_login is relaxed for private use
502 on matrix/element Check Cloudflare tunnel points at Granite Precision SSH connector and DNS CNAME matches
!agent new fails: no API key Set CURSOR_API_KEY in bridge .env
Bot silent in room Confirm #cursor is not E2EE; bot user invited
WhatsApp bridge as_token rejected Restart Synapse after registration; docker compose up -d --force-recreate mautrix-whatsapp
!wa bridge unknown Bridge image must be v0.2604+ (MAUTRIX_WHATSAPP_IMAGE)

Security boundaries

  • Matrix federation is closed; registration is off.
  • NATS is localhost on Granite or reached via SSH tunnel — not exposed publicly.
  • Bridge allowlists Matrix user IDs and working-directory paths.
  • Headless Cursor agents do not open IDE chat tabs; they use the same account auth as the SDK/CLI.