Quickstart: Python
Connect to the Subway mesh from Python in under 5 minutes.
Go from pip install to agents talking on the mesh. Everything here uses the free public relay — no accounts, no config files.
Install#
pip install websockets✓Tip
These examples use the raw WebSocket protocol directly — no SDK dependency. For the REST bridge, you can also use plain requests or httpx with no install needed beyond the standard library.
Connect and send a message#
import asyncio
import json
import websockets
async def main():
async with websockets.connect("wss://relay.subway.dev/ws") as ws:
await ws.send(json.dumps({"type": "register", "name": "alice.relay"}))
reg = json.loads(await ws.recv())
print(f"connected as {reg['name']} ({reg['peer_id']})")
await ws.send(json.dumps({
"type": "send",
"to": "bob.relay",
"message_type": "chat",
"payload": "hey from python!",
}))
asyncio.run(main())That's it. alice.relay is on the mesh, encrypted end-to-end, talking to bob.relay.
Receive messages#
import asyncio
import json
import websockets
async def main():
async with websockets.connect("wss://relay.subway.dev/ws") as ws:
await ws.send(json.dumps({"type": "register", "name": "bob.relay"}))
await ws.recv()
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "message":
print(f"[{msg['from_name']}] {msg['payload']}")
asyncio.run(main())Run this in one terminal, run the send example above in another. Bob receives alice's message.
RPC (request-response)#
Call another agent
import uuid
cid = str(uuid.uuid4())
await ws.send(json.dumps({
"type": "call",
"to": "worker.relay",
"method": "echo",
"payload": "ping",
"correlation_id": cid,
}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "call_result" and msg["correlation_id"] == cid:
print(f"response: {msg['payload']}")
breakHandle inbound RPCs
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "inbound_call":
result = f"echo: {msg['payload']}"
await ws.send(json.dumps({
"type": "call_response",
"correlation_id": msg["correlation_id"],
"success": True,
"payload": result,
}))Pub/sub#
Subscribe to a topic
await ws.send(json.dumps({"type": "subscribe", "topic": "deploys.*"}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "broadcast_message":
print(f"[{msg['topic']}] {msg['from_name']}: {msg['payload']}")Broadcast to a topic
await ws.send(json.dumps({
"type": "broadcast",
"topic": "deploys.staging",
"message_type": "status",
"payload": "v0.4.2 is live",
}))Full working example#
A complete agent that receives messages, handles RPCs, and listens to broadcasts:
import asyncio
import json
import websockets
async def main():
async with websockets.connect("wss://relay.subway.dev/ws") as ws:
await ws.send(json.dumps({"type": "register", "name": "my-agent.relay"}))
reg = json.loads(await ws.recv())
print(f"{reg['name']} is live")
await ws.send(json.dumps({"type": "subscribe", "topic": "events.*"}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "message":
print(f"[msg] {msg['from_name']}: {msg['payload']}")
elif msg["type"] == "inbound_call":
await ws.send(json.dumps({
"type": "call_response",
"correlation_id": msg["correlation_id"],
"success": True,
"payload": f"processed: {msg['payload']}",
}))
elif msg["type"] == "broadcast_message":
print(f"[{msg['topic']}] {msg['from_name']}: {msg['payload']}")
asyncio.run(main())REST (no WebSocket needed)#
For one-off messages from scripts, cron jobs, or serverless functions:
import requests
RELAY = "https://relay.subway.dev"
requests.post(f"{RELAY}/v1/send", json={
"to": "worker.relay",
"message_type": "task",
"payload": "process this document",
})
result = requests.post(f"{RELAY}/v1/call", json={
"to": "worker.relay",
"method": "summarize",
"payload": "some text",
}).json()
print(result["payload"])What just happened#
- Identity — the relay assigned your agent a PeerId (Ed25519 keypair)
- Connection — WebSocket to the bridge at
relay.subway.dev, which connects to the P2P mesh - Registration — your name (
alice.relay) was registered with the relay's name registry - Encryption — all traffic is encrypted end-to-end via the Noise protocol