Aegis Ledger SDK
Tamper-evident audit logs for AI agents.
When autonomous agents take actions, their logs become verifiable audit evidence. Aegis hash-chains every tool call, signs it with Ed25519 or post-quantum signatures (ML-DSA-65, ML-DSA-87, SLH-DSA-128s, Hybrid), and stores it on the Internet Computer — where tampering is cryptographically detectable. Not by you, not your ops team, not the hosting provider — any modification breaks the hash chain.
pip install aegis-ledger-sdk
For MCP server support: pip install aegis-ledger-sdk[mcp]
For post-quantum signatures: pip install aegis-ledger-sdk[pq]
For everything: pip install aegis-ledger-sdk[all]
The Problem
Your AI agent just autonomously called a payment API, transferred $47,000, and the client says it wasn't authorized. Your logs are in CloudWatch. The client's lawyer asks: "Can you prove these logs haven't been edited since the incident?"
You can't. Aegis fixes this.
Quickstart
from aegis import AegisClient
# After: pip install aegis-ledger-sdk && aegis init
client = AegisClient.from_config()
@client.trace()
def call_stripe(amount: int, currency: str) -> dict:
return stripe.PaymentIntent.create(amount=amount, currency=currency)
# Every call is now tamper-evident logged:
# SHA-256(input) + SHA-256(output) + signature (Ed25519/PQ) + hash-chain link
Verify any entry — no authentication required:
aegis verify toqqq-lqaaa-aaaae-afc2a-cai act_a7f3b2c19e4d
# VERIFIED — chain hash valid, signature valid
Explicit Logging API
# Tool/API calls
client.log_tool_call("stripe.charge", input_data={"amount": 5000}, output_data={"id": "ch_xxx"}, duration_ms=340)
# Decisions with reasoning
client.log_decision("Selected cheapest shipping provider", confidence=0.92, input_data=options)
# Observations (sensor data, API responses)
client.log_observation(input_data=sensor_reading, output_data=parsed_result)
# Errors
client.log_error("payment.process", input_data=request, error=exc, duration_ms=120)
# Human overrides (EU AI Act Art. 14 compliance)
client.log_human_override("Manager approved exception", input_data=original, output_data=override)
# Batch import
client.log_batch([
{"tool": "search", "input_data": "query", "output_data": "results"},
{"tool": "summarize", "input_data": "results", "output_data": "summary"},
])
Span Grouping
Group related actions under a parent for structured traces:
with client.span("process_order", reasoning="Customer checkout flow") as span_id:
client.log_tool_call("inventory.check", ...)
client.log_tool_call("payment.charge", ...)
# Both calls have parent_action_id = span_id
Session Management
# Start a new session (resets sequence counter)
new_id = client.new_session()
# Use as context manager for automatic cleanup
with AegisClient(...) as client:
client.log_tool_call(...)
# Spill buffer drained on exit
KYA — Know Your Agent (Roadmap)
Note:
register_agent()andupdate_agent_profile()are currently available viaCanisterOpsonly. A convenience wrapper on the mainAegisClientis planned.
Register agent identity on-chain for transparent AI governance:
# Register an agent profile (via CanisterOps)
client.register_agent(
agent_id="agent-billing-v2",
name="Billing Agent",
description="Handles invoice generation and payment processing",
capabilities=["stripe.charge", "invoice.create", "refund.process"],
framework="langchain",
model_id="gpt-4o",
)
# Update an existing profile
client.update_agent_profile("agent-billing-v2", name="Billing Agent v3", model_id="gpt-4.1")
# Retrieve public agent facts (no auth required)
facts = client.get_agent_facts("agent-billing-v2")
Agent profiles are stored on-chain and publicly verifiable — any third party can inspect what an agent claims to do.
OpenTelemetry Correlation
Aegis entries can carry OpenTelemetry context for correlation with your existing observability stack:
# Auto-extracted from active OTel span (if opentelemetry SDK installed)
client.log_tool_call("search", input_data=q, output_data=r, duration_ms=50)
# → otel_trace_id, otel_span_id auto-populated
# Or pass explicitly
client.log_tool_call(
"search", input_data=q, output_data=r, duration_ms=50,
otel_trace_id="abc123", otel_span_id="def456",
cost_usd=0.003, token_count=1500,
)
Framework Integrations
LangChain
from aegis.langchain import AegisCallbackHandler
handler = AegisCallbackHandler(client)
agent.invoke({"input": "Process refund"}, config={"callbacks": [handler]})
CrewAI
from aegis.crewai import AegisCrewCallback
callback = AegisCrewCallback(client)
crew = Crew(agents=[...], tasks=[...], step_callback=callback)
OpenAI Agents SDK
from aegis.openai_agents import AegisAgentTracer
tracer = AegisAgentTracer(client)
with tracer.trace() as tid:
result = await Runner.run(agent, "Process this request")
AutoGen / AG2
from aegis.autogen import AegisAutoGenHook
hook = AegisAutoGenHook(client)
hook.on_tool_call("search", arguments={"q": "test"}, caller="assistant")
hook.on_tool_result("search", result="found 5 items", caller="assistant")
Anthropic Agent SDK
from aegis.anthropic_sdk import AegisAnthropicTracer
tracer = AegisAnthropicTracer(client)
tracer.on_tool_use("search", tool_input={"q": "test"}, tool_response="5 results")
tracer.on_session_start("session_123")
tracer.on_subagent_start("sub_1", "researcher")
MCP (Model Context Protocol)
pip install aegis-ledger-sdk[mcp]
aegis-mcp # starts MCP server (stdio transport)
Any MCP-compatible agent can log actions to the tamper-evident ledger via MCP tools.
Async & Batch Support
# Async functions work directly with @trace
@client.trace()
async def fetch_data(url: str) -> dict:
async with aiohttp.ClientSession() as session:
resp = await session.get(url)
return await resp.json()
Post-Quantum Signatures
Five signature algorithms with crypto-agility:
| Algorithm | Type | Key Size | Use Case |
|---|---|---|---|
| Ed25519 | Classical | 32 B | Default, fast |
| ML-DSA-65 | Post-Quantum (FIPS 204) | 1952 B | PQ Level 3 |
| ML-DSA-87 | Post-Quantum (FIPS 204) | 2592 B | CNSA 2.0 Level 5 |
| SLH-DSA-128s | Hash-based (FIPS 205) | 32 B | Conservative PQ fallback |
| Hybrid | Ed25519 + ML-DSA-65 | 1984 B | Best of both worlds |
# Generate PQ keys
# aegis keygen ./key.mldsa65 --algorithm ml-dsa-65
# aegis keygen ./key --algorithm hybrid
client = AegisClient(
...,
signature_scheme="hybrid",
signing_key_path="./key.mldsa65",
)
Configure via ~/.aegis/config.toml:
[signing]
default_scheme = "hybrid"
signing_key_path = "~/.aegis/keys/agent.mldsa65"
PII Protection
PII is automatically detected and redacted before transmission (enabled by default):
client = AegisClient(..., redact_pii=True) # default
# Detected patterns: email, phone, IP, SSN, AHV (Swiss), credit cards
# PII is replaced with sha256:<128-bit hash> — verifiable but not reversible
CLI
# Setup & diagnostics
aegis init # Interactive setup wizard
aegis test # Send test entry + verify on-chain
aegis doctor # Check SDK health (config, keys, canister)
aegis version # Print SDK version
# Key generation
aegis keygen ./key.pem # Generate Ed25519 keypair
aegis keygen ./key.mldsa65 --algorithm ml-dsa-65 # Generate ML-DSA-65 keypair
aegis keygen ./key --algorithm hybrid # Generate Hybrid keypair
# Verification
aegis verify <canister_id> <action_id> # Verify single entry
aegis verify-chain <canister_id> <session_id> # Verify full session chain
# Canister queries
aegis status <canister_id> # Canister health + chain stats
aegis list-sessions <canister_id> # List your sessions
aegis session-analytics <session_id> # Error rate, duration, action types
aegis org-stats <canister_id> # Aggregated org statistics
aegis spill-status # Show pending offline buffer
# Compliance reports
aegis report <canister_id> --format eu-ai-act # EU AI Act Art. 12
aegis report <canister_id> --format all -o ./reports/ # All formats
# Key management (self-service)
aegis register-key <id> --key-file <f> # Register new API key
aegis revoke <key_id> # Revoke key (confirmation required)
aegis reactivate-key <key_id> # Reactivate revoked key
aegis delete-key <key_id> # Permanently delete revoked key
aegis update-key-desc <key_id> <desc> # Update key description
# Migration
aegis migrate <canister_id> <session_id> --to hybrid # Re-sign with new algorithm
aegis purge-session <session_id> # Purge session entries (owner/admin)
How It Works
Your Agent Aegis SDK ICP Canister
| | |
|-- call_stripe(500, "usd") ->| |
| |-- SHA-256(input) |
| |-- SHA-256(output) |
| |-- sign (Ed25519/PQ) ------->|
| | verify signature
| | check sequence
| | chain_hash = SHA-256(
| | prev_hash + payload
| | )
| | store in append-only ledger
| |<-- action_id ---------------|
|<-- return result -----------| |
Fail-open: if canister unreachable, entries buffer locally (~/.aegis/spill/) and retry.
What Gets Logged
| Field | Description |
|---|---|
input_hash |
SHA-256 of full input (raw data never stored on-chain) |
output_hash |
SHA-256 of full output |
tool |
Tool/API name |
duration_ms |
Wall-clock execution time |
chain_hash |
SHA-256 linking to previous entry |
payload_signature |
Cryptographic signature (Ed25519, ML-DSA-65, ML-DSA-87, SLH-DSA-128s, or Hybrid) |
sequence_number |
Monotonic counter (gap detection) |
otel_trace_id |
OpenTelemetry trace ID (optional, for correlation) |
otel_span_id |
OpenTelemetry span ID (optional) |
cost_usd |
LLM call cost in USD (optional) |
token_count |
Token usage (optional) |
What does NOT get logged: Raw payloads, API keys, secrets, PII. Only hashes — you control your data.
Compliance
Generate verifiable compliance reports:
from aegis.report import generate_report, generate_pdf, ReportFormat
report = generate_report("toqqq-...", format=ReportFormat.EU_AI_ACT, stats=stats, health=health)
generate_pdf(report, "compliance-report.pdf")
Supported frameworks: EU AI Act Art. 12, ISO/IEC 42001, AIUC-1 (insurance underwriting).
Links
Normal logging = trust the system. Aegis = verify the record.
License
MIT
Metadata
Release files for aegis-ledger-sdk 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aegis_ledger_sdk-0.5.0.tar.gz | 152.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aegis_ledger_sdk-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 327.9 kB
Release files / aegis_ledger_sdk-0.5.0.tar.gz
| Download URL | aegis_ledger_sdk-0.5.0.tar.gz |
|---|---|
| Size | 152.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26addb6c23da92850d991bcbb420e31ea2b5808c4bb9e03692a7b4bb1a78ffce
|
|
BLAKE2b-256 checksum How to use checksums |
b9051d3b685735b7527be68b20bc50fe81d01a0f9fbe3547476b75c8faf36d53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / aegis_ledger_sdk-0.5.0-py3-none-any.whl
| Download URL | aegis_ledger_sdk-0.5.0-py3-none-any.whl |
|---|---|
| Size | 175.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
133108dfe1f28ecd898dc937d33de5f129bf8739a84646bd085bacd724a31140
|
|
BLAKE2b-256 checksum How to use checksums |
fa332721079337036e58ccc681d5d36058f021a58fc6ea18d72a5041d7868b11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|