auth-agents
Verify AI agent identities with Agent Auth. DID-based authentication using Ed25519 and Verifiable Credentials.
Install
pip install auth-agents
Quick Start — Verify an Agent Credential
from auth_agents import AuthAgents
client = AuthAgents()
result = client.verify("eyJhbGciOiJFZERTQSJ9...")
if result["valid"]:
print(result["did"]) # did:key:z6Mk...
print(result["agent_name"]) # Claude
print(result["agent_model"]) # claude-opus-4-6
print(result["key_origin"]) # "server_generated" or "client_provided"
Authentication Flows
Server-Generated Keys (zero setup)
The server generates an Ed25519 keypair and returns the private key once. Store it securely — the server never retains it.
from auth_agents import AuthAgents
client = AuthAgents()
# 1. Register — server generates keypair and returns private key
identity = client.register(
agent_name="MyAgent",
agent_model="claude-opus-4-6",
agent_provider="Anthropic",
agent_purpose="Automated data processing",
)
did = identity["did"]
credential = identity["credential"]
private_key_jwk = identity["private_key_jwk"] # save this securely
# identity["key_origin"] == "server_generated"
# 2. Request a challenge nonce
challenge_resp = client.challenge(did)
challenge_id = challenge_resp["challenge_id"]
nonce = challenge_resp["nonce"]
# 3. Sign the nonce with the stored private key
signature = AuthAgents.sign_challenge(private_key_jwk, nonce)
# 4. Authenticate
auth_result = client.authenticate(
challenge_id=challenge_id,
did=did,
signature=signature,
)
if auth_result["valid"]:
print("Authenticated!", auth_result["session_token"])
Headless / Bring-Your-Own-Key (BYOK)
Generate your own keypair locally, register with your public key, and sign challenges with your private key. The server never sees your private key.
from auth_agents import AuthAgents
client = AuthAgents()
# 1. Generate a local Ed25519 keypair
key_pair = AuthAgents.generate_key_pair()
public_key_jwk = key_pair["public_key_jwk"]
private_key_jwk = key_pair["private_key_jwk"] # keep secret
# 2. Register with your own public key
identity = client.register(
agent_name="MyAgent",
agent_model="claude-opus-4-6",
agent_provider="Anthropic",
agent_purpose="Automated data processing",
public_key_jwk=public_key_jwk,
)
did = identity["did"]
credential = identity["credential"]
# identity["key_origin"] == "client_provided"
# 3. Request a challenge nonce
challenge_resp = client.challenge(did)
challenge_id = challenge_resp["challenge_id"]
nonce = challenge_resp["nonce"]
# 4. Sign the nonce locally — nonce is signed as UTF-8 text
signature = AuthAgents.sign_challenge(private_key_jwk, nonce)
# 5. Authenticate
auth_result = client.authenticate(
challenge_id=challenge_id,
did=did,
signature=signature,
)
if auth_result["valid"]:
print("Authenticated!", auth_result["session_token"])
API Reference
AuthAgents(base_url=...)
Client class. Defaults to https://auth.usevigil.dev. The SDK enforces HTTPS for all API communication. HTTP is only allowed for localhost during development.
AuthAgents.generate_key_pair() — static
Generate a fresh Ed25519 keypair. Returns:
{
"public_key_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "<base64url>"},
"private_key_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "<base64url>", "d": "<base64url>"},
}
AuthAgents.sign_challenge(private_key_jwk, nonce) — static
Sign a challenge nonce with an Ed25519 private key JWK. Returns a base64url-encoded signature string (no padding).
client.register(...)
Register a new agent identity. Pass public_key_jwk for BYOK; omit it for
server-generated keys. Optional inputs:
metadata— dict of string key/value pairs
Returns a dict including:
| Field | Description |
|---|---|
did |
Agent DID (did:key:z6Mk...) |
credential |
VC-JWT string |
key_fingerprint |
Short fingerprint of the public key |
key_origin |
"server_generated" or "client_provided" |
private_key_jwk |
Private key JWK (server-generated flow only) |
Registration always returns a credential with the server default lifetime (24 hours).
To customize the credential lifetime, use credential_expires_in on client.challenge(...).
client.challenge(did, site_id=None, credential_expires_in=None)
Request an authentication challenge nonce. Optional site_id scopes the
challenge/session in site-provisioned deployments. Optional credential_expires_in
sets the credential lifetime in seconds, controlled by the website developer
(0 means non-expiring). Returns challenge_id, nonce, and expires_in.
client.authenticate(challenge_id, did, signature)
Submit a signed challenge. Returns valid, session_token, credential,
agent object, and expires_in. The credential uses the lifetime chosen in the
preceding client.challenge(...) call.
client.verify(credential)
Verify a VC-JWT credential.
- Valid credential: returns
{"valid": True, ...} - Invalid credential (HTTP 401): returns
{"valid": False, "error": "...", "message": "..."}without raising
Returns a dict including:
| Field | Description |
|---|---|
valid |
True if the credential is valid |
did |
Agent DID |
agent_name |
Agent display name |
agent_model |
Model identifier (e.g. claude-opus-4-6) |
agent_provider |
Provider name (e.g. Anthropic) |
agent_purpose |
What the agent intends to do |
key_fingerprint |
Short fingerprint of the public key |
key_origin |
"server_generated" or "client_provided" |
issued_at |
ISO 8601 issuance timestamp |
expires_at |
ISO 8601 expiration timestamp (or None) |
verify(credential) — module-level shorthand
Equivalent to AuthAgents().verify(credential).
Documentation
Full API reference at usevigil.dev/docs
Metadata
Release files for auth-agents 0.4.3
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 |
|---|---|---|---|---|
| auth_agents-0.4.3.tar.gz | 6.8 kB | Without provenance | Details for auth_agents-0.4.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| auth_agents-0.4.3-py3-none-any.whl | Python 3 | none | any | Details for auth_agents-0.4.3-py3-none-any.whl |
Total release size: 14.4 kB
Release files / auth_agents-0.4.3.tar.gz
| Download URL | auth_agents-0.4.3.tar.gz |
|---|---|
| Size | 6.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
27547d88b71c2731d89be44129c069cca1e8b854574289b62d17daedf2051436
|
|
BLAKE2b-256 checksum How to use checksums |
3533289f57b2369f038da87286f75a2a1657fc8089222411e0aaebe0be6f0456
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / auth_agents-0.4.3-py3-none-any.whl
| Download URL | auth_agents-0.4.3-py3-none-any.whl |
|---|---|
| Size | 7.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec1f9774e7480ceb30d814484746c764f5573a1091fd10d2bb5dc5fff5de2104
|
|
BLAKE2b-256 checksum How to use checksums |
fde1324424e19ed162613c9d8c1e95b43b3121bc10a59d4ac2a973c046ff0c36
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Security for auth-agents 0.4.3
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.