You did the work. Every agent run is traced. Tool calls, spans, latency, token counts, and whatever rationale the system emitted along the way. When something looks off, you can pull the run and read it end to end.
Then someone asks whether the thing you are looking at is normal for this agent, and the trace has nothing to say about it.
That question is the one production teams actually ask, and it is not answerable from the run in front of you no matter how much of that run you kept. I went at the reasons in From Observability to Behavioral Intelligence; the short version is that in a probabilistic system the execution stops standing in for the behavior, so a richer description of one execution does not get you closer to characterizing the system. This piece is the practical half: what you capture starting now so that the question is answerable in three months.
Rich and comparable are different goals
Most decision-capture work optimizes for reconstruction. Could someone rebuild what happened here, later, without having been there? That is the right goal, and I have written a checklist for it.
Comparability is a different goal that looks identical while you are implementing it. It asks whether this captured decision can be lined up against nine hundred others and grouped, counted, and watched over time.
A capture can be excellent at the first and useless at the second. That happens more often than not, because the properties that make a record rich (free-form text, whatever context happened to be in scope, whatever the system chose to say that day) are exactly the properties that make two records incomparable.
The mechanism is worth stating plainly, because it tells you what to do when your situation differs from mine: comparison requires that the same thing be captured the same way at the same point every time. Richness is per-run and can vary freely. Comparability is a schema-level property of the whole population. Some historical features can be derived later from raw traces you happened to keep. The ones you never captured consistently are simply gone.
What makes a decision comparable
Five properties, and they are ordered. Each one is worth little if the one above it is missing.
A stable identity for the decision point, and a version beside it. Before anything can be compared, you need to be able to say that this decision and that decision are instances of the same thing. Not the same request, the same choice: the escalate-or-resolve call, the refund-approval call, the which-tool-to-reach-for call. Refund approval stays refund approval no matter which function or model implements it this quarter.
Do not let that stability erase the fact that the implementation moved. Record the prompt, model, tool and config version alongside the identity, because a deliberate rewrite in April is one of the likelier explanations for a distribution that looks different in June. Without the version you will read an intentional change as unexplained drift, which is the more expensive of the two mistakes.
Identity answers what decision this is. Version answers what was making it at the time. Keep them separate precisely so one can move while the other holds.
A fixed capture moment. Capture at the point of choice, not at the end of the run. A record assembled in the postmortem is a reconstruction of a reconstruction, and worse, it is assembled at a slightly different moment each time. That variance alone will cost you the ability to see drift, because drift is a small signal and inconsistent capture is a large noise source.
A small set of stable dimensions beside the rich part. Keep the free-form rationale. It is useful for reading one case, with the caveat that a natural-language rationale is an account the system produced, not a transcript of how it arrived there. Either way you cannot group by it.
Alongside it you want a handful of low-cardinality attributes that describe the shape of the decision rather than its content: how many options were genuinely available, whether the call was close or lopsided, which category of evidence carried it, whether a governing rule was in play. There is no single right set, and yours should come from the questions your team actually asks during incidents. The constraint is that they be few, stable, and cheap to compute at the moment of capture.
What was live, not only what was chosen. Be precise about what live means here, because you cannot observe whatever a model internally entertained and you should not claim to. What you can capture is what was available or explicitly represented at the decision boundary: the eligible tools and actions, the alternatives the system actually surfaced, the evidence retrieved and in scope, the options produced by a structured selection step. That set is observable, and it is enough.
A record of the chosen path tells you the outcome. A record of what was available tells you the shape of the judgment, and shape moves before outcomes do. When a signal that used to be decisive quietly stops appearing in the eligible set, nothing fails, no output looks wrong, and the distribution has already shifted underneath you.
Retention that outlives the raw run. Raw traces are expensive and you will expire them, correctly, on a schedule. The comparable summary has to be on a different and much longer clock. If they expire together, then every time someone asks whether a failure shape has occurred before, the honest answer is that the evidence aged out. Decide this deliberately, because storage defaults will decide it for you otherwise.
| What you want to ask | What it needs |
| --------------------------------------- | ------------------------------------------------- |
| What happened on this run | The trace you already have |
| Why this call was made | A decision captured at the point of choice |
| Is this normal for this agent | A stable identity plus groupable dimensions |
| Has this shape happened before | A summary that outlives the raw run |
| Did the system change, or the behavior | Identity held stable, version recorded beside it |
| Is judgment drifting, and since when | What was live, captured consistently over time |The one that breaks first
Identity, almost always, and its twin.
An agent gets refactored in March. The prompt gets rewritten in April. The model gets swapped in May. Every one of those is a normal, healthy change that nobody would think to announce to the observability layer. In June someone asks whether the escalation behavior has changed since spring, and the data splits into three populations that cannot be compared to each other, none of them covering enough time to answer the question.
Nothing was lost through negligence. The identity was never a first-class thing, so it drifted quietly every time the code did.
The mirror-image failure is subtler and more embarrassing. You hold the identity stable, the comparison works, the distribution has clearly moved, and nobody can say whether that is the system behaving differently or the April rewrite doing exactly what it was asked to do. You will spend a week finding out.
The fix for both is unglamorous and cheap if you do it early. Name your decision points explicitly, as durable identifiers that belong to the business choice rather than to the function that currently implements it, and treat renaming one as a migration rather than a cleanup. Then stamp every captured decision with the version of whatever produced it. If a refactor changes the identifier, you have started a new population and should know that you did. If it only changes the version, you have kept the population and gained the ability to explain a step change inside it.
What this does not give you
It does not tell you whether a decision was correct. Comparability tells you what is usual, and usual is not the same as right. A system can be consistently, stably, comparably wrong, and this instrumentation will show you a tight distribution and a healthy baseline the entire time. Correctness needs an outcome, and outcomes arrive later and from somewhere else.
It does not replace evals. Evals ask whether the system meets a standard on cases you chose. This asks what the system actually does on the cases production hands it. Teams that have both find the disagreements between them more informative than either one alone.
It is not free, and the cost is mostly discipline rather than compute. An attribute that seems useful and turns out to be high-cardinality will quietly make your population ungroupable, and you will not notice for a month. Start with fewer than you think you need. Adding one later is easy; the identity and the capture moment are the parts you cannot retrofit.
Start with one decision point
Not a program. One.
Pick the decision in your system that would be most expensive to get quietly wrong, the one where a bad call does not throw and does not page anyone. Give it a durable name. Capture it at the moment the choice is made, with whatever rationale you are already collecting, two or three stable attributes about the shape of the call, the alternatives that were available at that boundary, and the version of the prompt and model that produced it. Put that summary on a retention clock measured in months rather than days.
Then do nothing with it for six weeks.
That part matters, and it is the part that feels wrong. You are not building a dashboard; you are accumulating the population that makes the first real question answerable. The value shows up the first time someone asks whether this is normal and the answer comes from data instead of from the most senior person's memory.
A single captured decision tells you why something happened. Enough of them, captured the same way, tell you what normal looks like for your system, which is the thing nobody can currently answer and everyone eventually needs. That accumulation is what I am building Nalyqor around, and it is worth saying that the hard part is not the storage. It is deciding, before you need the answer, which comparisons you want to be able to make.
