Skip to main content
AI runs act on the real world β€” they spend money, read secrets, write files, call tools. Most of them leave nothing behind that a reviewer can trust: a chat log is editable, a dashboard is a vendor’s word, a green CI tick says only that something exited zero. Run receipts is the pattern that fixes this, and it is deliberately not a product: any pipeline, framework or runtime can implement it.

The pattern

A run deserves two documents, one on each side of the execution:
1

Before β€” a reviewable contract

A static, diffable statement of what the run would do: the task graph and its order, which models and secrets it needs, what it may read, write and reach on the network, and an honest cost bound β€” a ceiling when priceable, an explicit unknown when not (never a silent $0). A human can approve it in review; a machine can gate on it in CI. Nothing has executed yet.
2

During β€” bounded execution

The runtime enforces the contract instead of trusting the prose: effects outside the declared boundary fail, spend past the bound stops the run. The contract is load-bearing, not documentation.
3

After β€” a verifiable record

An append-only journal of what actually happened: every task’s settle, output digest, spend and timing, each entry carrying a hash of the previous one. Anyone holding the file can recompute the chain and detect tampering β€” trust lives in the artifact, not in whoever hands it over.

What a receipt answers

The minimal shape

Nothing about the record requires a platform. Newline-delimited JSON, one event per line, each line carrying the hash of the line before it:
Grep-able, git-trackable, verifiable offline with a for-loop and a hash function. That is the whole trick β€” the value is in committing to it, not in any engine.

Nika as one implementation

Nika ships the pattern end to end, which is why this page lives here β€” but each half maps to a plain command you can inspect:
  • The contract is nika check: the static audit that prints the plan, the cost bound, the secret flows and the permits boundary before a single token is spent, and exits non-zero when the file breaks its own contract.
  • The record is the flight recorder: every run journals to .nika/traces/ as hash-chained NDJSON, and the run prints its chain head on close.
  • The re-proof is nika trace verify β€” it recomputes the chain and either confirms the head or names the first altered link (the full trace verb family is in the CLI reference).
  • The exit is nika trace export: the journal projects to OTLP/JSON for Jaeger, Grafana or Langfuse β€” the receipt is portable, not a lock-in surface.
In CI, the same split powers Nika Γ— GitHub Actions: pull requests get the contract as a sticky comment, and nothing executes.

Adopt it without adopting Nika

The pattern is worth stealing. If your pipeline is LangGraph, plain Python or a Makefile, you can still ship receipts: declare the boundary in a reviewable file, journal settles as append-only NDJSON, chain the hashes, and teach CI to show the contract on every change. Your reviewers get the same two documents; no dependency required. If you later want the enforced version, how Nika compares is the honest map β€” including when not to switch.