Audit Logs
Audit logs are an immutable, time-stamped record of every action the agent took, including who requested it, what was done, and what the result was.
8 min•By Priygop Team•Updated 2026
Audit Log Requirements
- Completeness: log every action — both allowed and blocked
- Immutability: audit logs must not be editable or deletable by the agent
- Tamper-evident: use hash chaining or append-only storage so deletions are detectable
- Timestamp accuracy: use UTC timestamps from a trusted time source
- No secrets: never log API keys, passwords, or personal data beyond what is needed
- Retention: define how long logs are kept based on legal and compliance requirements
Audit Log Implementation
Audit Log Implementation
import json
import hashlib
from datetime import datetime, timezone
class AuditLogger:
"""Append-only audit logger with hash chaining for tamper detection."""
def __init__(self):
self.log = []
self._last_hash = "GENESIS" # Starting hash
def _compute_hash(self, entry: dict) -> str:
"""Hash this entry combined with the previous entry's hash."""
content = json.dumps(entry, sort_keys=True, default=str)
return hashlib.sha256(f"{self._last_hash}:{content}".encode()).hexdigest()[:16]
def log_action(
self,
event_type: str, # "tool_call", "decision", "approval", "block"
agent_id: str,
user_id: str,
action: str,
details: dict,
outcome: str, # "success", "blocked", "error", "requires_approval"
) -> dict:
# Redact any sensitive fields
safe_details = {
k: "***" if any(s in k.lower() for s in ("key", "password", "token", "secret"))
else v
for k, v in details.items()
}
entry = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"event_type": event_type,
"agent_id": agent_id,
"user_id": user_id,
"action": action,
"details": safe_details,
"outcome": outcome,
}
entry["hash"] = self._compute_hash(entry)
entry["prev_hash"] = self._last_hash
self._last_hash = entry["hash"]
self.log.append(entry)
return entry
def verify_integrity(self) -> bool:
"""Check that no log entries have been tampered with."""
prev = "GENESIS"
for entry in self.log:
expected_hash = entry.get("prev_hash")
if expected_hash != prev:
return False
prev = entry["hash"]
return True
logger = AuditLogger()
e1 = logger.log_action("tool_call", "agent-1", "user-1",
"issue_refund", {"amount": 49.99, "api_key": "sk-secret"}, "success")
e2 = logger.log_action("block", "agent-1", "user-1",
"delete_record", {"id": "X"}, "blocked")
print(f"Log entries: {len(logger.log)}")
print(f"Integrity check: {logger.verify_integrity()}")
print(f"Secret redacted: {e1['details']}")Key Takeaways
- Audit logs are an immutable, time-stamped record of every action the agent took, including who requested it, what was done, and what the result was.
- Completeness: log every action — both allowed and blocked
- Immutability: audit logs must not be editable or deletable by the agent
- Tamper-evident: use hash chaining or append-only storage so deletions are detectable