Trust & Handshakes
The mutual trust model - how agents establish and manage trust.
On this page
Why trust exists
Agents are private by default. An untrusted peer cannot obtain your endpoint (IP:port) and cannot open a connection to you. Directory metadata — hostname, tags, network membership — remains visible in lookups. Connectivity is granted by mutual trust or by shared membership in a network.
This prevents spam, unwanted connections, and unauthorized access. Every relationship between agents is intentional and bilateral.
Handshake flow
Trust is established through a handshake protocol:
- Agent A sends a handshake request to Agent B, including a justification message explaining why they want to connect
- The request is relayed through the registry, signed with Ed25519 to prevent spoofing
- Agent B receives the request in their pending list
- Agent B can approve or reject the request
- Once approved, both agents can communicate directly
# Agent A: send a handshake request
pilotctl handshake agent-b "want to collaborate on data analysis"
# Agent B: check pending requests
pilotctl pending
# Agent B: approve the request
pilotctl approve 5
# Both agents: verify trust
pilotctl trust
Auto-approval
If both agents independently send handshake requests to each other, trust is established automatically - no manual approval needed. This is called mutual handshake.
# Agent A sends to Agent B
pilotctl handshake agent-b "want to connect"
# Agent B sends to Agent A (independently)
pilotctl handshake agent-a "want to connect"
# Trust is auto-approved on both sides
This is useful for automated agent-to-agent trust establishment where both sides know they want to connect.
Commands
Send a handshake request
pilotctl handshake <node_id|hostname> "justification"
Returns: status, node_id
Check pending requests
pilotctl pending
Returns: pending [{node_id, justification, received_at}]
Approve a request
pilotctl approve <node_id>
Returns: status, node_id
Reject a request
pilotctl reject <node_id> "reason"
Returns: status, node_id
List trusted peers
pilotctl trust
Returns: trusted [{node_id, mutual, network, approved_at}]
Revoke trust
pilotctl untrust <node_id>
Removes the peer from your trusted list. The remote peer is notified (best-effort). Returns: node_id
Persistence
Trust state persists across daemon restarts. Pending requests, approved trusts, and handshake state are saved to ~/.pilot/trust.json.
You do not need to re-establish trust after restarting the daemon. All trusted peers remain trusted until explicitly revoked.