Skip to main content

Creduent Protocol SDK - cryptographic identity for AI agents

Project description

Creduent Python SDK

PyPI version License Python Compatibility Downloads

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 .env interference 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 200 response
  • Content-Type: application/json
  • No auth, no VPN, no private IPs — must be publicly reachable

Cloudflare Users — Required Configuration

If your domain is proxied through Cloudflare (orange cloud), you must add a WAF rule before registering. Without this, Cloudflare will block the Creduent registry server from fetching your agent.json and health-checking your endpoint, returning HTTP 403.

Rule 1 — Allow Registry Fetch and Endpoint Health Check

Cloudflare Dashboard → Security → Security Rules → Custom Rules → Create Rule

Name: Allow Creduent Manifest and Endpoint Field: URI Path Operator: is in Value:

  • /.well-known/agent.json
  • /<your-agent-endpoint-path> (e.g. /agent or /api/agent) Action: Skip Skip: All remaining custom rules + All rate limiting rules + All managed rules Place at: First

DNS TXT Record (Cloudflare)

When adding the _creduent TXT record in Cloudflare DNS:

  • Make sure the orange cloud (proxy) is OFF for the TXT record
  • TXT records do not need to be proxied
  • TTL: Auto

Common Cloudflare Errors

Error Cause Fix
Failed to fetch agent.json: HTTP 403 Cloudflare WAF blocking registry server Add the WAF rule above
Failed to fetch agent.json: HTTP 403 (after adding rules) Bot Fight Mode JS challenge Disable JS Detections under Security → Bots
Registration succeeds but resolver shows 403 CSP blocking api.idevsec.com Add api.idevsec.com to connect-src in your site's CSP headers

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}")

Challenge-Response Authentication

Allows agents to prove their cryptographically registered identity to other agents.

# Agent proving its identity to another agent
from creduent import challenge

# Agent side — prove identity
proof = challenge.create_proof(
    agent_id="agent://cyberhavox/havox-ai",
    private_key_pem=open("private_key.pem").read()
)
# proof = {"verified": True, "level": "trusted", "proof_token": "...", "valid_until": "..."}

# Receiver side — verify the proof
is_valid = challenge.verify_proof(
    proof_token=proof["proof_token"],
    agent_id="agent://cyberhavox/havox-ai"
)
print(is_valid)  # True

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 — bool
  • result.agent_id, result.public_key, result.endpoint, result.capabilities
  • result.error — str or None

register(agent_id, domain, agent_json_url, registry_url?) → RegisterResult

Registers an agent with the Creduent registry.

  • result.success — bool
  • result.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 — bool
  • result.level"unverified" | "verified" | "trusted"
  • result.issued_at, result.expires_at
  • result.error — str or None

challenge.create_proof(agent_id, private_key_pem, registry_url?) → dict

Initiates a cryptographic challenge-response authentication flow to generate an identity verification proof.

  • Returns dict containing proof_token, verified status, level, valid_until timestamp, and issuer.

challenge.verify_proof(proof_token, agent_id, registry_url?) → bool

Decodes the proof token and verifies its authenticity using the registry's public key. Returns True if valid and not expired, False otherwise.


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.3.0 (Current)

  • Added Challenge-Response Authentication feature: challenge.create_proof and challenge.verify_proof.
  • Added dynamic public key query endpoint /registry/public-key to registry.
  • Added outbound SSRF-protected POST helper safe_requests_post.

v0.2.3

  • Refactored safe_requests_get to fetch the original URL directly with verify=True enabled for secure SSL verification.
  • Synced the SSRF safety request client between the Vercel registry server and Python SDK.

v0.2.2

  • Added custom headers support (User-Agent and Accept: application/json) to the registry's agent verification fetch requests.

v0.2.1

  • 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.get with safe_requests_get for 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

creduent-0.3.0.tar.gz (24.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

creduent-0.3.0-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file creduent-0.3.0.tar.gz.

File metadata

  • Download URL: creduent-0.3.0.tar.gz
  • Upload date:
  • Size: 24.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for creduent-0.3.0.tar.gz
Algorithm Hash digest
SHA256 2d8a2d7ce8c32045e863d7d5d45a8cdb3a4a50421a427f59bc7b1c9111c8292c
MD5 321d460e2449f85d2b55c60011b3e686
BLAKE2b-256 51ab6afd85c2569c9078b3899b8796194680fcd4da9cb1e69c9fa52e0283b854

See more details on using hashes here.

File details

Details for the file creduent-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: creduent-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 21.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for creduent-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 234084ce8da46a0ead8c16f3def4c4b6a229d544c6ea50ff51215c435c2685ab
MD5 f82060e58127d4c35c5c1c0e9af3c673
BLAKE2b-256 d5f4c2ccb0b4421ed7099b665782da3dc6ea9825c77d5e99624f84af4b5b394b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page