The Audit Trail is the system of record for everything an agent does. It is append-only, cryptographically hashed, and periodically anchored to Solana — meaning records cannot be altered, deleted, or forged after the fact without detection.
Event model
Every interaction produces an audit event:
{
"event_id": "trade-2234146-d41d57ed",
"agent_id": "agent_b1c59d23...",
"event_type": "trade.executed",
"payload": {
"exchange": "binance-testnet",
"symbol": "BTCUSDT",
"side": "BUY",
"price": "80947.93",
"amount_usd": "49.38",
"btc_qty": "0.00061",
"order_id": "12345",
"authorization_jti": "848373a9-a016-46..."
}
}Standard event types include:
agent.registered,agent.revokedmandate.created,mandate.activated,mandate.revokedpayment.authorized,payment.rejectedtrade.executed,trade.rejected(or any application-specific events emitted by the agent)kyc.completed
Applications are free to emit additional event types; the protocol stores them all as part of the agent’s tamper-evident timeline.
The four-stage pipeline
Each stage updates the event’s status field:
| Status | Meaning |
|---|---|
received | Event ingested, payload hashed, stored in PostgreSQL |
batched | Event included in a sealed Merkle batch, batch ID assigned |
anchored | Batch root written to Solana, solana_tx recorded |
The Merkle-batching is what makes anchoring economical: hundreds of events share a single on-chain transaction (and its fee) while each one retains its own cryptographic proof of inclusion.
Proof of inclusion
Once batched, every event has a Merkle proof — a small list of sibling hashes that lets anyone verify “this event is in this batch” without downloading the whole batch.
The proof is returned by the API:
{
"event_id": "trade-2234146-d41d57ed",
"payload_hash": "0x44d926713d6d15...",
"batch_id": "78422d51-6248-...",
"merkle_index": 14,
"merkle_proof": ["0xabc...", "0xdef...", "..."],
"anchored_at": "2026-05-11T14:27:05Z"
}To verify off-chain:
- Pull the batch root from Solana via the
AuditAnchorprogram - Hash the event payload (canonical JSON) → get
payload_hash - Walk up the Merkle tree using the proof
- Confirm the resulting root matches the on-chain value
If steps 1–4 produce a match, the event is provably part of that batch and was not altered after anchoring.
Why this design
| Goal | How the design supports it |
|---|---|
| Immutability | Once anchored, modifying an event would change the Merkle root, which is fixed on Solana |
| Compactness | One Solana TX per batch (hundreds of events), not per event |
| Verifiability | Anyone with the batch root + proof can audit a single event without trusting Regent |
| Performance | Ingestion is async; the agent’s /audit call returns in <50ms even when the chain is slow |
What gets logged
The protocol enforces audit-event ingestion at every protocol boundary. Specifically, every:
- Agent registration and revocation
- Mandate authorize call — approved or rejected
- Mandate creation, suspension, revocation
- KYC milestone (submission, approval, DID issuance)
The agent itself is also expected to emit audit events for its own actions — trade fills, contract calls, payments, etc. The SDK’s ingest_event() method takes a single async call.