{"skill":{"slug":"agentpin","displayName":"AgentPin","summary":"Provides domain-anchored cryptographic identity verification for AI agents using ES256 JWTs, TOFU key pinning, revocation, and delegation chain checks.","description":"# AgentPin Development Skills Guide\n\n**Purpose**: This guide helps AI assistants work with AgentPin for domain-anchored cryptographic agent identity verification.\n\n**For Full Documentation**: See the [README](https://github.com/ThirdKeyAI/agentpin/blob/main/README.md) and [Technical Specification](https://github.com/ThirdKeyAI/agentpin/blob/main/AGENTPIN_TECHNICAL_SPECIFICATION.md).\n\n## What AgentPin Does\n\nAgentPin is a domain-anchored cryptographic identity protocol for AI agents. It enables organizations to publish verifiable identity documents for their agents, issue short-lived JWT credentials, and verify agent identity through a multi-step protocol including TOFU key pinning, revocation checking, and delegation chains.\n\n**Part of the ThirdKey trust stack**: SchemaPin (tool integrity) → AgentPin (agent identity) → Symbiont (runtime)\n\n---\n\n## Architecture\n\n```\nOrganization                         Verifying Party\n────────────                         ───────────────\n1. Generate ECDSA P-256 keypair\n2. Publish agent identity at          3. Discover identity from\n   /.well-known/agent-identity.json      /.well-known/agent-identity.json\n4. Issue JWT credential               5. Verify credential (12-step flow)\n   (ES256 signed, short-lived)           - JWT parsing & ES256 verification\n                                         - Domain binding check\n                                         - TOFU key pinning\n                                         - Revocation checking\n                                         - Capability validation\n                                         - Delegation chain verification\n```\n\n---\n\n## Project Structure\n\n```\ncrates/\n├── agentpin/          Core library (no mandatory HTTP dep)\n├── agentpin-cli/      CLI binary (keygen, issue, verify, bundle)\n└── agentpin-server/   Axum server for .well-known endpoints\n```\n\n---\n\n## Quick Start by Language\n\n### Rust (CLI)\n\n```bash\n# Generate keys\ncargo run -p agentpin-cli -- keygen \\\n    --output-dir ./keys --agent-name \"my-agent\"\n\n# Issue a credential (ES256 JWT, 1-hour TTL)\ncargo run -p agentpin-cli -- issue \\\n    --key ./keys/my-agent.private.pem \\\n    --issuer \"https://example.com\" \\\n    --agent-id \"my-agent\" \\\n    --capabilities read,write --ttl 3600\n\n# Verify offline\ncargo run -p agentpin-cli -- verify \\\n    --credential ./credential.jwt \\\n    --discovery ./agent-identity.json\n\n# Verify online (fetches from .well-known)\ncargo run -p agentpin-cli -- verify \\\n    --credential ./credential.jwt --domain example.com\n\n# Create trust bundle for air-gapped environments\ncargo run -p agentpin-cli -- bundle \\\n    --discovery ./agent-identity.json \\\n    --revocation ./revocations.json --output ./bundle.json\n```\n\n### Rust (Library)\n\n```rust\nuse agentpin::{\n    crypto,\n    credential::CredentialBuilder,\n    verification::verify_credential,\n    pinning::KeyPinStore,\n};\n\nlet (private_key, public_key) = crypto::generate_keypair()?;\n\nlet credential = CredentialBuilder::new()\n    .issuer(\"https://example.com\")\n    .agent_id(\"my-agent\")\n    .capability(\"read\")\n    .capability(\"write\")\n    .ttl_secs(3600)\n    .sign(&private_key)?;\n\nlet result = verify_credential(&credential, &discovery_doc, &pin_store)?;\n```\n\n### JavaScript\n\n```bash\nnpm install agentpin\n```\n\n```javascript\nimport {\n    generateKeypair, issueCredential, verifyCredential,\n    KeyPinStore\n} from 'agentpin';\n\n// Generate ECDSA P-256 keypair\nconst { privateKey, publicKey } = await generateKeypair();\n\n// Issue a credential\nconst credential = await issueCredential(privateKey, {\n    issuer: 'https://example.com',\n    agentId: 'my-agent',\n    capabilities: ['read', 'write'],\n    ttlSecs: 3600,\n});\n\n// Verify\nconst pinStore = new KeyPinStore();\nconst result = await verifyCredential(credential, discoveryDoc, pinStore);\n```\n\n### Python\n\n```bash\npip install agentpin\n```\n\n```python\nfrom agentpin.crypto import generate_keypair\nfrom agentpin.credential import issue_credential\nfrom agentpin.verification import verify_credential\nfrom agentpin.pinning import KeyPinStore\n\nprivate_key, public_key = generate_keypair()\n\ncredential = issue_credential(\n    private_key,\n    issuer=\"https://example.com\",\n    agent_id=\"my-agent\",\n    capabilities=[\"read\", \"write\"],\n    ttl_secs=3600,\n)\n\npin_store = KeyPinStore()\nresult = verify_credential(credential, discovery_doc, pin_store)\n```\n\n### Serve .well-known Endpoints\n\n```bash\ncargo run -p agentpin-server -- \\\n    --identity ./agent-identity.json \\\n    --revocation ./revocations.json \\\n    --port 3000\n```\n\nServes:\n- `GET /.well-known/agent-identity.json` (Cache-Control: max-age=3600)\n- `GET /.well-known/agent-identity-revocations.json` (Cache-Control: max-age=300)\n- `GET /health`\n\n---\n\n## Core Library API\n\n### Key Modules\n\n| Module | Purpose |\n|--------|---------|\n| `crypto` | ECDSA P-256 signing/verification (no external JWT crate) |\n| `types` | Core data structures (agents, credentials, capabilities) |\n| `credential` | JWT issuance and parsing |\n| `discovery` | Publishing and resolving agent identity documents |\n| `verification` | 12-step credential validation flow |\n| `revocation` | Checking revoked credentials/agents/keys |\n| `pinning` | TOFU key pinning with JWK thumbprints |\n| `delegation` | Delegation chain validation |\n| `mutual` | Challenge-response mutual authentication (128-bit nonces) |\n| `jwk` | JWK handling and thumbprint computation |\n| `resolver` | Pluggable discovery resolution |\n\n### Language API Reference\n\n| Operation | Rust | JavaScript | Python |\n|-----------|------|------------|--------|\n| Generate keys | `crypto::generate_keypair()` | `generateKeypair()` | `generate_keypair()` |\n| Issue credential | `CredentialBuilder::new().sign()` | `issueCredential()` | `issue_credential()` |\n| Verify credential | `verify_credential()` | `verifyCredential()` | `verify_credential()` |\n| Key pinning | `KeyPinStore` | `KeyPinStore` | `KeyPinStore` |\n| Trust bundle | `TrustBundle::from_json()` | `TrustBundle.fromJson()` | `TrustBundle.from_json()` |\n| Mutual auth | `MutualAuth::challenge()` | `createChallenge()` | `create_challenge()` |\n\n### Feature Flags\n\n| Feature | Purpose |\n|---------|---------|\n| `fetch` | Enables HTTP via reqwest for online discovery |\n| (default) | Core library with no HTTP dependency |\n\n---\n\n## Key Concepts\n\n### ES256 Only\n\nAgentPin exclusively uses ES256 (ECDSA P-256). All other algorithms are rejected. This is enforced inline without an external JWT crate.\n\n### 12-Step Verification\n\nThe credential verification flow includes:\n1. JWT structure parsing\n2. Header algorithm validation (ES256 only)\n3. Signature verification\n4. Issuer domain extraction\n5. Discovery document resolution\n6. Domain binding verification\n7. Key matching (issuer key vs discovery)\n8. TOFU key pinning check\n9. Expiration validation\n10. Revocation checking\n11. Capability validation\n12. Delegation chain verification (if present)\n\n### TOFU Key Pinning\n\nOn first credential verification for a domain, the agent's public key (JWK thumbprint) is pinned. Subsequent verifications reject different keys for the same domain — detecting key substitution attacks.\n\n### Delegation Chains\n\nAgents can delegate capabilities to sub-agents. The delegation chain is validated to ensure:\n- Each link is signed by the delegator\n- Capabilities only narrow (never widen) down the chain\n- Chain depth limits are respected\n\n### Mutual Authentication\n\nChallenge-response protocol with 128-bit nonces for bidirectional agent identity verification.\n\n---\n\n## Discovery Document Format\n\nPublished at `/.well-known/agent-identity.json`:\n\n```json\n{\n    \"schema_version\": \"0.2\",\n    \"domain\": \"example.com\",\n    \"agents\": [\n        {\n            \"agent_id\": \"my-agent\",\n            \"display_name\": \"My Agent\",\n            \"description\": \"A helpful agent\",\n            \"capabilities\": [\"read\", \"write\"],\n            \"public_key_jwk\": { ... },\n            \"constraints\": {\n                \"max_ttl_secs\": 86400,\n                \"allowed_scopes\": [\"api\"]\n            }\n        }\n    ],\n    \"revocation_endpoint\": \"https://example.com/.well-known/agent-identity-revocations.json\",\n    \"directory_listing\": true\n}\n```\n\n---\n\n## v0.2.0 Features\n\n### Trust Bundles (Offline / Air-Gapped)\n\nPre-package discovery + revocation data for environments without internet:\n\n```python\nfrom agentpin.bundle import TrustBundle\n\nbundle = TrustBundle.from_json(bundle_json_str)\ndiscovery = bundle.find_discovery(\"example.com\")\nrevocation = bundle.find_revocation(\"example.com\")\n```\n\n### Pluggable Discovery Resolvers\n\n```python\nfrom agentpin.discovery import (\n    WellKnownResolver,    # HTTP .well-known lookups\n    DnsTxtResolver,       # DNS TXT record lookups\n    ManualResolver,       # Pre-configured discovery data\n)\n```\n\n### Directory Listing\n\nDomains can advertise all their agents via `\"directory_listing\": true` in the discovery document. Verifiers can enumerate available agents before issuing challenges.\n\n---\n\n## Development\n\n### Build and Test\n\n```bash\n# Build all crates\ncargo build --workspace\n\n# Run all tests\ncargo test --workspace\n\n# Lint\ncargo clippy --workspace\n\n# Format check\ncargo fmt --check\n```\n\n### Conventions\n\n- Rust edition 2021, MSRV 1.70\n- `cargo clippy --workspace` must pass with zero warnings\n- `cargo fmt --check` must pass\n- Inline tests in source files (`#[cfg(test)] mod tests`)\n- ES256 only — reject all other algorithms\n- Feature-gated HTTP: `fetch` feature enables reqwest\n\n---\n\n## Pro Tips for AI Assistants\n\n1. **ES256 only** — never accept RS256, HS256, or any other algorithm\n2. **Short-lived credentials** — prefer TTLs of hours, not days\n3. **Always check revocation** before trusting a credential\n4. **TOFU pinning** means first-seen key is trusted — warn on key changes\n5. **Delegation chains** should narrow capabilities, never widen them\n6. **No external JWT crate** — algorithm validation is controlled inline to prevent algorithm confusion attacks\n7. **Feature-gate HTTP** — use the `fetch` feature only when online discovery is needed; default is offline-capable\n8. **Cross-compatible with SchemaPin** — both use ECDSA P-256, same crypto primitives\n9. **Trust bundles** are ideal for CI/CD and air-gapped deployments — pre-package discovery + revocation data\n10. **JavaScript and Python SDKs** provide identical verification guarantees to the Rust crate\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":1019,"installsAllTime":1,"installsCurrent":1,"stars":2,"versions":1},"createdAt":1771138617907,"updatedAt":1778491542212},"latestVersion":{"version":"1.0.0","createdAt":1771138617907,"changelog":"Initial release of AgentPin skill: easy cryptographic identity for AI agents, with cross-language support.\n\n- Provides an overview of AgentPin's architecture, protocol flow, and core concepts.\n- Includes language-specific quick start guides for Rust, JavaScript, and Python.\n- Documents core modules, features, and verification steps in detail.\n- Explains TOFU key pinning, delegation chains, and mutual authentication protocols.\n- Details the structure and endpoints for discovery and revocation documents.\n- Describes the project layout and feature flags for customization.","license":null},"metadata":null,"owner":{"handle":"jaschadub","userId":"s176rj5h9rh0de7t9tcfqxyyfd8859g6","displayName":"Jascha","image":"https://avatars.githubusercontent.com/u/768841?v=4"},"moderation":null}