Concepts: DIDs, passports & signed actions¶
Identity (did:key)¶
Each agent/operator is an Ed25519 keypair encoded as a did:key. Because the public
key is embedded in the identifier, a verifier resolves it offline — no registry,
no network. The trade-off is no rotation/revocation at the DID level; handle those at
the passport level (short expiresIn) or move to did:web for long-lived operators.
Passport (a Verifiable Credential)¶
A passport is a W3C VC signed by the operator about the agent:
{
"type": ["VerifiableCredential", "AgentPassport"],
"issuer": "did:key:<operator>",
"credentialSubject": {
"id": "did:key:<agent>",
"name": "support-bot",
"model": "claude-fable-5",
"scopes": ["email:send", "crm:read"],
"operator": "did:key:<operator>"
}
}
verifyPassport checks the operator's signature and returns this subject. Scopes are
free-form strings you define ("resource:action" works well). "*" grants all.
Signed actions¶
An action is an EdDSA JWT signed by the agent:
{ "iss": "did:key:<agent>", "act": { "type": "email:send", "target": "a@b.com" }, "iat": 1785600000 }
verifyAction proves the JWT was signed by the agent's key. Store these to build a
tamper-evident audit trail: even a compromised app server can't forge an action
without the agent's private key.
Trust chain¶
A verifier trusts an action if: (1) the action verifies to the agent DID, (2) the passport verifies to a trusted operator DID and names that same agent, and (3) the passport grants the scope the action needs.