Skip to main content

Decision Trail — Inference Audit Log

Every inference decision your agent makes is logged — which model, what query, which facts were retrieved (with similarity scores), what the model output, how many tokens were used, and how long it took.

Each record gets a BLAKE2b-128 content-addressed ID and an optional Ed25519 signature for tamper-proof provenance.

Decision record schema

FieldTypeDescription
decision_idstringBLAKE2b-128 hex digest (deterministic)
tenant_idstringTenant that owns the decision
store_idstringMemory store queried
session_idstringSession identifier (optional)
model_idstringLLM model used (e.g. gpt-4o)
querystringThe user's query
retrieved_refsint[]Memory fact refs that were retrieved
retrieved_contentsstring[]Content of each retrieved fact
retrieved_scoresfloat[]Similarity scores
outputstringModel's generated output
token_countintTokens consumed
latency_msfloatEnd-to-end latency in milliseconds
timestampdatetimeISO-8601 with microsecond precision
signaturebytesEd25519 signature (optional)
public_keybytesSigner's public key (optional)

Provenance

The decision_id is computed deterministically:

decision_id = BLAKE2b-128(tenant_id ‖ store_id ‖ model_id ‖ query ‖ timestamp)

When a signing key is configured, the decision is Ed25519-signed over the ID. This creates an immutable, verifiable chain of inference evidence.

API reference

POST /v1/decisions/log

Log a new decision record.

curl -X POST https://cloud.grafomem.com/v1/decisions/log \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"store_id": "default",
"model_id": "gpt-4o",
"query": "Where does Aria live?",
"retrieved_refs": [42, 87],
"retrieved_contents": ["Aria lives in Rome", "Aria works at ACME"],
"retrieved_scores": [0.95, 0.72],
"output": "Based on the memory, Aria lives in Rome.",
"token_count": 145,
"latency_ms": 230.5
}'

GET /v1/decisions/

List decisions with pagination and filtering.

ParameterTypeDescription
model_idstringFilter by model
store_idstringFilter by store
session_idstringFilter by session
limitintPage size (default 20, max 200)
offsetintPagination offset

GET /v1/decisions/stats

Summary statistics: total decisions, models used, average latency, total tokens.

GET /v1/decisions/{decision_id}

Get a single decision record by ID.

GET /v1/decisions/{decision_id}/replay

Replay a decision — returns which facts have been deleted since the decision was made.

{
"decision": { ... },
"facts_since_deleted": [42]
}
Why replay matters

The replay endpoint is critical for GDPR audit trails. It answers: "If this decision were made today, would it have the same inputs?" If facts have been deleted since, the answer is no — and the erasure certificate proves the deletion.

GET /v1/decisions/export

Bulk export all decisions as NDJSON (newline-delimited JSON). Opens as a file download.

DELETE /v1/decisions/scrub/{fact_ref}

GDPR scrub — removes all references to a deleted fact from decision records. Content is replaced with [REDACTED — GDPR Article 17].

Portal UI

The Decision Trail tab in the Cloud Portal provides:

  • Stats grid — total decisions, models used, avg latency, total tokens
  • Filter bar — search by model, store, session
  • Decision table — paginated list with time, model, query preview, facts count, tokens, latency, signed status
  • Detail panel — click any row to see full query, retrieved facts with scores, model output
  • Provenance badge — green badge showing Ed25519 signature + public key
  • Replay — see which facts have been deleted since the decision
  • NDJSON export — one-click bulk download