This content originally appeared on DEV Community and was authored by David Okeke
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
}
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,
});
Tracking events
await client.track({
action_type: 'call',
resource: 'api/stripe',
metadata: { amount: 9900, currency: 'usd' }
});
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
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'
}
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
Docs: mandatez.mintlify.app
GitHub: github.com/mandatez/core
This content originally appeared on DEV Community and was authored by David Okeke