It is 9:40 on a Tuesday. Finance has a $50,000 outbound wire from yesterday afternoon that nobody remembers approving. The agent that handles vendor payments says it was instructed to. The customer whose account it left says it was not. Your CEO wants to know, by lunch, which of them is right — and your general counsel wants to know what you can prove.
This note works backwards from that morning. What does a record have to contain for the question to be settled in an hour rather than a month? And, more uncomfortably, what do most stacks actually have?
What “hallucinated a transfer” actually means
Three different failures hide under that phrase, and the record has to distinguish them:
- 01The agent invented the instruction. No human or upstream system asked for a transfer; the model generated a tool call from nothing.
- 02The agent misread a real instruction. Somebody asked for $5,000 and it sent $50,000, or asked for a different payee.
- 03The instruction was real and the agent was right. The customer is mistaken, or is not being straight.
A stack that cannot tell these apart the morning after will end up refunding the money in all three cases, because it cannot prove the third.
What the record has to hold
Here is the sequence as it would sit on a chain, for a version of this where the control worked. Sequence numbers, the action, what was fingerprinted, and the seal.
| Seq | What happened | Recorded as | Seal |
|---|---|---|---|
| 4180 | pulled the credit file | tool_call · fingerprint 9c1e… | — |
| 4181 | declined — debt-to-income 51% | decision · fingerprint 44a0… | — |
| 4182 | asked to wire $50,000 | tool_call · policy: above $10,000 a person signs | waiting |
| 4183 | approved by r.mehta@ (session 7f…) | approval · from authenticated session | — |
| 4184 | wire_transfer executed · ref TXN-88213 | tool_result · fingerprint e07b… | sealed #4184 · TSA 14:32:07Z |
Six things in that table settle the Tuesday question, and each is a property a stack either has or does not:
- The input the agent acted on, fingerprinted. Not the full payload — a hash of it, so the instruction can be matched against what the customer says they sent without the record itself holding their data. If the fingerprint of “wire $5,000 to Acme” does not match what the agent recorded at 4182, failure two. If nothing upstream of 4182 carries an instruction at all, failure one.
- The tool call as the model emitted it. Function name, arguments, and the model’s own call id — recorded before execution, not reconstructed from the result.
- The policy verdict, before execution. “Above $10,000 a person signs first” ran at 4182 and the agent stopped. If your stack has no row like this, the answer to “why did nobody stop it” is that nothing could have.
- A named human on the approval, from the session. 4183 is r.mehta@, from an authenticated session, not from a field the agent filled in. If the approval is svc-agent-prod, you have a service account approving its own wire.
- The result, with the external reference. TXN-88213 ties the chain to the bank’s own record. Two independent systems agreeing is what “proof” means in practice.
- A seal with an independent timestamp. The chain head at 4184 was signed and countersigned by an RFC 3161 authority at 14:32:07Z. That is what stops “you could have written this last night” from being a reasonable objection.
What most stacks have instead
We have looked at a lot of these the morning after. The usual inventory:
- The model provider’s request log — full payloads, a provider-controlled retention window (see OpenAI’s published endpoint policy), and no record of whether the tool call was executed, only that it was emitted.
- An observability trace — good for the “why”, mutable, and typically expired if the dispute surfaces at month-end reconciliation.
- The bank’s record — TXN-88213, which proves the money moved and nothing about why.
- A Slack thread from that afternoon in which somebody says “approved 👍” and nobody can say whether that was this wire.
Nothing there is tamper-evident, nothing was checked before execution, and the one human signal is a thumbs-up emoji. In that stack the honest answer to the CEO is “we cannot prove it either way”, and the refund goes out.
The uncomfortable part: it was probably failure three
In the disputes we have seen, the agent was usually right — the instruction was real, the amount was correct, and the customer had forgotten or was testing the process. A company with the record above keeps the $50,000 and the customer. A company without it refunds, and has taught the customer that disputes work. The cost of not being able to prove your agent was right is paid most often on the days it was.
What to do before Tuesday
- 01Name the material actions. Wires, refunds above a figure, anything that touches a person’s data or a decision about them.
- 02Put a pre-execution check in front of each, with the threshold in one English sentence and the approver’s identity from the session.
- 03Record the input fingerprint, the tool call as emitted, the verdict, the approval and the result as five entries in order, on a chain.
- 04Seal the head on a schedule and get it countersigned by a timestamp authority you do not run.
- 05Export it once and verify it offline yourself, so you know the answer to “can you prove it” before anyone asks.
The demo at /app/demo is this exact sequence — 4182 waits, a person signs, the chain seals — and you can try to edit a row and watch the verifier fail on it. The five-entry shape is specified field by field at /ai-agent-audit-trail.
See it on a real chain
The evidence path described above is running on our own account. Every ad-account change made by the agents behind Admiral, our paid-ads product, is recorded on the chain admiral/prod — actions on the chain, seals countersigned, and the sealed-through sequence are read live at /trust, not written into the page.