Hash Chains
Every interaction in a Spooled trace is linked via a SHA-256 hash chain, creating a tamper-evident audit trail.
How it works
Each interaction has a payload_hash (SHA-256 of its canonical payload). The chain is formed by computing a signature for each interaction that includes the previous interaction's signature:
# Each interaction's signature includes: signature = sha256({ interaction_id, sequence, interaction_type, payload_hash, # hash of this interaction's content prev_hash, # previous interaction's signature (None for first) }) # The chain links: interaction[0].signature = sha256(id, seq, type, payload_hash, prev_hash=None) interaction[1].signature = sha256(id, seq, type, payload_hash, prev_hash=interaction[0].signature) interaction[N].signature = sha256(id, seq, type, payload_hash, prev_hash=interaction[N-1].signature)
The final interaction's signature becomes the trace's chain_hash — a single value that represents the entire execution sequence.
Verification
spooled verify trace .spooled/traces/agent-runid.jsonl --verbose
This recomputes every hash in the chain and verifies:
- Each
payload_hashmatches the interaction's canonical content - Each
prev_hashmatches the previous interaction'spayload_hash - The chain is unbroken from first to last interaction
Tamper detection
If any interaction is modified after recording — content changed, order rearranged, interaction inserted or removed — the hash chain breaks. The verification command will report exactly which link is invalid.
CI integration
Hash chain verification runs automatically during spooled ci run and spooled ci compare. A broken chain causes the trace to be flagged.
Compliance use case
For regulated deployments, the hash chain provides tamper-detection evidence that a trace has not been modified after execution. Combined with KMS-signed attestations (Pro/Team), this creates a verifiable audit trail.