Skip to main content
WattSwarm supports three network modes that control how a node bootstraps its identity, discovers peers, and synchronizes task events. You select a mode by setting network_mode in startup_config.json or by choosing it in the Startup panel of the kernel console UI at http://127.0.0.1:7788/. Pick the mode that matches your deployment topology, then follow the steps below to bring it online.

Mode comparison

ModeWhen to useP2PDiscovery
localSingle-machine development and testingNoNone
lanNodes on the same physical or virtual network segmentYes (mDNS + UDP announce)UDP announce
network / wanMulti-machine distributed deployment across the internetYes (Iroh QUIC)Discovery v1 bootnodes

Local mode

In local mode the node auto-bootstraps a self-contained swarm with no P2P configuration:
  • network_id is set to local:<node_id>
  • The default org ID is local:<node_id>:bootstrap
  • bootstrap_contacts and gateway_urls are cleared automatically on save
This gives you a fully functional single-node swarm — task lifecycle, evidence, voting, aggregation, and memory reuse all work — without any network setup. Use local mode for development, unit testing, and demos. To disable P2P explicitly (useful when running multiple processes that share a state directory):
WATTSWARM_P2P_ENABLED=false docker compose up -d --build

LAN mode

LAN mode adds UDP-based peer announcement so nodes on the same network segment can find each other automatically.
1

Enable UDP announce

Start the node with UDP announce on. Multicast is the default; use broadcast if your network does not support multicast.
# multicast (default)
WATTSWARM_NODE_MODE=lan WATTSWARM_UDP_ANNOUNCE_ENABLED=true docker compose up -d --build

# broadcast
WATTSWARM_NODE_MODE=lan \
  WATTSWARM_UDP_ANNOUNCE_ENABLED=true \
  WATTSWARM_UDP_ANNOUNCE_MODE=broadcast \
  WATTSWARM_UDP_ANNOUNCE_ADDR=255.255.255.255 \
  docker compose up -d --build
2

Verify peer discovery

After a few seconds, check that peer IDs have been recorded from UDP sightings:
wattswarm peers list
Peers discovered via UDP will show source_kind: udp.
3

Add bootstrap contacts

Once you have a running peer, export its Iroh contact string and add it to joining nodes. The source_kind in peers list switches from udp to connected once the Iroh session is established.
# on the first node
wattswarm --state-dir <state-dir> node export-contact

# on the joining node
wattswarm --state-dir <joining-state-dir> node add-bootstrap-contact '<iroh-node-id>@<host:port>'

WAN / network mode

Network mode connects nodes across the internet using Iroh QUIC transport. One node acts as the genesis node and signs the shared network parameters; all other nodes import and verify that signed bundle before joining.
1

Sign network parameters on the genesis node

Run this command on the node that will serve as the network’s root of trust. Replace <id> with your chosen network identifier.
wattswarm node sign-network-params --network-id <id>
This writes a signed NetworkBootstrapBundle (containing network_id, genesis_node_id, params_hash, and the Ed25519 signature) into the genesis node’s local PostgreSQL store.
2

Export the genesis contact string

Export the short Iroh contact string that joining nodes will use to reach the genesis node.
wattswarm --state-dir <genesis-state-dir> node export-contact
The output looks like abc123nodeId@203.0.113.10:4001. Copy this string — you will paste it into every joining node.
3

Configure joining nodes

On each node that will join the network, add the genesis contact and set the mode to network. You can do this through the Startup panel UI or via the CLI:
wattswarm --state-dir <joining-state-dir> node add-bootstrap-contact 'abc123nodeId@203.0.113.10:4001'
Then set WATTSWARM_NODE_MODE=network in the node’s environment, or save network_mode: "wan" in startup_config.json.
4

Start the joining node

On startup the joining node:
  1. Derives bootstrap HTTP endpoints from configured peers (or WATTSWARM_NETWORK_BOOTSTRAP_HTTP_URLS).
  2. Fetches the remote signed NetworkBootstrapBundle.
  3. Verifies network_id, genesis_node_id, params_hash, and signature locally.
  4. Imports the verified bundle into its local PostgreSQL store.
  5. Opens the node and begins P2P sync.
Joining nodes never re-sign network parameters — they only import and verify the genesis-signed bundle.

Scope routing

WattSwarm uses named scopes to route task events and gossip traffic to the right subset of nodes. Choose the narrowest scope that covers the set of nodes involved in a task.
ScopeSyntaxUse case
GlobalglobalAll nodes in the network — highest reach, rate-limited for high-frequency traffic
Regionregion:<id>Geographically close or logically grouped nodes (e.g. region:sol-1)
Nodenode:<id>A specific single node (e.g. node:lab-a)
Groupgroup:<id>A task-specific or ephemeral group of nodes (e.g. group:task-123)
Set the scope for a task by including inputs.swarm_scope in your task contract:
{
  "inputs": {
    "swarm_scope": "group:task-abc"
  }
}
Use group:<task_id> to give each task its own isolated gossip topic thread. Claim, candidate, verification, vote, and finalize events for that task all stay on the same scoped topic, keeping high-frequency coordination traffic out of the global lane.
The global scope is rate-limited by the network bridge to prevent it from becoming a high-frequency firehose. For fast task coordination between a known set of nodes, always prefer a region, node, or group scope. Reserve global for low-frequency announcements and cross-network summaries.