DEV Community

Cover image for How I built cryptographic audit trails for AI agents (and why it matters)
David Okeke
David Okeke

Posted on

How I built cryptographic audit trails for AI agents (and why it matters)

Every company is deploying AI agents. Nobody knows what those agents are actually doing.

An autonomous agent can read your emails, call your Stripe API, export your database, and send messages — all without a human in the loop. When something goes wrong, there's no proof of what happened, no way to prove authorization, and no compliance trail.
I built MandateZ to solve this. Here's how it works technically.
The core problem
Traditional software has clear audit trails. An AI agent doesn't. When a LangChain agent calls send_email(), nothing records: who authorized it, which policy allowed it, what the payload was, or whether a human approved it. That's fine for demos. It's a blocker for any enterprise deployment.
The architecture
Everything flows from one data structure — the AgentEvent:

interface AgentEvent {
  event_id: string;        // uuid v4
  agent_id: string;        // ag_ prefix + nanoid
  owner_id: string;        
  timestamp: string;       // ISO 8601
  action_type: 'read' | 'write' | 'export' | 'delete' | 'call' | 'payment';
  resource: string;        // e.g. "emails", "api/stripe"
  outcome: 'allowed' | 'blocked' | 'flagged' | 'pending_approval';
  policy_id: string | null;
  metadata: Record<string, unknown>;
  signature: string;       // Ed25519 signature
  public_key: string;      // agent's public key
}
Enter fullscreen mode Exit fullscreen mode

Every agent action produces one of these. Every event is Ed25519 signed — cryptographically proving which agent produced it and that it hasn't been tampered with.
Agent identity
Each agent gets a unique Ed25519 keypair on registration:

import { generateAgentIdentity, MandateZClient } from '@mandatez/sdk';

const agent = await generateAgentIdentity();
// { agent_id: 'ag_abc123', public_key: '...', private_key: '...' }

const client = new MandateZClient({
  agentId: agent.agent_id,
  ownerId: 'your_owner_id',
  privateKey: agent.private_key,
  supabaseUrl: process.env.SUPABASE_URL,
  supabaseAnonKey: process.env.SUPABASE_ANON_KEY,
});
Enter fullscreen mode Exit fullscreen mode

Tracking events

await client.track({
  action_type: 'call',
  resource: 'api/stripe',
  metadata: { amount: 9900, currency: 'usd' }
});
Enter fullscreen mode Exit fullscreen mode

Under the hood this: generates an event ID, timestamps it, canonicalizes the payload (keys sorted alphabetically), signs it with the agent's private key using Ed25519, and inserts it into Supabase. The whole thing takes ~5ms.
Policy enforcement

const result = await client.track({
  action_type: 'export',
  resource: 'database/users',
});
// outcome: 'blocked' — policy rule matched, action never executed
Enter fullscreen mode Exit fullscreen mode

Policies are JSON rules stored per owner. The engine evaluates them before the action executes. Blocked actions are logged with the matched rule ID.
Human oversight gate
For high-risk actions:

const oversight = {
  require_human_approval: ['export', 'delete', 'payment'],
  alert_channel: 'slack',
  timeout_seconds: 300,
  timeout_action: 'block'
}
Enter fullscreen mode Exit fullscreen mode

The agent pauses execution, fires a Slack alert, and waits for human approval. If no response in 5 minutes — auto-blocked and logged.
Why Ed25519 specifically
RSA and ECDSA are too slow for high-frequency agent event signing. Ed25519 signatures are 64 bytes, verification is ~0.05ms, and the keys are small enough to store as base64 strings without bloating your database. libsodium-wrappers handles all of this with a clean API.
The neutrality moat
MandateZ works with LangChain, n8n, AutoGen, CrewAI, and every other framework simultaneously. OpenAI, Anthropic, and Nvidia all have security layers — but only for their own agents. MandateZ is the only layer that works across all vendors without a conflict of interest.
Try it

npm install @mandatez/sdk
Enter fullscreen mode Exit fullscreen mode

Docs: mandatez.mintlify.app
GitHub: github.com/mandatez/core

Top comments (1)

Collapse
 
micelclaw profile image
Victor García

The Ed25519 signing per event is a great insight. We've been building audit trails for agent routing decisions and the cryptographic integrity piece is exactly what's missing from most implementations — including ours. A SQL log answers "what happened" but not "has this log been tampered with." Signing each event at ~5ms overhead makes that a non-tradeoff. Good stuff.