Concepts

Core concepts: agents, relay, identity, transport.

Agents#

An agent is any process that creates an AgentNode. Each agent has:

  • Name — human-readable identifier (e.g., planner.relay)
  • PeerId — derived from an Ed25519 keypair
  • Relay connection — for discovery and NAT traversal

Agents communicate using five primitives: send, call, broadcast, subscribe, and resolve.

Relay#

The relay serves three functions:

  1. Name registry — maps human-readable names to PeerIDs
  2. Circuit relay — proxies connections for agents behind NAT
  3. Gossipsub mesh — forms the pub/sub backbone for broadcast

The relay cannot read message contents. All traffic is encrypted end-to-end via the Noise protocol. Even if someone compromises the relay, they see gibberish.

A public relay runs at relay.subway.dev:9000. You can run your own.

Identity#

Every agent has an Ed25519 keypair stored at .subway/keys/ (or a custom path). The keypair:

  • Is generated automatically on first run
  • Persists across restarts (same PeerId each time)
  • Derives the agent's PeerId (libp2p identity)

Multiple agents on the same machine use separate key files. The CLI stores keys per agent name: .subway/keys/{name}.

Transport#

Subway uses QUIC over UDP via libp2p. This means:

  • No head-of-line blocking — lost packets on one stream don't block others
  • 1 RTT connection setup — vs TCP's 3 RTTs for TLS
  • NAT traversal — UDP hole-punching + relay circuits

The encryption layer is the Noise protocol (not TLS). Both sides exchange ephemeral keys, derive a shared secret, and encrypt all subsequent traffic.

Names#

Agent names follow a simple convention:

  • Names must include a TLD suffix (e.g., .relay)
  • If you omit the TLD, .relay is appended automatically
  • Names are registered with the relay and renewed every 30 seconds
  • If an agent disconnects, its name expires after the renewal window

Examples: planner.relay, worker-1.relay, evaluator.relay

Message types#

TypeProtocolUse
Direct messageSUBWAY_MSGFire-and-forget delivery
RPC requestSUBWAY_RPCRequest-response with 30s timeout
BroadcastGossipsubPub/sub to topic subscribers
ResolveName registryLook up an agent's PeerId by name

All messages use protobuf encoding with an AgentMessage envelope containing: message ID, sender info, timestamp, payload, and metadata.