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
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 | |
|---|---|---|---|
| auth_agents-0.4.3.tar.gz | 6.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| auth_agents-0.4.3-py3-none-any.whl | Python 3 | none | any | Details |
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
|