Build a Multi-Agent Network in 5 Minutes
This tutorial takes you from zero to a working multi-agent network. Two agents, on different machines (or the same machine), communicating over encrypted tunnels with a mutual trust relationship. The whole thing takes about 5 minutes.
By the end, you will have two agents that can send messages, transfer files, ping each other, and publish/subscribe to event streams -- all over Pilot Protocol's encrypted UDP overlay.
Prerequisites
You need Go 1.21 or later installed. That is the only dependency. Pilot Protocol is a single binary with zero external libraries.
You will also need access to a rendezvous server. The public rendezvous server at pilotprotocol.network:9000 is available for testing. For production, you can run your own.
Step 1: Install pilotctl
Install the CLI tool with a single command:
$ go install github.com/TeoSlayer/pilotprotocol/cmd/pilotctl@latest
This installs pilotctl to your $GOPATH/bin. Make sure that directory is in your $PATH.
Verify the installation:
$ pilotctl version
pilotctl v0.5.0
Alternative: You can also clone the repository and build from source with go build ./cmd/pilotctl. See the Getting Started guide for details.
Step 2: Start Two Agents
Each agent needs its own identity. The init command generates a cryptographic identity (Ed25519 key pair) and stores it locally.
Agent Alice (Terminal 1)
# Initialize identity
$ pilotctl init
Identity created: ~/.pilot/identity.json
# Start the daemon and register as "alice"
$ pilotctl daemon start --hostname alice --public
Daemon started
Registered as alice (0:0000.0000.0003)
STUN discovered endpoint: 203.0.113.42:4000
Tunnel listening on :4000
Agent Bob (Terminal 2)
# On a different machine (or different directory)
$ pilotctl init
Identity created: ~/.pilot/identity.json
# Start the daemon and register as "bob"
$ pilotctl daemon start --hostname bob --public
Daemon started
Registered as bob (0:0000.0000.0004)
STUN discovered endpoint: 198.51.100.17:4000
Tunnel listening on :4000
Both agents are now running. The --public flag makes them discoverable by hostname. Without it, agents are private and can only be found by trusted peers.
Same machine? If you are running both agents on one machine for testing, use different directories for identity storage: PILOT_HOME=~/.pilot-alice pilotctl init and PILOT_HOME=~/.pilot-bob pilotctl init. Each daemon also needs a different tunnel port: --port 4000 and --port 4001.
Step 3: Discover and Establish Trust
Alice can find Bob by hostname because he registered as public:
# From Alice's terminal
$ pilotctl find bob
bob 0:0000.0000.0004 public 198.51.100.17:4000
Now Alice initiates a trust handshake. The justification message tells Bob why Alice wants to connect:
# Alice requests trust
$ pilotctl handshake bob "Collaborating on the Q1 data analysis project"
Handshake request sent to bob (0:0000.0000.0004)
Waiting for approval...
On Bob's side, the handshake request appears. Bob reviews it and approves:
# Bob sees the pending request
$ pilotctl pending
PENDING HANDSHAKES:
0:0000.0000.0003 (alice) — "Collaborating on the Q1 data analysis project"
# Bob approves
$ pilotctl approve 0:0000.0000.0003
Trust established with alice (0:0000.0000.0003)
Done. Alice and Bob now have a mutual trust relationship, signed with Ed25519 keys. An encrypted tunnel is established automatically.
Step 4: Communicate
With trust established, Alice and Bob can use the full set of communication primitives.
Ping
Test connectivity and measure latency:
$ pilotctl ping bob
PING bob (0:0000.0000.0004) via echo port 7
Reply from 0:0000.0000.0004: seq=1 time=23.4ms
Reply from 0:0000.0000.0004: seq=2 time=21.8ms
Reply from 0:0000.0000.0004: seq=3 time=22.1ms
Send a Message
Send structured text data through the Data Exchange service on port 1001:
# Alice sends a message to Bob
$ pilotctl send bob "Analysis complete. 47 anomalies detected in dataset-7."
Message sent to bob (0:0000.0000.0004)
# Bob receives it
$ pilotctl recv
From: alice (0:0000.0000.0003)
"Analysis complete. 47 anomalies detected in dataset-7."
Transfer a File
Send files directly between agents -- no S3, no cloud storage, no intermediary:
# Alice sends a file to Bob
$ pilotctl send-file bob ./report.pdf
Sending report.pdf (2.4 MB) to bob...
Transfer complete: 2.4 MB in 1.2s (2.0 MB/s)
# Bob receives files into the current directory
$ ls report.pdf
report.pdf
Publish/Subscribe Events
Set up real-time event streams using the built-in pub/sub on port 1002:
# Bob subscribes to events from Alice on topic "status"
$ pilotctl subscribe alice "status"
Subscribed to alice/status
Listening...
# Alice publishes events
$ pilotctl publish "status" "processing batch 1/10"
$ pilotctl publish "status" "processing batch 2/10"
# Bob sees them in real time
[alice/status] processing batch 1/10
[alice/status] processing batch 2/10
What Just Happened
Behind those simple CLI commands, a surprising amount happened:
- Identity generation --
pilotctl initgenerated an Ed25519 key pair and stored it in~/.pilot/identity.json. This key pair is the agent's permanent cryptographic identity. - STUN discovery -- when the daemon started, it sent a UDP packet to the beacon server and learned its own public IP:port mapping. This is how other agents can reach it through NAT.
- Registration -- the daemon connected to the rendezvous server over TCP and registered its hostname, public key, and STUN-discovered endpoint.
- Handshake -- Alice's handshake request was signed with her Ed25519 private key and relayed through the rendezvous server to Bob. Bob verified the signature, approved, and signed his response. Both sides now store the peer's public key.
- Tunnel establishment -- with trust established, Alice's daemon resolved Bob's endpoint from the rendezvous server, attempted direct UDP connection (using hole-punching if needed), and performed X25519 key exchange to set up AES-256-GCM encryption.
- Communication -- every message, file, and ping traveled over the encrypted tunnel as Pilot Protocol packets with the 34-byte header, CRC32 checksums, sequence numbers, and acknowledgments.
All of this happened without configuring firewalls, opening ports, setting up TLS certificates, or deploying cloud infrastructure. The agents found each other, established trust, traversed NAT, and communicated -- all through the protocol.
Next Steps
Now that you have a working network, explore further:
- How Pilot Protocol Works -- understand the full architecture: packet format, NAT traversal tiers, encryption, and trust model
- The Trust Model -- learn why agents are invisible by default and how the handshake system works in depth
- Why Agents Need a Network Stack -- the motivation behind Pilot Protocol and why HTTP is not enough for agent communication
- CLI Reference -- complete documentation for every
pilotctlcommand - Built-in Services -- port-based services including Echo, Data Exchange, Event Stream, and Task Submit
- Integration Guide -- embed Pilot Protocol in your Go applications
Explore the Full Documentation
CLI reference, Go API, configuration, deployment guides, and more.
Read the Docs
Pilot Protocol