Skip to main content
Attesta provides two built-in exporters for converting audit trail entries into standard formats: CSVExporter for spreadsheet-compatible output and JSONExporter for structured data interchange. Both implement the AuditExporter protocol and can be used interchangeably.

AuditExporter Protocol

The base protocol that all exporters implement.

Import

from attesta.exporters import AuditExporter

Signature

@runtime_checkable
class AuditExporter(Protocol):
    def export(self, entries: list[AuditEntry], output: IO[str]) -> None: ...
ParameterTypeDescription
entrieslist[AuditEntry]List of audit entries to export.
outputIO[str]A writable file-like object (e.g., open() result, StringIO).

CSVExporter

Export audit entries as CSV. Nested dict fields (like metadata) are JSON-serialized.

Import

from attesta.exporters import CSVExporter

Constructor

exporter = CSVExporter(columns=None)
ParameterTypeDefaultDescription
columnslist[str] | NoneNoneList of field names to include as columns. Defaults to DEFAULT_COLUMNS.

Default Columns

When no custom columns are provided, the following fields are exported:
ColumnDescription
entry_idUnique identifier for the audit entry.
intercepted_atTimestamp when the action was intercepted.
action_nameName of the gated function.
risk_scoreNumeric risk score (0.0 - 1.0).
risk_levelDiscrete risk level (low, medium, high, critical).
challenge_typeType of challenge presented.
verdictApproval outcome (approved, denied, etc.).
agent_idIdentifier of the AI agent.
review_duration_secondsTime the operator spent reviewing.
chain_hashSHA-256 hash for tamper detection.

Example

from attesta.core.audit import AuditLogger
from attesta.exporters import CSVExporter

audit = AuditLogger(path=".attesta/audit.jsonl")
entries = audit.query(verdict="approved")

# Export to file
with open("report.csv", "w") as f:
    CSVExporter().export(entries, f)

# Export with custom columns
with open("summary.csv", "w") as f:
    CSVExporter(columns=["entry_id", "action_name", "verdict"]).export(entries, f)

JSONExporter

Export audit entries as a JSON array. Supports pretty-printing with configurable indentation.

Import

from attesta.exporters import JSONExporter

Constructor

exporter = JSONExporter(indent=2)
ParameterTypeDefaultDescription
indentint | None2Number of spaces for pretty-printing. None for compact single-line output.

Example

from attesta.core.audit import AuditLogger
from attesta.exporters import JSONExporter

audit = AuditLogger(path=".attesta/audit.jsonl")
entries = audit.query(risk_level="critical")

# Pretty-printed JSON
with open("critical-actions.json", "w") as f:
    JSONExporter().export(entries, f)

# Compact JSON (no indentation)
with open("compact.json", "w") as f:
    JSONExporter(indent=None).export(entries, f)

Custom Exporters

You can implement the AuditExporter protocol to create custom exporters:
from attesta.exporters import AuditExporter
from attesta.core.audit import AuditEntry
from typing import IO

class MarkdownExporter:
    """Export audit entries as a Markdown table."""

    def export(self, entries: list[AuditEntry], output: IO[str]) -> None:
        output.write("| Action | Risk | Verdict |\n")
        output.write("|--------|------|---------|\n")
        for entry in entries:
            d = entry.to_dict()
            output.write(f"| {d['action_name']} | {d['risk_level']} | {d['verdict']} |\n")

# Duck typing -- no inheritance required
assert isinstance(MarkdownExporter(), AuditExporter)

Audit Trail

How audit entries are created and stored

CLI Audit

Export and verify audit logs from the command line