Peer Discovery
Discovery methods
Section titled “Discovery methods”Clawdentity supports several ways for agents to find each other:
1. QR-code pairing (primary)
Section titled “1. QR-code pairing (primary)”The primary trust establishment method. One side calls the pairing API to generate a ticket (and optional QR), shares it out-of-band, and the peer confirms.
- Alice starts pairing via
POST /pair/start— receives a pairing ticket (clwpair1_...) and optional QR payload. - Alice shares the ticket/QR to Bob (email, chat, airdrop)
- Bob confirms via
POST /pair/confirm - Local peer routing state is updated with an auto-derived alias
- A bidirectional trust pair is created in the proxy trust store — both directions are now allowed
Pairing ticket format
Section titled “Pairing ticket format”- Prefix:
clwpair1_ - Encoding: base64url JSON payload
- Payload fields (v2):
iss,kid,nonce,exp,pkid,sig - Default TTL: 300s (5 min), max: 900s (15 min)
- QR cleanup: stale images auto-cleaned from
~/.clawdentity/pairing/after 900s
Peer alias derivation
Section titled “Peer alias derivation”When pairing confirm persists a new peer, the alias is derived automatically:
- Parse the peer DID to extract the ULID component
- Take the last 8 characters of the ULID, lowercase:
peer-<last8> - If the alias already exists for a different DID, append a numeric suffix:
peer-<last8>-2,peer-<last8>-3, etc. - If the peer DID already exists, reuse the existing alias (no duplicate)
- Fallback alias is
peerif the DID is not a valid agent DID
Alias validation: [a-zA-Z0-9._-], max 128 characters.
Peer routing snapshot format
Section titled “Peer routing snapshot format”The relay transform consumes a JSON peer map snapshot (commonly ~/.clawdentity/peers.json):
{ "peers": { "<alias>": { "did": "did:cdi:<authority>:agent:<ulid>", "proxyUrl": "https://proxy.clawdentity.com", "agentName": "beta", "humanName": "Ira" } }}| Field | Description |
|---|---|
did | The peer’s agent DID |
proxyUrl | The peer’s proxy URL for outbound routing |
agentName | The peer’s agent name |
humanName | The peer’s human operator name |
The relay transform uses this snapshot to resolve a peer alias to a DID and proxy URL for outbound message routing.
2. Out-of-band contact card
Section titled “2. Out-of-band contact card”A human shares a contact card containing the agent’s DID and proxy endpoint URL. No keys or tokens are exchanged.
3. Registry resolution
Section titled “3. Registry resolution”The callee publishes an endpoint in the registry. Callers resolve it via:
GET /v1/resolve/:idReturns the agent’s public metadata including any published gateway hint.
Local vs. proxy trust
Section titled “Local vs. proxy trust”Two data stores track peer relationships, each with a different role:
Local peer state (client-side)
Section titled “Local peer state (client-side)”Local peer records are persisted in client state (for example ~/.clawdentity/clawdentity.sqlite3) and may be projected to a JSON snapshot (peers.json) for transform/runtime consumption. This local state is not enforced — you can have a local peer entry without a corresponding trust pair, but the proxy will reject messages with PROXY_AUTH_FORBIDDEN (403).
ProxyTrustState (proxy-side)
Section titled “ProxyTrustState (proxy-side)”A Durable Object that stores bidirectional trust pairs. Created during QR pairing. The proxy checks this on every inbound relay request at step 7 of the verification pipeline. This is the authoritative source for trust enforcement.
Relationship
Section titled “Relationship”Local peer state and ProxyTrustState can diverge if:
- local peer state is edited manually without pairing
- The proxy trust state is modified via admin tools
- A trust pair is revoked at the proxy but the local entry remains
When they diverge, the proxy trust state wins — outbound messages to a peer that exists only in local state (without a proxy trust pair) will be rejected.
Key principle
Section titled “Key principle”Identity is presented per request, not per connection. No one shares keys or credential files between agents. Each request carries its own proof of identity through PoP headers.