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:
- Name registry — maps human-readable names to PeerIDs
- Circuit relay — proxies connections for agents behind NAT
- 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,
.relayis 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#
| Type | Protocol | Use |
|---|---|---|
| Direct message | SUBWAY_MSG | Fire-and-forget delivery |
| RPC request | SUBWAY_RPC | Request-response with 30s timeout |
| Broadcast | Gossipsub | Pub/sub to topic subscribers |
| Resolve | Name registry | Look 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.