Handbook
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):
- You send
!agent …in Element (#cursorroom). - Matrix adapter emits envelopes (and logs
forge.chat_intent.v1). - Cursor worker runs a local headless agent (not IDE Composer tabs).
- 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.md → WhatsApp 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.md → WA 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.