The Problem: AI Agent Impersonation
As AI agents become more autonomous and interact with external services, a critical question arises: how do you know which agent you're talking to?
Without cryptographic identity, any agent can claim to be any other agent. A malicious actor could deploy an agent that impersonates a trusted service, exfiltrating data or performing unauthorized actions.
AgentPin solves this with domain-anchored cryptographic credentials — ES256 JWTs tied to discoverable public keys, with capability scoping, delegation chains, and TOFU key pinning.
Step 1: Install the CLI
Install the AgentPin CLI tools via Cargo.
cargo install agentpin
Step 2: Generate Keys
Generate an ECDSA P-256 keypair anchored to your domain.
agentpin keygen \
--domain example.com \
--kid my-key-01 \
--output-dir ./keys
This creates PEM and JWK files in the output directory:
ls ./keys/
# my-key-01.private.pem
# my-key-01.public.pem
# my-key-01.private.jwk
# my-key-01.public.jwk
Step 3: Create Discovery Document
Create a discovery document that declares your agent's identity and capabilities. This will be served at .well-known/agent-identity.json.
{
"agentpin_version": "0.1",
"entity": "example.com",
"entity_type": "maker",
"public_keys": [
{
"kid": "my-key-01",
"kty": "EC",
"crv": "P-256",
"x": "<base64url-encoded-x>",
"y": "<base64url-encoded-y>",
"use": "sig"
}
],
"agents": [
{
"agent_id": "urn:agentpin:example.com:my-agent",
"name": "My Agent",
"capabilities": ["read:data", "write:reports"],
"status": "active"
}
],
"max_delegation_depth": 2,
"updated_at": "2026-02-08T00:00:00Z"
}
Save this as discovery.json. Use the JWK x and y values from your generated public key.
Step 4: Issue a Credential
Issue a signed JWT credential for your agent.
agentpin issue \
--private-key ./keys/my-key-01.private.pem \
--kid my-key-01 \
--issuer example.com \
--agent-id urn:agentpin:example.com:my-agent \
--capabilities read:data,write:reports \
--ttl 3600
This outputs a compact ES256 JWT:
eyJ0eXAiOiJhZ2VudHBpbi1jcmVkZW50aWFsK2p3dCIsImFsZyI6IkVTMjU2Iiwia2lkIjoibXkta2V5LTAxIn0.eyJpc3MiOiJleGFtcGxlLmNvbSIsInN1YiI6InVybjphZ2VudHBpbjpleGFtcGxlLmNvbTpteS1hZ2VudCIsImlhdCI6MTczODk3MjgwMCwiZXhwIjoxNzM4OTc2NDAwLCJqdGkiOiI1NTBiOTYzMy1lMjRiLTRlMzEtODk3ZC0xYWYzMDA3YzI5YzAiLCJhZ2VudHBpbl92ZXJzaW9uIjoiMC4xIiwiY2FwYWJpbGl0aWVzIjpbInJlYWQ6ZGF0YSIsIndyaXRlOnJlcG9ydHMiXX0.MEUCIQDhZ...
Step 5: Verify a Credential
Verify a credential against the discovery document.
agentpin verify \
--credential ./credential.jwt \
--discovery ./discovery.json \
--offline
Verification Result
VERIFIED
Agent: urn:agentpin:example.com:my-agent
Issuer: example.com
Capabilities: read:data, write:reports
Key Pinning: first_use (pinned)
Expires: 2026-02-08T01:00:00Z
Step 6: Serve Discovery Endpoints
Run the AgentPin server to host your discovery and revocation documents.
agentpin-server \
--discovery ./discovery.json \
--port 8080
This serves the following endpoints:
GET /.well-known/agent-identity.json → Discovery document
GET /.well-known/agent-identity-revocations.json → Revocation list
GET /health → Health check
Optionally include a revocation document:
agentpin-server \
--discovery ./discovery.json \
--revocation ./revocations.json \
--bind 0.0.0.0 \
--port 8080