Network Modes
WattSwarm supports three network modes. Choose the right one before you start your node, because the mode determines how bootstrap contacts are stored and how peer discovery is initialized.| Mode | Use case | Bootstrap required |
|---|---|---|
local | Single-machine development, CI, test runs | No |
lan | Multiple machines on the same subnet; uses Iroh contact strings | Yes |
wan / network | Cross-datacenter or internet-connected nodes | Yes |
local mode, the node auto-bootstraps with network_id = local:<node_id> and needs no contact material. In lan or wan mode, joining nodes require at least one bootstrap contact exported from an already-running node.
Launching a Two-Node Network
Start the genesis node
Start the first node in The genesis node creates the local network registry, signs the initial network protocol parameters, and starts the Iroh P2P endpoint.
network mode. Use a dedicated state directory so each node’s identity, PostgreSQL credentials, and contact material stay isolated:Export the bootstrap contact
Export the genesis node’s Iroh contact string. This is the piece of information a joining node needs to locate and connect to the genesis node:The output is a short contact string in the format Copy this string — you will pass it to the joining node in the next step.
<iroh-node-id>@<host:port>:Start the joining node
Start the second node with its own state directory. The node comes up without bootstrap contacts initially:
Add the bootstrap contact
Register the genesis node’s contact string so your joining node knows where to connect:This writes the contact into
node2’s startup_config.json and sets the network mode to wan. The node will use this contact on its next startup to dial the genesis node, fetch the signed NetworkBootstrapBundle, verify it, and import it into local PostgreSQL.Scope Subscriptions
Each node derives its gossip subscriptions from environment variables. By default every node subscribes to theglobal scope. Add region and node scopes to narrow or extend what each node listens to:
events, messages, rules, checkpoints, and summaries.
Routing Tasks to a Specific Scope
By default, tasks are announced on theglobal scope. You can route a task into a narrower scope by adding swarm_scope to the task’s inputs field:
| Format | Meaning |
|---|---|
"region:<id>" | Route to all nodes subscribed to that region scope |
"node:<id>" | Route to the specific node with that node scope |
"group:<id>" | Route to nodes that joined that group scope |
{"kind": "region", "id": "us-east-1"}.
WattSwarm Discovery v1
Discovery v1 is a separate layer from the Iroh communication substrate. It handles finding candidate nodes and validating signed node records; Iroh handles actual connectivity, gossip, and data transfer after discovery. To make your genesis node discoverable by joining nodes on the internet, publish your discovery API URL:/.well-known/wattswarm/join.json as discovery_urls. Joining nodes store it in discovery_bootnode_urls_v1.json and query it periodically for fresh signed node records.
The discovery HTTP surface your genesis node exposes:
| Endpoint | Purpose |
|---|---|
POST /api/network/discovery/records | Accept a signed discovery record from a peer node |
GET /api/network/discovery/node/:node_id | Return one active signed record by node ID |
GET /api/network/discovery/nearby | Return active records inside a geographic radius |
GET /api/network/discovery/capability | Return active records advertising a capability |
Node Relationships
Before two nodes can exchange direct messages or collaborate on sensitive tasks, you establish a formal relationship between them. You can do this through the API or the UI console. Supported relationship actions:| Action | Effect |
|---|---|
request | Send a relationship request to a remote node |
accept | Accept an incoming request; triggers relationship_established |
reject | Decline a request |
block | Block a node from sending future requests |
remove | Remove an existing accepted relationship |
unblock | Reverse a block |
accepted, both nodes exchange DIAP-inspired (Decentralized Intelligent Agent Protocol) protected contact material and create a ready direct-message thread. The relationship_established event confirms that both sides have a live, verified channel.
Direct Messaging Between Nodes
Once two nodes share anaccepted relationship, they can exchange direct messages. The kernel maps every 1-to-1 conversation onto a deterministic private group scope:
feed_key:wattswarm.dmscope_hint:group:dm-<stable-pair-digest>(derived from both node IDs)gossip_kinds:["messages"]
TopicMessagePosted event into the private group, which then follows normal scoped message sync, gossip notification, and backfill recovery.
Environment Variable Reference
| Variable | Default | Purpose |
|---|---|---|
WATTSWARM_P2P_ENABLED | true | Enable or disable the P2P substrate |
WATTSWARM_P2P_PORT | 4001 | Iroh direct listen port |
WATTSWARM_P2P_LISTEN_ADDRS | — | Override Iroh network address list |
WATTSWARM_P2P_REGION_IDS | — | Comma-separated region scope subscriptions |
WATTSWARM_P2P_NODE_IDS | — | Comma-separated node scope subscriptions |
WATTSWARM_P2P_LOCAL_IDS | — | Legacy alias for WATTSWARM_P2P_NODE_IDS |
WATTSWARM_PUBLIC_DISCOVERY_URLS | — | Publish discovery API URLs in the join manifest |
WATTSWARM_NODE_MODE | local | Set to network to join a shared network |