Chapter 8 of 8 · 18 min read
A decision record that survives "it can't handle anything new"
On this page
- The five dimensions, and what the expense case scores on each
- Writing it down so it survives repetition
- Meeting the objection by agreeing with it
- Twelve minutes, in what order
- Reading a review that confirms the decision
- The single requirement that would flip the design
- Two ways a signed record stops working
A design argument has a short life as speech and a long one as a document. The version of your reasoning that reaches the people who decide is whatever somebody else can repeat from memory a fortnight later, and that version is almost never the one you delivered. This is the practical problem with winning a design review: the win is not portable. What is portable is an artifact, and the artifact has to be built so that a reader who was not in the room reaches the same conclusion from it.
The artifact is a decision record — an architecture decision record, in the sense the acronym ADR is usually given: a short document naming the decision taken, the evidence behind it, the alternative rejected and the date somebody has agreed to look again. This chapter builds one around five dimensions, and the reason it is five rather than one is structural. A recommendation resting on one dimension is a single claim, so a single counter-claim retires it, and there is always a counter-claim available. Build cost loses to future-proofing. Accuracy loses to a benchmark someone else ran. Elegance loses to everything. Five dimensions, each with the evidence attached and each answerable independently, is harder to knock over because knocking over one of them does not change the recommendation.
The load-bearing word there is independently, and it is worth being strict about it. Five restatements of one claim are one claim wearing five hats, and they fall over together the moment their common assumption is challenged. The five below survive separately because each is answered by a different kind of evidence: a count of code paths, a description of the work, a measured latency, a retention requirement from outside engineering, and a property of what the system does to the world when it is wrong. No single objection reaches more than one of them.
The five dimensions, and what the expense case scores on each
| Dimension | Question it answers | Expense reports |
|---|---|---|
| Path variability | Can the steps and their order be listed in advance for nearly every input? | Five steps, one branch, one fallback. Fixed. |
| Tool-choice requirements | Does the work require selecting tools whose identity depends on mid-run discoveries? | Four tools, all called on every claim, in the same order. |
| Latency budget | What is the deadline, and whose? | Claim submitted from a phone; user expects a decision screen inside 5 s. |
| Auditability | Who has to answer "why was this decided" and how long after? | Finance, to an external auditor, up to seven years later. |
| Containment of wrong actions | Reversibility and blast radius of the worst single action | Irreversible payment after payroll, one record, 18,600/yr. |
The useful reading of that table is not the verdict in any single row. It is the gap between what this work requires and what the alternative design supplies. A model-driven loop has exactly one capability that a fixed graph cannot reproduce, which is choosing what to do next from something discovered mid-run, and the second row records that this task never needs it. Every other row then measures a cost of the loop against a requirement the loop does not help with. Reading down the levels tells you the expense flow is unremarkable; reading the gaps tells you the flexibility is being bought and never spent.
Four of those five point the same way without any appeal to cost. Path variability is the criterion from chapter 1 applied directly — whether the steps and their order can be listed in advance for nearly every input — and here they can: parse, categorise, policy-check, threshold, route is a graph with seven reachable states, and a claim that produces something outside them lands in an explicit unrouted branch. The latency budget is decided by where the work happens: a submission screen with a five-second expectation cannot absorb the kind of latency tail chapter 6 measured on a model-driven loop, where the ninety-fifth percentile sat at several times the median, and a fixed path of four tool calls at a p95 of 3.2 seconds can. Auditability and containment are the two properties chapter 7 supplies — how reversible a wrong action is and how far its blast radius reaches — and they are the two that a six-week estimate cannot buy its way past.
The fifth works the other way round, and separating it from the four is worth the sentence. Tool choice is the thing an agent is actually for, and this task does not have it — the receipt is always OCR'd, the policy is always retrieved, the amount is always compared, and no claim requires deciding whether to do any of those. An absence does not point anywhere. What it does is remove the only positive case the other design had, which leaves the other four arguing against a proposal with nothing left arguing for it. That is why the dimension belongs in the table and is not counted among the four.
The record is also precise about which of those calls reach a model, and the distinction matters more than it looks: field extraction and categorisation, and nothing else. Approval routing, the threshold comparison and the ledger write are ordinary code. A model that gets better or slower therefore moves the accuracy and the latency of two steps, and leaves the shape of the path, the comparison that decides a payment, and the record of what happened exactly where they were.
The seven reachable states are worth pausing on, because the same number came out of the six-way ticket router in chapter 1 and that is not a coincidence. Both counts are built by the same construction: enumerate the outcomes the domain actually has, then add one deliberately built branch that catches everything else, owns it, and increments a counter. Six labels plus an unrouted default made seven there. The states a claim can be in plus an unrouted default make seven here. What the construction buys is that the function is total — every input reaches a state somebody named — and the count is a consequence of the construction rather than a number worth remembering. In both chapters the enumeration is executable rather than asserted, which is why the record's evidence column names a test file instead of a diagram.
Some of what the table records is a requirement and some of it is a design decision, and the whole method depends on the reader being able to tell them apart. Seven years of retention, a five-second expectation on a submit screen, and the fact that a payment cannot be taken back once payroll has run are requirements: they arrive from finance, from the product surface and from the world, and no architecture choice negotiates with them. The threshold at fifty, the number of tools, the review interval and the band the override rate is allowed to sit in are design decisions: somebody chose them, can defend them, and can change them. The two behave differently under challenge, and a record that blurs them invites a reviewer to argue with the calendar of an external audit.
Writing it down so it survives repetition
adr: 041-expense-claim-processing
status: proposed
date: 2026-03-19
owner: d.okafor
decision: >
Deterministic five-node workflow. Model calls at field extraction and
categorisation only. Approval routing, threshold comparison and ledger
write in code.
dimensions:
path_variability: {verdict: fixed, evidence: "7 reachable states, enumerated in test_paths.py"}
tool_choice: {verdict: static, evidence: "4 tools, all invoked every run, fixed order"}
latency_budget: {verdict: 5s p95, evidence: "mobile submit screen; measured workflow p95 3.2s"}
auditability: {verdict: strict, evidence: "external audit, 7y retention, policy version must be recorded"}
containment: {verdict: irreversible, evidence: "payroll run on the 25th; undo = 3 people, ~2h"}
instrumentation:
fallback_metric: expense.unrouted_rate
review_date: 2026-06-19
reversal_thresholds:
- "unrouted_rate > 3% sustained over 4 weeks"
- "manager override rate < 2% (gate is theatre) or > 25% (extraction is wrong)"
- "a policy corpus that requires open-ended retrieval to evaluate one claim"
rejected_alternative:
option: "tool-calling agent over the same four tools"
reason: >
Adds a trajectory as the audit record where a state transition table is
required; moves the payment decision from a comparison in code to a model
output; p95 latency incompatible with the submit screen.
not_reason: "build cost"That last key is doing deliberate work. Writing not_reason: build cost in the
record removes the weakest argument from the table before anyone else can
attribute it to you, and it makes the record readable by the product lead as
something other than an engineering preference. Nine days against six weeks is
real and it is the least durable fact in the document, because estimates move
and the other five rows do not.
The reversal_thresholds block is what converts the record from a verdict into
a commitment. Without it, "we can add flexibility later" is a sentence that has
never once caused anyone to add flexibility later, which is why chapter 3's
instrumented fallback branch and chapter 5's scoping of a loop to a single node
have to be in the record rather than in the reviewer's intentions.
What makes a threshold able to fire is worth taking apart, because most written
ones cannot. It has four parts. It names a metric, meaning a counter that
exists in the code and is being written to right now — here expense.unrouted_rate,
the share of claims that match no branch and land in the branch built to catch
them. It names a number, so that an observed value can be on one side of it
or the other. It names an observation window, so that a single bad day does
not trip it and a single quiet week does not clear it. And it names a date
on which somebody performs the comparison. Remove any one of the four and the
threshold is inert. With no metric there is nothing to compare, and no goodwill
produces a measurement afterwards for a period that has already gone by. With
no number, every value observed is consistent with the record. With no window,
the rate is whatever the last hour happened to be. With no date, the comparison
is nobody's job. "We'll revisit if it becomes a problem" has none of the four,
which is exactly why it is so easy to write and has never fired.
Two of the three entries in that block are instruments of this kind. The third is not, and the difference is worth naming rather than smoothing over. A policy corpus that requires open-ended retrieval to evaluate one claim names no metric and no number, so nothing can be read off a dashboard against it on the review date. It fires when somebody writes a new requirement down, which is a legitimate trigger and is how the requirement in the last section of this chapter would arrive — but it is a different instrument, and a record whose thresholds are all of that kind has a review date with nothing to read on it.
Meeting the objection by agreeing with it
The objection arrives in some form of but then it can't handle anything we didn't think of, and it is true. A fixed graph handles exactly the cases somebody enumerated, and the person raising it is describing the design accurately. The reply that holds is to agree, state that the fallback branch is the mechanism by which unanticipated inputs are handled today — visibly and countably, rather than silently — and name the number that would change the design, which for this system is the unrouted rate crossing 3% over four weeks.
Agreeing feels like conceding, and the step that makes it safe is noticing that the objection and the recommendation are claims about different things. The objection is a claim about the future distribution of inputs. The recommendation is a claim about what to build now, given that nobody has evidence about that distribution yet. Agreeing with the first does not touch the second. Refusing to agree with it, on the other hand, commits you to predicting the same unknown distribution in the opposite direction, which is the position the person proposing the agent is already in and is not a position worth joining them in.
That reply also gives the objector something they did not have: a way to be proved right, on a date, by a metric that will be collected whether or not anyone remembers the argument. It costs nothing to offer, because the fallback branch and the counter are fifteen lines and would exist anyway.
| Objection | The weak reply | The reply that holds |
|---|---|---|
| "It can't handle anything new" | "It won't need to" | "Correct. Unrouted rate is the metric, 3% is the threshold, June 19th is the date." |
| "The agent is more future-proof" | "You aren't going to need it" | "Future-proof against what rate of what input? That is the number we're instrumenting." |
| "Models will keep getting better" | "We can't build on speculation" | "A better model improves the extraction and categorisation nodes identically. It doesn't change who compares 50 to the amount." |
| "Six weeks is already approved" | "Nine days is cheaper" | "The estimate isn't the issue. The audit record and the payment decision are, at any build cost." |
| "Other companies ship agents for this" | "They're wrong" | "On what task shape and what latency budget? Ours is a 5-second submit screen with a 7-year audit trail." |
Read that table down the middle column rather than across, and every weak reply fails in the same way: it denies the objection instead of naming what would settle it. Denial invites the objector to hold their position, since nothing has been offered that could ever change either side's mind. The right-hand column concedes the factual content of each objection and moves the disagreement onto a quantity, which is the only move that ends an argument about the future.
The third row is the one most often missed and it is the strongest available. It also inverts the shape most of this topic has been teaching. Elsewhere the stumble is a quantity held constant while the dangerous property varies — an iteration cap that stays at fifteen while what it counts and what it does on tripping do not, a prompt that says the same thing on every run while compliance with it does not. Here the quantity that varies is model quality, and the things that stay constant are the ones doing the protecting. Model improvement is frequently offered as an argument for the agent, and improvements accrue to both designs, because the fixed graph contains model calls too. What a better model does not do is turn a trajectory into a state transition table or move an irreversible payment back behind a comparison. The belief being corrected is that a defence will eventually be supplied by progress; what is true is that progress moves the accuracy of two nodes and leaves the control exactly where it was.
Twelve minutes, in what order
The record is the durable artifact and the meeting still has to be survived, and the ordering of the five dimensions in the room is different from their ordering in the document. Lead with containment, because it is the one nobody in the room disagrees with once it is stated: the system pays money, the payment is irreversible after the 25th, and the comparison of an amount against a threshold is going to be a line of code in either design. That sentence is short, it is not an architecture opinion, and it changes the shape of the conversation from "which paradigm" to "which parts".
Follow with auditability, which is the dimension the finance stakeholder in the room will adopt as their own and carry for you. Then latency, because it is a measured number against a stated budget and requires no interpretation. Path variability and tool choice come last, in the room, even though they are the criterion the whole topic has been building, because they are the two an audience without the background reads as engineering preference. A room that has already agreed the payment decision belongs in code and the audit record must be a table will accept a five-node graph without needing to be convinced of anything about state spaces.
The ordering has a mechanical justification rather than a rhetorical one. Each dimension needs a different amount of shared background before the room can evaluate it, and the order above is that requirement, ascending. Containment needs none, because everyone present already knows what a payment is and that it is hard to take back. Auditability needs one fact, which somebody in the room already owns. Latency needs a measured number and a stated budget, which is two facts and no framework. Path variability and tool choice need a criterion nobody outside this material has read. Leading with the dimension that requires the most shared background is how a technical disagreement turns into a status one, because an audience that cannot evaluate a claim evaluates the person making it instead.
What not to say is equally practical. Do not describe the agent proposal as over-engineering, which attacks the person rather than the design. Do not offer the nine-day estimate unprompted, since it invites the whole decision to be re-argued on the one dimension the record deliberately set aside. And do not claim the workflow will never need to change, because it will, and the record already says when you will look.
Reading a review that confirms the decision
The composition figures above are worth reading as a partial answer rather than a complete one. The two named causes account for most of the unrouted claims and not all of them; roughly one in seven of those claims was never characterised, and the conclusion that nothing here is a control-flow finding is a conclusion about the part that was examined. That is not a reason to distrust the outcome, and it is a reason to write the scope into the record alongside it, because the unexamined remainder is exactly where a second cause would first appear. The cheap correction is to make the reason-code enumeration total in the same way the claim states are total: a named bucket that owns everything unclassified, with its own share on the dashboard.
Most reviews confirm the original decision, and that is the ordinary outcome rather than a disappointing one. The value of having written the record is that confirming it cost twenty minutes and produced evidence. The reviews that do not confirm it are the ones this topic exists for, and they have a recognisable shape: the rate crosses the threshold, the composition shows a tail rather than a head, and the change that follows is one node acquiring a bounded loop with its own budgets, while the payment decision, the audit table and the four other nodes stay exactly where they were.
The single requirement that would flip the design
Something should flip it, and it is worth being specific rather than gesturing at complexity. The requirement that flips this design is a policy check that cannot be evaluated by retrieving a known set of clauses — a policy that lives as a corpus of country-specific handbooks, union agreements, per-project exception memos and emailed approvals, where deciding whether a claim is compliant requires reading a document, discovering that it defers to another document, and following that reference, with the identity of the next document determined by what the last one said. That is chapter 4's criterion exactly: the argument to the next step is drawn from an open space, and the rule mapping a discovery to the next action cannot be written in advance. Note which dimension moved. Tool choice was the one that removed the agent's positive case, and an open corpus is precisely the thing that restores it.
What flips is narrower than the slide asks for, and the narrowness follows from the other four dimensions being untouched. The policy-check node becomes model-controlled iteration in the shape chapter 5 described, a bounded loop inside a single node: a read-only tool set over the corpus, a step cap, a token budget, a wall-clock deadline, and a refusal that routes to a manager. Parsing, categorisation, the threshold comparison and the ledger write stay in code, because nothing about an open policy corpus changes the reversibility of a payment or who has to answer the auditor. An open-corpus requirement is an argument for one agentic node, and it is not an argument for a six-week rewrite of a graph whose other four nodes were never in question.
Two ways a signed record stops working
The first is the absence of an owner, so that the review date passes and nobody was accountable for looking. A date with no name against it is a wish, and the failure is silent, because a review that does not happen produces no artifact whose absence anybody notices.
The second is a reversal threshold that cannot be measured with what was actually built, which is the failure the four-part test above is for. This is how "we'll revisit if it becomes a problem" gets into a document and stays there: it reads as a commitment and names no metric, so it can never fire. Both failures are avoidable by one check made before the record is signed — that every threshold in it corresponds to a counter that exists in the code and to a person who has agreed to read it.
An argument you win in a room is spent the moment the room empties. The same argument written as a record with five independent dimensions, evidence against each, an owner, a date and a number that would reverse it survives being repeated by people who were never in the room, and it survives the objection that started this chapter by agreeing with it and pointing at a counter.
The record is the deliverable. Take the system in front of you now, score it on the five dimensions, write the fifteen lines that will produce the number in the reversal threshold, and put a date on it. The argument you have been reading is only useful once it exists as an artifact somebody else can act on in three months.
Workflows vs agents — read the current version at https://daviddominguez.dev/learn/en/workflows-vs-agents/a-decision-record-that-survives-it-can-t-handle-anything-new