Verify AI agent identities with Agent Auth. DID-based authentication using Ed25519 and Verifiable Credentials.
Project description
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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auth_agents-0.4.3.tar.gz.
File metadata
- Download URL: auth_agents-0.4.3.tar.gz
- Upload date:
- Size: 6.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27547d88b71c2731d89be44129c069cca1e8b854574289b62d17daedf2051436
|
|
| MD5 |
ef3bf2872b452029a53cb018253ee46b
|
|
| BLAKE2b-256 |
3533289f57b2369f038da87286f75a2a1657fc8089222411e0aaebe0be6f0456
|
File details
Details for the file auth_agents-0.4.3-py3-none-any.whl.
File metadata
- Download URL: auth_agents-0.4.3-py3-none-any.whl
- Upload date:
- Size: 7.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec1f9774e7480ceb30d814484746c764f5573a1091fd10d2bb5dc5fff5de2104
|
|
| MD5 |
c6e523fd701862287f64aa814093f712
|
|
| BLAKE2b-256 |
fde1324424e19ed162613c9d8c1e95b43b3121bc10a59d4ac2a973c046ff0c36
|