Can Your Traces Reconstruct What Your Agent Did?
When I ask teams running agents in production whether they can reconstruct what an agent did yesterday, most of them say "we have logs." Logs show that a call happened. A post-mortem needs more: which agent acted, who it acted for, what it was asked to do, and under what permission.
So I built a free check that answers that question for your own system in one run: agent-evidence-check. Your coding agent runs it on the traces you already keep. This piece covers what it found on our own platform, the six questions behind it, how to run it, and what to do with the gaps.
I ran it on our own platform first
Before sending the check to anyone, I ran it on the agent platform we build at Theona. Five of the six questions had no answer, and that held across five separate runs, one of them on the live database. We were building software for exactly this problem, and our own record answered one question out of six.
The three gaps that hurt most were ordinary:
- The human's answer was nowhere. The system held a call and asked a person to confirm. The person answered. Nothing stored what they were shown or what they said. We could count how many calls were held, but not what was decided.
- The agent's instructions were a hash. The record could say the instructions had not changed since the run started. It could not say what they were, or what the agent was allowed to do under them. Ask "under what permission did this run" and you get a checksum.
- Two runs touching the same thing did not know about each other. One run wrote a file, a later run read it, and nothing linked them.
I publish this because a check is only worth running if it can come back bad, and this one did.
Where the six questions come from
Start by listing the most damaging things an agent can do to the company that runs it. Some harms are loud: an outage, a deletion, a payment. Those already have watchdogs — monitoring, backups, finance reconciliation. Others are quiet: a leak, a made-up number, access that slowly spreads. Each action in those stories looks normal on its own, so nothing watches for them.
The quiet harms compress into four conditions a rule can test on a single action:
- Transparency. Every action can be reconstructed.
- Data. Nothing goes to a recipient nobody asked for.
- Irreversibility. No irreversible or bulk action without a check.
- Authority. The agent does not act beyond what it was given.
The full derivation is in the README. What matters is the consequence: before any rule can test any of the four, the record of the action has to answer six questions.
The six questions
- Which agent acted, for whom, and with what permissions? The tools it called tell you what it did. They do not tell you what it was allowed to do.
- What did the user, or the trigger, actually ask for? Guessing it from the tool name does not count, and neither does the fact that the call succeeded.
- Which resource or recipient was affected, and what kind of data reached it? An id for the thing itself, and a recorded data class.
- What did the agent try, and what actually happened? A success flag written by your own code says you asked. The called system's response says what happened.
- Was a human asked, and what did they answer? An approval flag with no prompt behind it does not say what was approved.
- Which version of the instructions, the tool catalogue and the policy was in force, and which other runs is this one linked to? One hash over everything changes whenever anything changes, so it identifies nothing.
A question with no answer means every rule that depends on it can never run.
How to run it
The check is a skill: a Markdown file of instructions for a coding agent. Claude Code, Codex, or anything else that follows a skill file will run it. Clone the repository, give your agent the path to skills/agent-evidence-check/SKILL.md, and ask it to check what your traces can prove.
It needs read access to wherever your traces live, and nothing more. It never asks for new access: a store the agent cannot reach is written down as a limit of the check, not as a gap in your evidence. It installs nothing and sends nothing anywhere.
The agent finds every place agent activity is kept: the tracing tool (Langfuse, LangSmith, an OpenTelemetry pipeline or similar), the framework's run store, application logs, the rows the agent wrote. It picks one consequential action from the retention window, follows the chain back to whatever started the run and forward to how it ended, and answers the six questions. Budget about an hour of the agent's time, more if your traces live in many places.
The output is one page. For each question you get either a field path in a record the agent actually opened, or a gap with its kind: never captured, captured but not linked to this action, captured but out of reach, or removed by retention. It also lists the sources it read with their retention windows, and what would have to be recorded to close each gap. It carries field paths, identifiers and counts only, never message bodies or personal values. A line looks like this:
5. Was a human asked, and what did they answer?
GAP, never captured.
runs.interruptions records that the call was held (1 row).
No field stores the prompt shown or the answer given.
Closest field you already write: runs.interruptions.resolved_at
It gives no score, and it never calls an action harmful or unauthorised. Where the evidence runs out it says "insufficient evidence" instead of guessing. A clean result means one thing: one consequential action could be reconstructed from what you keep today. It does not mean your tracing is good in general.
What to do with the gaps
Close the ones that are one field away first. Many are. Store the decision next to the approval flag. Carry the request id into every tool call it caused. Emit the instruction version and the catalogue version as two fields instead of one combined hash. This is instrumentation at the point where your agents' calls leave your system, and it needs no vendor.
Some gaps are bigger than one field: the request never reaches the tool layer, or two systems each hold half the story with nothing to join them. Those need one record written at that same point, by your platform rather than by each agent, so every call carries who acted, for whom, under what permission, and what came back.
Once the six questions close, rules become possible. Write them against the tools your agents really call, and keep them current as those tools change. An agent can draft most of them from what the check and the record turn up. A person confirms each rule before it goes live and decides the cases that need judgement.
What I'd add now
Since the first version I've talked with many more teams running agents. The record of one action is still the floor. But once a company has dozens of agents, the harder questions are about the agents themselves: who answers for each one, who takes over when its builder leaves, and which agents break when a process changes.
The first of the six questions is where that starts. If your record cannot say which agent acted and for whom, there is nothing to attach an owner to. The teams I've seen handle this well keep a registry of their agents with a named owner for each one.
Where to start
Run the check on your own traces. It will tell you which of the six questions your record answers today and where it goes quiet. If it gets something wrong on your system, or you think a question is missing, open an issue in the repo or message me.
If your agents live on laptops with keys in a dozen configs, there is no record to check yet. Start by putting one door in front of your agents, let a few days of traffic through it, then come back.
An earlier version was published on the Heron blog as Can Your Traces Reconstruct What Your Agent Did?.