AERDocumentation

Guide

Content commitments

Prove what a prompt or response was without AER ever seeing it. With a key only you hold, the collector signs one-way commitments to the content it observes into the record; later you open them offline against your own retained plaintext.

The problem this solves

Bodies-off capture is the right default: AER never records prompts or responses. But some disputes need exactly that evidence: prove the agent was sent this prompt, prove the model returned that answer. Commitments square the circle: the signed record contains an HMAC tag over the content, computed under a customer-held key. AER holds neither the key nor the plaintext, so it can neither read nor brute-force the content; you, holding both, can prove byte-exact correspondence offline.

Turn it on

export AER_COMMITMENT_KEY=…   # at least 32 bytes; 64-hex recommended

With the key set, the collector commits to each LLM request it observes: the canonicalised prompt (prompt_canon_tag, stable across providers, so the same logical prompt to OpenAI or Anthropic yields the same tag), the assembled response text (response_tag, streaming or not), the full wire body including sampling parameters (wire_canon_tag) and each tool call’s arguments and fed-back results (tool_args_tag, tool_result_tags). Every tag carries a non-secret key id so keys can rotate. Without a key, no commitments are emitted; there is deliberately no bare-hash fallback, which would be a low-entropy oracle.

Open a commitment offline

AER_COMMITMENT_KEY=<64-hex> aer commitments verify \
  --requests requests.json --aer <aer-id>
# exit 0 iff every request opened; the key never leaves your machine

The CLI recanonicalises your retained requests under your key and diffs the recomputed tags against the signed bundle. Output is tags and booleans only, never plaintext. The canonicalisation (aer-canon.v1) is versioned and exported from the collector package, so any party you disclose the key and plaintext to can re-verify independently.

Failure posture

The whole path is best-effort and fail-open: a fault in commitment computation degrades to a name-only event and never breaks the host SDK call. A prompt with no matching completion is recorded as aborted rather than silently dropped.