Your agent was reachable this morning. You deployed it, tested it end to end, and closed the laptop. This morning it's gone — not the code, not the model, the address. The laptop went to sleep and woke on a new DHCP lease. Or the container got rescheduled onto a different host. Or the office router rebooted and the port mapping vanished with it.
If you're searching for agent connectivity best practices, that's the scenario you're trying to fix: agents that silently go unreachable while nothing about their code changed. The failure modes behind it are a short, well-understood list, and each one has a practice that prevents it. This post is that list — six failure modes, six fixes, in the order you're likely to meet them.
Why agents go unreachable
A web service has a stable address: a DNS name, a public IP, maybe a load balancer in front. An agent has none of that by default. It runs on whatever machine it happens to occupy — a laptop behind home NAT, a container that gets rescheduled, a VM in a cloud region you don't control. The network gives it an address that is really a property of the machine, and the machine moves. Restarts, sleep/wake, cloud migrations, and network changes all break the address before they break the code.
Six failure modes cover most "my agent is unreachable" incidents:
- NAT and CGNAT — the agent sits behind a router that silently drops inbound connections.
- IP churn — the address is keyed to an IP, and the IP changes.
- Egress-only firewalls — the network allows outbound only; nothing can reach the agent.
- Symmetric NAT — hole punching fails on networks that assign per-destination ports.
- Restart rotation — every restart mints new credentials, so the agent's identity effectively changes.
- Discovery gaps — the address is fine, but nothing can find what the agent offers.
The practices below each prevent one of these. Do all six and your agents stay reachable across restarts, networks, and clouds — without you touching a router.
1. NAT and CGNAT: stop depending on inbound
The classic case is an agent on a home or office network. The router NATs outbound traffic and drops unsolicited inbound connections. Port forwarding can patch it — until the ISP runs carrier-grade NAT (CGNAT) and the "public" IP isn't even yours, or you simply don't want ports open on a machine running an agent.
The practice: outbound-only connectivity with NAT traversal. The agent initiates outbound and keeps the path alive; peers reach it through that path. STUN discovers the externally mapped address, and hole punching opens the route. No router config, no forwarded ports, no static IP from the ISP — the agent is reachable purely through connections it started itself.
2. IP churn: don't key the address to the IP
Laptops sleep and wake on new leases. Containers get rescheduled onto new hosts. Cloud providers reassign addresses at will. If your agent's address is an IP — or a DNS record you update by hand — its address dies every time the machine moves.
The practice: stable addressing. Give the agent a permanent virtual address that survives restarts, IP changes, and moves across clouds. The address is keyed to the agent's identity, not its location; the network resolves it to whatever IP the agent happens to hold right now.
3. Firewalls: work with egress-only networks
A large share of agents run inside networks where inbound traffic is simply not allowed — corporate offices, locked-down cloud VPCs. A VPN gets you in, but it's a heavy tool for the job, and it comes with an assumption you may not want: everyone on the network is trusted.
The practice: outbound-initiated tunnels with relay fallback. The agent connects outward into an overlay; peers reach it through that overlay connection. When direct paths are blocked, traffic relays through a fallback. The agent stays reachable with zero inbound rules on the firewall.
4. Symmetric NAT: assume hole punching will fail sometimes
Hole punching is reliable on most home routers and flaky on enterprise and mobile networks. Symmetric NAT assigns a different port per destination, which breaks the classic punch. If your connectivity plan is "we do hole punching," a slice of your fleet will silently be unreachable — and it will be the hardest slice to debug.
The practice: relay fallback. Design for the failure. When direct punching fails, fall back to relaying through a beacon. The difference between "usually reachable" and "always reachable" is exactly this fallback path.
5. Restart rotation: make identity outlive the process
The quiet one. An agent that mints a new keypair on every start — or gets handed a fresh ephemeral tunnel URL — is a new agent each time it runs. Peers that trusted it yesterday can't find it today, and it can't find them. From the network's perspective, the agent died and a stranger appeared.
The practice: persistent identity. Store the keypair; derive the address from the identity, not from the process run. Restart, reschedule, migrate — the address stays the same, and so does trust.
6. Discovery: find agents by name, not by address book
An address is only useful if the right peer knows it. Hardcoded address lists stop scaling the moment a fleet grows past a handful of machines, and they rot the moment anything moves.
The practice: a rendezvous registry and nameserver. Agents register once and are found by name or tag; the network resolves the name to the live address. New agents appear without anyone editing a config file.
Agent connectivity best practices for production
The whole checklist, compressed:
- Initiate outbound; never depend on inbound.
- Key the address to identity, not IP.
- Assume egress-only networks.
- Plan a relay fallback for when punching fails.
- Persist identity across restarts.
- Make discovery a registry lookup, not a config file.
One box that does all six is an agent-native overlay network. Pilot Protocol is an open-source one — implemented in Go with zero external dependencies, AGPL-3.0 — that gives every agent a permanent virtual address, encrypted UDP tunnels (X25519 key exchange, AES-GCM), STUN-based hole punching with a relay fallback, and a rendezvous registry for discovery. The trust model is the part worth calling out: membership and trust are decoupled. Joining the network doesn't make you trusted; every peer relationship is an explicit mutual handshake.
For fairness: the alternatives do pieces of this well. Tailscale, ZeroTier, and Nebula are mature mesh VPNs with solid NAT traversal, and if your fleet is mostly servers you control, they're a reasonable choice. The difference with an agent-native overlay is that the primitives — stable identity, mutual trust, name-based discovery — are designed for machines that come and go, restart, and change networks.
The first step is one command:
curl -fsSL https://pilotprotocol.network/install.sh | sh
Then the commands you'll actually live in:
pilotctl handshake <peer> "reason" # explicit mutual trust
pilotctl send-message <peer> 'hello' # reachable across NAT, firewalls, clouds
More than 243k agents and users already run on the network. If your agents keep going unreachable, the fix isn't a better restart script — it's an address that doesn't die with the machine.
Top comments (0)