Creduent Protocol SDK - cryptographic identity for AI agents
Project description
Creduent Python SDK
The official Python SDK for the Creduent Protocol — a federated, open trust-verification layer and cryptographic identity infrastructure for autonomous AI agents.
Creduent enables autonomous agents to cryptographically sign metadata, verify identities across administrative domains via DNS bindings, and interact with the Creduent registry for secure, machine-to-machine trust checks.
Key Features
- 🔑 Cryptographic Identity Management: Generate secure Ed25519 keypairs for AI agents.
- ✍️ RFC 8785 Canonical Signatures: Compute cryptographic signatures over JSON agent documents using JCS and Ed25519.
- 🛡️ SSRF Protection: Safe endpoint resolution blocking private/loopback network ranges.
- 🔗 DNS Trust Binding: Verify cryptographic bindings between
agent://identifiers and web domains. - 🏛️ Registry Integration: Register agents and resolve signed attestations from the Creduent Registry.
- 🛠️ CLI Utilities: Out-of-the-box CLI commands for signing, verification, and key generation.
- ⚙️ Serverless-Safe Env Loader: Avoids
.envinterference in Vercel and other serverless environments.
Installation
pip install creduent
Architectural Flow
+------------------+ +----------------------+ +------------------+
| Agent Domain | | Creduent Registry | | Agent Client |
| (agent.json) | | api.idevsec.com | | (MCP Host) |
+------------------+ +----------------------+ +------------------+
| | |
|---- 1. Serve agent.json ------>| |
| |-- 2. Verify identity & DNS --->|
| | and sign attestation |
|<--- 3. Query agent endpoint ------------------------------------|
| | |
| |<--- 4. Fetch attestation ------|
Registering Your Agent
Registration is open — no admin key required. Any developer can register an agent.
After registration, your agent gets level: "unverified". Contact the registry admin for verified or trusted upgrade.
The backend runs 6 verification steps — all must pass:
Step 1 → Fetch agent.json from your agent_json_url
Step 2 → Validate schema (7 required fields)
Step 3 → Confirm agent_id matches in both form and file
Step 4 → Verify Ed25519 self-signature
Step 5 → Check DNS TXT record: _creduent.yourdomain.com
Step 6 → Health check your agent endpoint (must be live HTTPS)
Step 1 — Generate Ed25519 Keypair
from creduent import generate_keys
private_key_pem, public_key_str = generate_keys()
with open("private_key.pem", "w") as f:
f.write(private_key_pem)
print(public_key_str) # ed25519:ABC123... ← goes in agent.json
Or via CLI:
creduent-sign generate-keys
# Saves: private_key.pem (KEEP SECRET)
# Prints: ed25519:... (public key)
Step 2 — Create agent.json
Create a draft with these required fields:
{
"version": "1.0",
"agent_id": "agent://yourorg/youragent",
"owner": "Your Name or Organization",
"public_key": "ed25519:ABC123...",
"endpoint": "https://yourdomain.com/agent",
"capabilities": ["task_execution", "file_read"]
}
| Field | Requirement |
|---|---|
version |
Must be exactly "1.0" |
agent_id |
Format: agent://<namespace>/<name> — lowercase, alphanumeric, hyphens |
owner |
Any string |
public_key |
Must start with ed25519: |
endpoint |
Live public HTTPS URL (no localhost, no private IPs) |
capabilities |
Array of strings |
signature |
Added in next step — do not add manually |
Step 3 — Sign agent.json
from creduent import sign
import json
with open("draft_agent.json") as f:
draft = json.load(f)
with open("private_key.pem") as f:
private_key_pem = f.read()
signed_doc = sign(draft, private_key_pem)
with open("agent.json", "w") as f:
json.dump(signed_doc, f, indent=2)
Or via CLI:
creduent-sign sign \
--key private_key.pem \
--input draft_agent.json \
--output agent.json
Important: Re-sign every time you modify
agent.json. Any change to the document invalidates the signature.
Step 4 — Host agent.json
Serve the signed file at a public HTTPS URL. Recommended path:
https://yourdomain.com/.well-known/agent.json
Requirements:
- HTTP
200response Content-Type: application/json- No auth, no VPN, no private IPs — must be publicly reachable
Step 5 — Add DNS TXT Record
Proves domain ownership. Add this to your domain's DNS:
| Type | Name | Value |
|---|---|---|
TXT |
_creduent |
agent://yourorg/youragent |
Full record name: _creduent.yourdomain.com
Verify propagation (~5 min):
# Windows
nslookup -type=TXT _creduent.yourdomain.com
# Linux / Mac
dig TXT _creduent.yourdomain.com
# Expected: "agent://yourorg/youragent"
Step 6 — Register
from creduent import register
result = register(
agent_id="agent://yourorg/youragent",
domain="yourdomain.com",
agent_json_url="https://yourdomain.com/.well-known/agent.json"
)
if result.success:
print(f"Registered! Level: {result.attestation['level']}")
# → Registered! Level: unverified
else:
print(f"Failed: {result.error}")
Or via curl:
curl -X POST https://api.idevsec.com/registry/register \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent://yourorg/youragent",
"domain": "yourdomain.com",
"agent_json_url": "https://yourdomain.com/.well-known/agent.json"
}'
Success response:
{
"agent_id": "agent://yourorg/youragent",
"issuer": "agent://creduent/registry",
"level": "unverified",
"issued_at": "2026-05-31T00:00:00Z",
"expires_at": "2027-05-31T00:00:00Z",
"public_key": "ed25519:...",
"domain": "yourdomain.com",
"signature": "...",
"status": "registered"
}
Common Registration Errors
| Error | Cause | Fix |
|---|---|---|
Failed to fetch agent.json: HTTP 404 |
File not at URL | Check URL is public and returns 200 |
Missing required field 'signature' |
Draft not signed | Run creduent-sign sign first |
agent_id in agent.json does not match |
Mismatch in form vs file | Use exact same string in both |
Cryptographic signature is INVALID |
File modified after signing | Re-sign with creduent-sign sign |
DNS TXT record not found (NXDOMAIN) |
TXT record missing | Add _creduent TXT to your DNS |
does not contain agent_id |
Wrong TXT value | Value must be exactly agent://yourorg/youragent |
Endpoint healthcheck failed |
Endpoint unreachable | Is your server live? Public HTTPS? |
429 Too many requests |
5/hour rate limit | Wait 1 hour and retry |
Registration Checklist
[ ] Ed25519 keypair generated (private_key.pem + public key)
[ ] draft_agent.json created with all required fields
[ ] agent.json signed (signature field present)
[ ] agent.json hosted at a public HTTPS URL
[ ] DNS TXT record added: _creduent.yourdomain.com = agent://yourorg/youragent
[ ] DNS propagated (verified with nslookup or dig)
[ ] register() called → status: "registered" received
Quickstart (Full Example)
from creduent import generate_keys, sign, verify, register, attest, CreduEntError
try:
# 1. Generate keypair
private_key_pem, public_key_str = generate_keys()
# 2. Sign a draft agent.json
draft = {
"version": "1.0",
"agent_id": "agent://creduent/reconbot",
"owner": "Creduent Foundation",
"public_key": public_key_str,
"endpoint": "https://api.idevsec.com/recon",
"capabilities": ["osint", "dns_lookup"]
}
signed_doc = sign(draft, private_key_pem)
# 3. Verify self-signed document
result = verify(signed_doc)
print(f"Self-verify: {result.valid}")
# 4. Register with registry (requires DNS + hosted agent.json)
reg = register(
agent_id="agent://creduent/reconbot",
domain="api.idevsec.com",
agent_json_url="https://api.idevsec.com/.well-known/agent.json"
)
print(f"Registered: {reg.success}, Level: {reg.attestation['level']}")
# 5. Query attestation
att = attest("agent://creduent/reconbot")
print(f"Attested: {att.attested}, Level: {att.level}")
except CreduEntError as e:
print(f"Error: {e}")
Command Line Interface
creduent-sign
# Generate Ed25519 keypair
creduent-sign generate-keys
# Sign a draft agent.json
creduent-sign sign --key private_key.pem --input draft_agent.json --output agent.json
creduent-verify
# Verify a local file
creduent-verify agent.json
# Verify by URL
creduent-verify https://yourdomain.com/.well-known/agent.json
# Verify by domain
creduent-verify yourdomain.com
# Verify by agent:// URI
creduent-verify agent://creduent/reconbot
API Reference
generate_keys() → (private_key_pem: str, public_key_str: str)
Generates a new Ed25519 keypair. Returns PEM private key and ed25519:-prefixed public key.
sign(draft: dict, private_key_pem: str) → dict
Signs a draft agent.json using JCS canonicalization (RFC 8785) + Ed25519. Returns signed document with signature field.
verify(target: str | dict) → VerifyResult
Verifies a self-signed agent.json. Accepts dict, HTTPS URL, domain, local path, or agent:// URI.
result.valid— boolresult.agent_id,result.public_key,result.endpoint,result.capabilitiesresult.error— str or None
register(agent_id, domain, agent_json_url, registry_url?) → RegisterResult
Registers an agent with the Creduent registry.
result.success— boolresult.attestation— dict (level, issued_at, expires_at, ...)result.error— str or None
attest(agent_id, registry_url?) → AttestResult
Fetches attestation status for an agent from the registry.
result.attested— boolresult.level—"unverified"|"verified"|"trusted"result.issued_at,result.expires_atresult.error— str or None
Advanced Utilities
SSRF Protection
from creduent.utils import safe_requests_get
response = safe_requests_get("https://example.com/.well-known/agent.json", timeout=5)
Blocks private IPs (RFC 1918), loopback, and link-local addresses before connecting.
Serverless Environment Loader
from creduent.utils import load_dotenv
load_dotenv() # Skips loading in Vercel (VERCEL=1) to avoid clobbering prod env vars
Changelog
v0.2.1 (Current)
- Complete registration guide added to README: 6-step pipeline, DNS TXT setup, error table, and checklist.
- Fixed function name documentation (register, attest, verify, sign).
v0.2.0
- Replaced
requests.getwithsafe_requests_getfor SSRF protection. - Added comprehensive Google-style docstrings and type hints.
- Updated documentation and simplified CLI usage.
v0.1.5
- Internal beta release with security features and docstring polish.
v0.1.2
- Initial release: core signing, verification, and registration logic.
Contributing
Bugs, feature requests, and pull requests welcome via GitHub Issues.
License
MIT License — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 creduent-0.2.1.tar.gz.
File metadata
- Download URL: creduent-0.2.1.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5aa209fdc0754336e135fe044f89bf64f7373fa213dc16f27b427070683abe0
|
|
| MD5 |
36cda8da35b72bde3631c9acddb96203
|
|
| BLAKE2b-256 |
a3fe23c67517564e7c422ef89064be1dab23bd8ac5cb7f1b8a232d0db3cb767d
|
File details
Details for the file creduent-0.2.1-py3-none-any.whl.
File metadata
- Download URL: creduent-0.2.1-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75a38d805b2b10752090ff698967545eacc48a36c3acafe5d34e8e967566d2bc
|
|
| MD5 |
eecac370665e73117e1d66d81f70390d
|
|
| BLAKE2b-256 |
ffd14defb3fac6e5b3380551e55d46c8f5948a5b15ca802c4d807f2899314f18
|