Audit log

Tamper-evident record of every tool call. Hash-chained for retroactive-edit detection.

Every tenet.execute() call lands as a row in the audit log, whether the outcome was ALLOW, ESCALATE, or BLOCK. The log is hash-chained so retroactive edits to historical decisions are detectable.

What gets recorded

For every decision:

  • decision_id and timestamp
  • agent_id: which agent made the call
  • tool_name and tool_arguments: what the agent was trying to do
  • outcome: ALLOW, ALLOW_WITH_CONDITIONS, ESCALATE, or BLOCK
  • policy_bundle_id and policy_version: which policy was evaluated
  • reason_codes: which rules matched, including which trust layer decided (SERVICE_LOCKED, SERVICE_TRUSTED, FUNCTION_OVERRIDE_*) and, for services in dry-run, EVALUATE_MODE plus a WOULD_* preview of what would have happened
  • explanations: engine-generated explanation strings
  • context and signals: the request metadata and computed signal scores
  • prev_hash, record_hash, inputs_hash: integrity hashes (see below)

What's NOT recorded:

  • The downstream response body (would balloon log size + risk leaking PII into the audit log).
  • Your downstream API keys (they're injected server-side and never serialized into the audit).
  • Customer-supplied secrets in arguments if they match the PII redaction patterns.

Browsing the log

The Audit log page in the dashboard (/decisions) shows recent decisions with filter chips for outcome (ALLOW / BLOCK / ESCALATE). Click a row to expand and see reason codes, full tool arguments, and the decision ID.

For programmatic access, GET /v1/decisions returns paginated decision rows. It supports filters via query params: outcome, tool, agent, from, and to.

The hash chain

Each decision row carries three hashes:

  • inputs_hash: SHA-256 of the request (tool name + arguments + context).
  • record_hash: SHA-256 of the entire decision row (after the outcome is determined).
  • prev_hash: the record_hash of the immediately-prior decision row for this tenant.

The chain links every decision to the one before it. The first decision (per tenant) chains to a genesis hash sha256:0000....

To verify integrity, recompute each record_hash from the row contents and check that each row's prev_hash matches the previous row's record_hash. If anything's been edited retroactively, the chain breaks at the edit point.

This isn't blockchain-grade tamper resistance (we don't replicate to external chains); it's audit-grade. A motivated attacker with DB write access could rewrite the chain. A casual edit to "fix" a decision retroactively can't.

Retention

  • Free plan: 14 days of queryable history.
  • Tenet Pro ($29/mo): 90 days of queryable history.

Querying

The audit log is queryable through GET /v1/decisions, which supports filters for outcome, tool, agent, and a from/to time range, and through the Audit log page in the dashboard. Direct SQL access to the audit log is not available.

EU AI Act / GDPR

The audit log is designed to satisfy the operational logging requirements of the EU AI Act (Article 12) and GDPR's accountability principle (Article 5(2)). What we record + tamper-evidence + retention are the building blocks.

This isn't legal advice. If you're operating under a regulatory framework that requires specific audit characteristics, work with your legal counsel to confirm what your framework requires, and check it against what Tenet records.

What's next