agentpin
Domain-anchored cryptographic identity for AI agents. Part of the ThirdKey trust stack (SchemaPin → AgentPin → Symbiont).
Requires Python >= 3.8.
Install
pip install agentpin
Quick Start
from agentpin import (
generate_key_pair,
generate_key_id,
pem_to_jwk,
issue_credential,
verify_credential_offline,
build_discovery_document,
KeyPinStore,
Capability,
)
# Generate keys
private_key_pem, public_key_pem = generate_key_pair()
kid = generate_key_id(public_key_pem)
jwk = pem_to_jwk(public_key_pem, kid)
# Build discovery document
discovery = build_discovery_document(
"example.com", "maker", [jwk],
[{
"agent_id": "urn:agentpin:example.com:my-agent",
"name": "My Agent",
"capabilities": ["read:data", "write:reports"],
"status": "active",
}],
2,
)
# Issue credential
credential = issue_credential(
private_key_pem=private_key_pem,
kid=kid,
issuer="example.com",
agent_id="urn:agentpin:example.com:my-agent",
audience="verifier.com",
capabilities=[
Capability.create("read", "data"),
Capability.create("write", "reports"),
],
constraints=None,
delegation_chain=None,
ttl_secs=3600,
)
# Verify credential
result = verify_credential_offline(
credential_jwt=credential,
discovery=discovery,
revocation=None,
pin_store=KeyPinStore(),
audience="verifier.com",
)
if result.valid:
print(f"Agent: {result.agent_id}")
print(f"Capabilities: {result.capabilities}")
print(f"Key pinning: {result.key_pinning}")
else:
print(f"Failed: {result.error_code} - {result.error_message}")
Features
- ES256 (ECDSA P-256) cryptographic credentials
- Domain-anchored
.well-known/agent-identity.jsondiscovery - 12-step verification protocol
- Maker-deployer delegation chains
- Capability-scoped credentials with constraints
- TOFU key pinning (compatible with SchemaPin)
- Credential, agent, and key-level revocation
- Mutual authentication with challenge-response
- Trust bundles for air-gapped and enterprise verification (v0.2.0)
API
Key Management
generate_key_pair() # → (private_key_pem, public_key_pem)
generate_key_id(public_key_pem) # → kid (hex SHA-256)
pem_to_jwk(public_key_pem, kid) # → JWK dict
jwk_to_pem(jwk) # → PEM string
Credentials
issue_credential(
private_key_pem, kid, issuer, agent_id, audience,
capabilities, constraints, delegation_chain, ttl_secs
)
# → compact JWT string
Verification
# Offline (with local discovery document)
verify_credential_offline(jwt, discovery, revocation, pin_store, audience, config)
# → VerificationResult(valid, agent_id, issuer, capabilities, key_pinning, ...)
# Online (auto-fetches discovery from issuer domain)
verify_credential(jwt, pin_store, audience, config)
Discovery & Revocation
build_discovery_document(entity, entity_type, public_keys, agents, max_delegation_depth)
build_revocation_document(entity)
add_revoked_credential(doc, jti, reason)
add_revoked_agent(doc, agent_id, reason)
add_revoked_key(doc, kid, reason)
Mutual Authentication
from agentpin import create_challenge, create_response, verify_response
challenge = create_challenge(verifier_credential)
response = create_response(challenge, private_key_pem, kid)
verify_response(response, challenge["nonce"], public_key_pem)
Key Pinning
from agentpin import KeyPinStore, PinningResult
store = KeyPinStore()
result = store.check_and_pin(domain, jwk) # PinningResult.FIRST_USE | MATCHED | CHANGED
store.add_key(domain, jwk) # allow key rotation
json_str = store.to_json() # persist
restored = KeyPinStore.from_json(json_str) # restore
Trust Bundles (v0.2.0)
from agentpin import (
create_trust_bundle,
find_bundle_discovery,
verify_credential_with_bundle,
save_trust_bundle,
load_trust_bundle,
)
# Create a bundle with pre-loaded discovery documents
bundle = create_trust_bundle()
bundle["documents"].append(discovery)
bundle["revocations"].append(revocation)
# Verify without any HTTP calls
result = verify_credential_with_bundle(
credential, bundle, pin_store=KeyPinStore(), audience="verifier.com"
)
# Save / load bundles to disk
save_trust_bundle(bundle, "trust-bundle.json")
bundle = load_trust_bundle("trust-bundle.json")
Configuration
from agentpin import VerifierConfig
config = VerifierConfig(
clock_skew_secs=60, # allow 60s time skew
max_ttl_secs=86400, # max 24h credential lifetime
)
Cross-Language Interoperability
Credentials issued by the Python package can be verified by the Rust and JavaScript implementations, and vice versa. All implementations use DER-encoded ECDSA signatures and identical JSON field names.
License
MIT — ThirdKey.ai
Metadata
Release files for agentpin 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| agentpin-0.3.0.tar.gz | 42.0 kB | Without provenance | Details for agentpin-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| agentpin-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for agentpin-0.3.0-py3-none-any.whl |
Total release size: 76.2 kB
Release files / agentpin-0.3.0.tar.gz
| Download URL | agentpin-0.3.0.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c6998b46ef855240d3143e0182c7470745bfab59207c50b1f56249e3499a2e6
|
|
BLAKE2b-256 checksum How to use checksums |
ab505971d1dbf9c3403dba871185eb0f16a454d5bf1ea47eaf7e5f760848bfe5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / agentpin-0.3.0-py3-none-any.whl
| Download URL | agentpin-0.3.0-py3-none-any.whl |
|---|---|
| Size | 34.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5ddef1f127de80d86a426f157bf7b8860847fb3bd5ebab47e6025713bb43ce50
|
|
BLAKE2b-256 checksum How to use checksums |
220ea4bd2190afaf8d04de7b456d6a3b258165d7ff101befe4afc7d2640b3bd5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Security for agentpin 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.