Python SDK for the Elydora tamper-evident audit platform
Project description
Elydora Python SDK
Official Python SDK for the Elydora tamper-evident audit platform. Build cryptographically verifiable audit trails for AI agent operations.
Installation
pip install elydora
Requires Python 3.9+.
Quick Start
from elydora import ElydoraClient
# Authenticate
auth = ElydoraClient.login("https://api.elydora.com", "user@example.com", "password")
# Create client
client = ElydoraClient(
org_id=auth["user"]["org_id"],
agent_id="my-agent-id",
private_key="<base64url-encoded-ed25519-seed>",
base_url="https://api.elydora.com",
token=auth["token"],
)
# Create and submit an operation
eor = client.create_operation(
operation_type="data.access",
subject={"user_id": "u-123", "resource": "patient-record"},
action={"type": "read", "scope": "full"},
payload={"record_id": "rec-456"},
)
response = client.submit_operation(eor)
print("Receipt:", response["receipt"]["receipt_id"])
Async Support
from elydora import AsyncElydoraClient
async def main():
client = AsyncElydoraClient(
org_id="org-123",
agent_id="agent-456",
private_key="<base64url-encoded-ed25519-seed>",
token="<jwt-token>",
)
eor = client.create_operation(
operation_type="inference",
subject={"model": "gpt-4"},
action={"type": "completion"},
)
response = await client.submit_operation(eor)
await client.close()
CLI
The SDK includes a CLI for installing audit hooks into AI coding agents.
elydora install \
--agent claudecode \
--org_id org-123 \
--agent_id agent-456 \
--private_key <key> \
--kid agent-456-key-v1
Commands
| Command | Description |
|---|---|
elydora install |
Install Elydora audit hook for a coding agent |
elydora uninstall |
Remove Elydora audit hook for a coding agent |
elydora status |
Show installation status for all agents |
elydora agents |
List supported coding agents |
Supported Agents
| Agent | Key |
|---|---|
| Claude Code | claudecode |
| Copilot CLI | copilot |
| Cursor | cursor |
| Gemini CLI | gemini |
| Kiro CLI | kirocli |
| Kiro IDE | kiroide |
| Letta Code | letta |
| OpenCode | opencode |
API Reference
Configuration
client = ElydoraClient(
org_id="org-123", # Organization ID
agent_id="agent-456", # Agent ID
private_key="<seed>", # Base64url-encoded Ed25519 seed
base_url="https://...", # API base URL (default: https://api.elydora.com)
ttl_ms=30000, # Operation TTL in ms (default: 30000)
max_retries=3, # Max retries on transient failures (default: 3)
token="<jwt>", # Optional JWT bearer token
)
Authentication
# Register a new user and organization
reg = ElydoraClient.register(base_url, email, password, display_name=None, org_name=None)
# Login and receive a JWT
auth = ElydoraClient.login(base_url, email, password)
# Get current authenticated user profile
me = client.get_me()
# Issue a new API token (with optional TTL in seconds)
token_resp = client.issue_token(ttl_seconds=3600)
Operations
# Create a signed EOR locally (no network call)
eor = client.create_operation(
operation_type="inference",
subject={"model": "gpt-4"},
action={"type": "completion"},
payload={"prompt": "Hello"},
)
# Submit to API
response = client.submit_operation(eor)
# Retrieve an operation
op = client.get_operation(operation_id)
# Verify integrity
result = client.verify_operation(operation_id)
Agent Management
# Register a new agent
agent = client.register_agent({
"agent_id": "my-agent",
"display_name": "My Agent",
"responsible_entity": "team@example.com",
"keys": [{"kid": "key-v1", "public_key": "<base64url>", "algorithm": "ed25519"}],
})
# Get agent details
details = client.get_agent(agent_id)
# Freeze an agent
client.freeze_agent(agent_id, reason="security review")
# Revoke a key
client.revoke_key(agent_id, kid, reason="key rotation")
# List all agents in the organization
agents_resp = client.list_agents()
# Unfreeze a previously frozen agent
client.unfreeze_agent(agent_id, reason="review complete")
# Delete an agent permanently
deleted_resp = client.delete_agent(agent_id)
Audit
import time
results = client.query_audit(
agent_id="agent-123",
operation_type="inference",
start_time=int(time.time() * 1000) - 86400000,
end_time=int(time.time() * 1000),
limit=50,
)
Epochs
epochs = client.list_epochs()
epoch = client.get_epoch(epoch_id)
Exports
export = client.create_export(
start_time=start,
end_time=end,
format="json",
)
exports = client.list_exports()
detail = client.get_export(export_id)
# Download export file data
data = client.download_export(export_id)
JWKS
jwks = client.get_jwks()
Health
# Check API health (no authentication required)
health = client.health()
# health["status"], health["version"], health["protocol_version"], health["timestamp"]
Crypto Functions
The SDK exports low-level cryptographic primitives for advanced use:
from elydora import (
jcs_canonicalize, # RFC 8785 JSON Canonicalization
sha256_base64url, # SHA-256 hash as base64url
compute_chain_hash, # Chain hash computation
compute_payload_hash, # Payload hash (SHA-256 of JCS-canonicalized payload)
sign_ed25519, # Ed25519 signing
sign_eor, # Sign an EOR dict
get_public_key_base64url, # Derive public key from private seed
)
Utility Functions
from elydora import (
base64url_encode, # Encode bytes to base64url (no padding)
base64url_decode, # Decode base64url string to bytes
generate_nonce, # Generate 16-byte random nonce (base64url)
generate_uuidv7, # Generate UUIDv7 (time-ordered, RFC 9562)
)
Type Definitions
All types are TypedDict classes for structural typing:
from elydora import (
# Protocol types
EOR, # Elydora Operation Record
EAR, # Elydora Acknowledgment Receipt
# Entity types
Agent, AgentKey, Operation, Receipt, Epoch, Export, Organization, User,
# API response types
RegisterAgentResponse, GetAgentResponse, ListAgentsResponse,
DeleteAgentResponse, SubmitOperationResponse, GetOperationResponse,
VerifyOperationResponse, AuditQueryResponse, GetEpochResponse,
ListEpochsResponse, CreateExportResponse, GetExportResponse,
ListExportsResponse, JWKSResponse, AuthRegisterResponse,
AuthLoginResponse, GetMeResponse, IssueTokenResponse, HealthResponse,
# Request types
RegisterAgentRequest,
)
Error Handling
from elydora import ElydoraError
try:
client.submit_operation(eor)
except ElydoraError as e:
print(e.code) # e.g. "INVALID_SIGNATURE"
print(e.message) # Human-readable message
print(e.status_code) # HTTP status code
print(e.request_id) # Request ID for support
Dependencies
- requests - Sync HTTP client
- aiohttp - Async HTTP client
- cryptography - Ed25519 signing
License
MIT
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 elydora-1.1.0.tar.gz.
File metadata
- Download URL: elydora-1.1.0.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01248882ea19fdaf45f03e32583f548f050e544f676242c99f50c6957668c4b6
|
|
| MD5 |
b9159eca2a07ace8283947a972f849fd
|
|
| BLAKE2b-256 |
9e37be7fba8548207be7e1768ddd0a816a5bcb67047be28450a70ef54350d277
|
File details
Details for the file elydora-1.1.0-py3-none-any.whl.
File metadata
- Download URL: elydora-1.1.0-py3-none-any.whl
- Upload date:
- Size: 44.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f02c8588a905be1c87dc54c09b299449dffa708e30c7f962b1126182d58fc4d1
|
|
| MD5 |
9e7ae6fa23a68fca0a75df684f949615
|
|
| BLAKE2b-256 |
e772bb6a8f758b5ca7080b78b0b3f25bf09f11d659647cae1b89ed53d290bb39
|