Google's Agent-to-Agent (A2A) protocol standardizes what agents say to each other — Agent Cards, task lifecycle, JSON-RPC 2.0. But it assumes HTTP transport: public URLs, a /.well-known/agent.json endpoint, TLS certs. That's a fine assumption for a cloud service. It's a bad one for an agent behind NAT, running in a container, or living on someone's laptop — which describes most real agent deployments.
A2A defines the language of agent collaboration. It doesn't define how two agents that can't both hold a public IP actually reach each other. That's a networking problem, and Pilot Protocol is a networking layer: permanent virtual addresses, encrypted UDP tunnels, NAT traversal, and a trust model. A2A defines the language; Pilot provides the phone system. You need both to have a conversation.
Where the two layers meet
| Concern | A2A | Pilot |
|---|---|---|
| Capability advertisement | Agent Cards (JSON) | Registry (capability flags + metadata) |
| Task lifecycle | send/get/cancel task (JSON-RPC) | Messaging ports (send/recv) |
| Wire format | JSON-RPC 2.0 | Binary header + payload |
| Transport | HTTP/HTTPS | UDP overlay |
| Discovery | Well-known URL or directory | Registry resolve + trust handshake |
| Security | TLS + auth headers | X25519 + AES-GCM, encrypted by default |
| NAT traversal | Not addressed | STUN, hole-punching, relay fallback |
| Trust model | OAuth / API keys | Private-by-default, trust-gated resolve |
A2A tells you the shape of the conversation. Pilot tells you how the bytes actually get from one agent to the other when neither one has a stable public address.
The Agent Card's weak point
A standard minimal A2A Agent Card looks like this:
{
"name": "ResearchAgent",
"description": "Summarizes academic papers on any topic",
"url": "https://research-agent.example.com",
"version": "1.0.0",
"capabilities": { "streaming": true, "pushNotifications": false },
"skills": [{
"id": "summarize-papers",
"name": "Paper Summarization",
"tags": ["research", "nlp", "summarization"]
}],
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain", "text/markdown"]
}
The url field is where the assumption bites: it has to be a publicly reachable HTTPS endpoint. Every agent that isn't running behind a reverse proxy with a domain name and a cert either can't be reached, or has to be stood up with infrastructure that has nothing to do with what the agent actually does.
Swap that url for a Pilot virtual address — a permanent identifier like 1:0000.0042.00A1 — and the agent is reachable over Pilot's encrypted overlay instead. No public IP, no DNS record, no certificate to renew.
Serving Agent Cards over a Pilot tunnel (Go)
Using github.com/pilot-protocol/pilotprotocol/pkg/driver:
drv, err := driver.Connect("/tmp/pilot.sock")
info, _ := drv.Info()
pilotAddr := info.Address // e.g., "1:0000.0042.00A1"
card := AgentCard{
URL: fmt.Sprintf("pilot://%s:80", pilotAddr),
// ... other fields
}
http.HandleFunc("/.well-known/agent.json", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(card)
})
http.HandleFunc("/a2a", func(w http.ResponseWriter, r *http.Request) {
// handles JSON-RPC methods: "tasks/send", "tasks/get"
})
drv.ListenAndServeHTTP(80, http.DefaultServeMux)
The card fetch, the task submission, and the result delivery all travel over Pilot's encrypted UDP tunnel. Key exchange (X25519) and encryption (AES-GCM) are negotiated automatically when the tunnel is established — the application code above never touches TLS.
Trust-gated cards instead of public ones
Standard A2A treats the Agent Card as public: anyone with the URL can fetch it. Pilot's trust model changes that by default, in three layers:
- Address resolution is trust-gated — an untrusted peer can't resolve the agent's address, so it can't even confirm the agent exists.
- Connection requires mutual trust — an explicit handshake (mutual approve) has to complete before a tunnel opens.
- The card itself is served only over an already-trusted connection — its contents are revealed post-authentication, not before.
That gives you a privacy gradient A2A alone doesn't offer:
- Public agents — serve the card to anyone who resolves the address.
- Private agents — require a trust handshake before the card is even visible.
- Semi-private agents — a redacted card (name/description only) for untrusted peers, the full card (skills, examples) for trusted ones.
A medical-research agent, a financial-analysis agent, or anything sitting on proprietary data can be fully A2A-compliant while staying invisible to everyone it hasn't explicitly trusted.
A2A over the internet vs. A2A over Pilot
| Dimension | A2A over the internet | A2A over Pilot |
|---|---|---|
| Reachability | Requires a public IP or reverse proxy | Works behind any NAT |
| Encryption | TLS certs — issuance and renewal | Automatic X25519 + AES-GCM, no certs to manage |
| Discovery | DNS + well-known URL | Registry resolve, no DNS involved |
| Privacy | Card visible to anyone with the URL | Visible only to peers you've explicitly trusted |
| Identity | A domain name you purchase and maintain | A permanent virtual address, assigned once |
None of this replaces A2A — the protocol still defines what a task request looks like, how capabilities are described, how results come back. What changes is everything underneath: no public endpoint to expose, no cert lifecycle to manage, and a trust boundary that exists by default instead of being bolted on with API keys.
Try it
curl -fsSL https://pilotprotocol.network/install.sh | sh
Full walkthrough, the driver API, and the registry docs: pilotprotocol.network/docs. Source is open, AGPL-3.0: github.com/pilot-protocol.
Top comments (0)