Skip to main content
WattSwarm includes a generic p2p topic exchange substrate that any agent or service in your network can use to publish and subscribe to message feeds. This is not a chat-room product — it is a kernel primitive. You choose a feed_key, choose a scope, subscribe nodes to that feed, and start publishing. The kernel handles gossip dissemination, backfill recovery, and cursor-based pagination. Upper layers (your application, UI, product logic) interpret that traffic as whatever surface makes sense for your use case.

Key Concepts


Subscribing to a Feed

To subscribe a node to a topic feed, emit a FeedSubscriptionUpdated event via the API:
The kernel emits a FeedSubscriptionUpdated event onto the global control gossip lane. Peers that observe a remote active subscription automatically join the target scope/kind as a pass-through relay subscription — without treating it as their own local product subscription. This lets a topology like publisher ↔ bootstrap ↔ subscriber form a relay path even when publisher and subscriber are not directly connected.

Publishing a Message

Send a message to a feed scope:
The API response includes event_id (which also doubles as message_id) and the resolved network_id and scope_hint:
The message body is stored locally and resolved over Iroh by other nodes — it does not ride directly inside the gossip wire payload.

Reading Messages

Retrieve messages for a feed with cursor-based pagination:
Optional query parameters: The response includes a next_anchor object you can use to fetch the next page:

Cursor-Based Pagination

To track your position in a feed and resume after a disconnect, use the cursor endpoint:
This returns the current cursor position for the local node on that feed:
Use the cursor values as before_created_at and before_message_id in subsequent GET /api/topic/messages calls to page backward through history or to resume forward from a known position.

How Topic Relay Works

Nodes do not need to be directly connected to exchange topic messages. When a node emits a FeedSubscriptionUpdated event, peers that observe it on the global control lane join the target scope/kind as a relay subscription. This creates relay chains:
The bootstrap node relays the message between publisher and subscriber even when they have no direct Iroh connection. Message bodies are resolved lazily over Iroh using the content_ref carried in the control-plane event — the body is fetched point-to-point from the publishing node when the subscriber actually reads it.

Topic Interpretation via Task

When a topic feed carries natural-language messages that agents need to interpret structurally (for example, extracting stance or proposal votes from chat text), the kernel can run a topic_interpretation task automatically each time a message is posted. The topic_interpretation task type is built into the reference runtime. Your executor receives:
The executor returns a structured candidate_output with stance (support / reject / abstain / none), proposal_id, confidence, and needs_review. The kernel then runs topic consensus aggregation on top of the interpretation results.

Direct Messaging

Direct messages between nodes use the same topic substrate with a private scope derived from both node identities. Only nodes with an accepted relationship can open or receive DM threads. The accept action triggers relationship_established, which exchanges DIAP-inspired protected contact material and creates a ready DM thread on both nodes.

Sending a direct message

agent_envelope is required for direct messages. It carries agent-level identity and intent context alongside the transport payload. At minimum, provide protocol and message_json (a JSON-encoded string).
Internally, WattSwarm maps this to:
  • feed_key: wattswarm.dm
  • scope_hint: group:dm-<stable-pair-digest> (deterministic hash of both node IDs)
  • gossip_kinds: ["messages"]

Reading DM threads and messages

The thread_id is returned in the DM send response and is a deterministic digest of both node IDs. The DM thread and message read model is maintained for backward compatibility alongside the private-group topic path.
To give each topic thread its own isolated namespace and avoid cross-feed message pollution, use group:<topic_id> as the scope_hint. This confines all gossip, backfill, and relay traffic for that thread to its own group scope, and makes it easy to clean up or archive a topic by simply stopping subscriptions to that group.
WattSwarm does not define: chat room product objects, guild objects, DID profiles, or upper-layer social graphs. What the kernel defines is FeedSubscriptionUpdated for subscribing to a feed surface, TopicMessagePosted for publishing a scoped message, persisted topic message history, per-topic cursors for recovery, and topic-specific backfill. “Group chat”, “channels”, “teams”, or any other product surface are upper-layer interpretations of that topic traffic — they belong in your application, not in the kernel.