|
2 | 2 |
|
3 | 3 | Domain-anchored cryptographic identity for AI agents. The second layer in the [ThirdKey](https://thirdkey.ai) trust stack (SchemaPin → **AgentPin** → Symbiont). |
4 | 4 |
|
5 | | -AgentPin lets organizations publish verifiable identity documents for their AI agents, issue short-lived cryptographic credentials (JWTs), and verify agent identity using a 12-step protocol with TOFU key pinning, capability validation, delegation chains, and revocation checking. |
| 5 | +**[Read the Documentation →](https://docs.agentpin.org)** |
6 | 6 |
|
7 | | -## Protocol Overview |
| 7 | +## What It Does |
8 | 8 |
|
9 | | -- **Discovery** — Organizations publish `/.well-known/agent-identity.json` declaring their agents, public keys, and capabilities |
10 | | -- **Credentials** — ES256 (ECDSA P-256) signed JWTs with agent identity, capabilities, constraints, and optional delegation chains |
11 | | -- **Verification** — 12-step flow: JWT parsing, temporal validation, discovery resolution, signature verification, revocation checking, agent status, capability/constraint validation, delegation chain verification, TOFU key pinning, and audience matching |
12 | | -- **Mutual Authentication** — Challenge-response protocol with 128-bit nonces for bidirectional identity verification |
13 | | -- **Revocation** — Credential, agent, and key-level revocation via `/.well-known/agent-identity-revocations.json` |
| 9 | +AgentPin lets organizations publish verifiable identity for their AI agents. Issue short-lived ES256 credentials, verify agent identity with a 12-step protocol, and enforce capability-scoped access — all anchored to your domain via `.well-known` discovery. |
14 | 10 |
|
15 | | -See [AGENTPIN_TECHNICAL_SPECIFICATION.md](AGENTPIN_TECHNICAL_SPECIFICATION.md) for the full protocol spec (v0.1.0-draft). |
16 | | - |
17 | | -## Project Structure |
18 | | - |
19 | | -``` |
20 | | -crates/ |
21 | | -├── agentpin/ # Core Rust library (publishable to crates.io) |
22 | | -├── agentpin-cli/ # CLI binary |
23 | | -└── agentpin-server/ # HTTP server for discovery/revocation endpoints |
24 | | -javascript/ # JavaScript/Node.js package (zero dependencies) |
25 | | -python/ # Python package (uses cryptography library) |
26 | | -``` |
27 | | - |
28 | | -All three implementations share the same API surface and produce interoperable credentials — a JWT issued by one language can be verified by any other. |
| 11 | +- **ES256 (ECDSA P-256)** cryptographic credentials |
| 12 | +- **Domain-anchored** `.well-known/agent-identity.json` discovery |
| 13 | +- **12-step verification** with TOFU key pinning |
| 14 | +- **Delegation chains** for maker-deployer models |
| 15 | +- **Capability-scoped credentials** with constraints |
| 16 | +- **Credential revocation** at credential, agent, and key level |
| 17 | +- **Mutual authentication** with challenge-response |
| 18 | +- **Trust bundles** for air-gapped and enterprise environments |
| 19 | +- **Cross-language** — Rust, JavaScript, and Python SDKs produce interoperable credentials |
29 | 20 |
|
30 | 21 | ## Quick Start |
31 | 22 |
|
32 | | -### Generate Keys |
33 | | - |
34 | 23 | ```bash |
35 | | -agentpin keygen --domain example.com --kid example-2026-01 --output-dir ./keys |
36 | | -``` |
37 | | - |
38 | | -Generates `example-2026-01.private.pem`, `example-2026-01.public.pem`, and `example-2026-01.public.jwk.json`. |
39 | | - |
40 | | -### Issue a Credential |
| 24 | +# Generate keys |
| 25 | +agentpin keygen --domain example.com --kid my-key-2026 --output-dir ./keys |
41 | 26 |
|
42 | | -```bash |
| 27 | +# Issue a credential |
43 | 28 | agentpin issue \ |
44 | | - --private-key ./keys/example-2026-01.private.pem \ |
45 | | - --kid example-2026-01 \ |
46 | | - --issuer example.com \ |
| 29 | + --private-key ./keys/my-key-2026.private.pem \ |
| 30 | + --kid my-key-2026 --issuer example.com \ |
47 | 31 | --agent-id "urn:agentpin:example.com:scout" \ |
48 | | - --capabilities "read:data,write:reports" \ |
49 | | - --ttl 3600 |
50 | | -``` |
51 | | - |
52 | | -Outputs a signed JWT to stdout. |
| 32 | + --capabilities "read:data,write:reports" --ttl 3600 |
53 | 33 |
|
54 | | -### Verify a Credential |
55 | | - |
56 | | -Offline (with local discovery document): |
57 | | - |
58 | | -```bash |
59 | | -agentpin verify \ |
60 | | - --credential <jwt> \ |
61 | | - --discovery ./agent-identity.json \ |
62 | | - --pin-store ./pins.json |
63 | | -``` |
64 | | - |
65 | | -Online (fetches discovery from issuer domain): |
66 | | - |
67 | | -```bash |
| 34 | +# Verify a credential |
68 | 35 | agentpin verify --credential <jwt> |
69 | 36 | ``` |
70 | 37 |
|
71 | | -Outputs a JSON verification result with validity, capabilities, key pinning status, and any errors. |
| 38 | +**[Getting Started Guide →](https://docs.agentpin.org/getting-started/)** |
72 | 39 |
|
73 | | -### Serve Discovery Endpoints |
74 | | - |
75 | | -```bash |
76 | | -agentpin-server \ |
77 | | - --discovery ./agent-identity.json \ |
78 | | - --revocation ./revocations.json \ |
79 | | - --port 8080 |
80 | | -``` |
81 | | - |
82 | | -Serves: |
83 | | -- `GET /.well-known/agent-identity.json` (Cache-Control: max-age=3600) |
84 | | -- `GET /.well-known/agent-identity-revocations.json` (Cache-Control: max-age=300) |
85 | | -- `GET /health` |
86 | | - |
87 | | -## Installation & Building |
| 40 | +## Installation |
88 | 41 |
|
89 | 42 | ### Rust |
90 | 43 |
|
91 | | -```bash |
92 | | -cargo build --workspace |
93 | | -cargo test --workspace |
94 | | -``` |
95 | | - |
96 | | -The core library has no mandatory HTTP dependency. Network fetching is behind the `fetch` feature flag: |
97 | | - |
98 | 44 | ```toml |
99 | 45 | [dependencies] |
100 | 46 | agentpin = { version = "0.1", features = ["fetch"] } |
101 | 47 | ``` |
102 | 48 |
|
103 | 49 | ### JavaScript |
104 | 50 |
|
105 | | -Requires Node.js >= 18. Zero external dependencies — uses Node.js built-in `crypto`. |
106 | | - |
107 | 51 | ```bash |
108 | | -cd javascript |
109 | | -npm install # dev dependencies only (eslint, c8) |
110 | | -npm test # runs all 76 tests |
111 | | -``` |
112 | | - |
113 | | -```javascript |
114 | | -import { generateKeyPair, pemToJwk, issueCredential, Capability, |
115 | | - verifyCredentialOffline, KeyPinStore, buildDiscoveryDocument } from 'agentpin'; |
116 | | - |
117 | | -const { privateKey, publicKey } = generateKeyPair(); |
118 | | -const jwk = pemToJwk(publicKey, 'my-key-2026'); |
119 | | - |
120 | | -const credential = issueCredential( |
121 | | - privateKey, 'my-key-2026', 'example.com', |
122 | | - 'urn:agentpin:example.com:agent', 'verifier.com', |
123 | | - [new Capability('read:data')], null, null, 3600 |
124 | | -); |
125 | | - |
126 | | -const result = verifyCredentialOffline( |
127 | | - credential, discovery, null, new KeyPinStore(), 'verifier.com' |
128 | | -); |
| 52 | +npm install agentpin |
129 | 53 | ``` |
130 | 54 |
|
131 | 55 | ### Python |
132 | 56 |
|
133 | | -Requires Python >= 3.8. |
134 | | - |
135 | 57 | ```bash |
136 | | -cd python |
137 | | -pip install -e ".[dev]" |
138 | | -pytest tests/ -v # runs all 76 tests |
| 58 | +pip install agentpin |
139 | 59 | ``` |
140 | 60 |
|
141 | | -```python |
142 | | -from agentpin import ( |
143 | | - generate_key_pair, pem_to_jwk, issue_credential, |
144 | | - verify_credential_offline, KeyPinStore, Capability, |
145 | | - build_discovery_document, EntityType, AgentStatus, |
146 | | -) |
147 | | - |
148 | | -private_key, public_key = generate_key_pair() |
149 | | -jwk = pem_to_jwk(public_key, "my-key-2026") |
150 | | - |
151 | | -credential = issue_credential( |
152 | | - private_key, "my-key-2026", "example.com", |
153 | | - "urn:agentpin:example.com:agent", "verifier.com", |
154 | | - [Capability("read:data")], None, None, 3600, |
155 | | -) |
156 | | - |
157 | | -result = verify_credential_offline( |
158 | | - credential, discovery, None, KeyPinStore(), "verifier.com" |
159 | | -) |
160 | | -``` |
| 61 | +## Documentation |
161 | 62 |
|
162 | | -## Key Design Decisions |
| 63 | +| Topic | Link | |
| 64 | +|-------|------| |
| 65 | +| Getting Started | [docs.agentpin.org/getting-started](https://docs.agentpin.org/getting-started/) | |
| 66 | +| Verification Flow | [docs.agentpin.org/verification-flow](https://docs.agentpin.org/verification-flow/) | |
| 67 | +| CLI Reference | [docs.agentpin.org/cli-guide](https://docs.agentpin.org/cli-guide/) | |
| 68 | +| Trust Bundles | [docs.agentpin.org/trust-bundles](https://docs.agentpin.org/trust-bundles/) | |
| 69 | +| Delegation Chains | [docs.agentpin.org/delegation-chains](https://docs.agentpin.org/delegation-chains/) | |
| 70 | +| Deployment | [docs.agentpin.org/deployment](https://docs.agentpin.org/deployment/) | |
| 71 | +| Security | [docs.agentpin.org/security](https://docs.agentpin.org/security/) | |
| 72 | +| Technical Specification | [AGENTPIN_TECHNICAL_SPECIFICATION.md](AGENTPIN_TECHNICAL_SPECIFICATION.md) | |
163 | 73 |
|
164 | | -- **ES256 only** — Rejects all other JWT algorithms to prevent algorithm confusion attacks |
165 | | -- **Inline JWT implementation** — No external JWT library in any language; we control algorithm validation |
166 | | -- **No-redirect enforcement** — HTTP client configured to reject redirects per spec security requirements |
167 | | -- **Feature-gated HTTP** — Core libraries work offline; network fetching is opt-in |
168 | | -- **TOFU key pinning** — Trust-on-first-use with JWK thumbprint (RFC 7638) for key continuity verification |
169 | | -- **Cross-language interop** — All three implementations use DER-encoded ECDSA signatures and identical JSON field names, so credentials are fully interoperable |
| 74 | +## Project Structure |
| 75 | + |
| 76 | +``` |
| 77 | +crates/ |
| 78 | +├── agentpin/ # Core Rust library |
| 79 | +├── agentpin-cli/ # CLI binary |
| 80 | +└── agentpin-server/ # HTTP server for .well-known endpoints |
| 81 | +javascript/ # JavaScript/Node.js SDK |
| 82 | +python/ # Python SDK |
| 83 | +``` |
170 | 84 |
|
171 | 85 | ## License |
172 | 86 |
|
173 | | -MIT - Jascha Wanger / [ThirdKey.ai](https://thirdkey.ai) |
| 87 | +MIT — Jascha Wanger / [ThirdKey.ai](https://thirdkey.ai) |
0 commit comments