There is one genuinely good sentence buried in the pile of AI agent guides published this year, and it is this:
Recurring failures become harness features.
It is good advice. Your agent keeps choking on a malformed API response, so you stop pleading with it in the prompt and write a validator. It keeps asking for a field it could have fetched itself, so you build a tool that fetches the field. It runs away with itself on long tasks, so you give it a step budget. Every one of those moves is correct, and almost every guide published in 2026 says some version of it.
Then they stop, because the advice is about a Tuesday. You have a bad day, you harden the harness, you ship.
Nobody writes about year five.
Harness, as the word is being used this year: the deterministic runtime that wraps a language model. The model proposes an action; the harness decides whether that action is well-formed, permitted, affordable and safe, executes it, and hands the result back. Everything an agent does that you can actually reason about happens in the harness rather than in the model.
What a harness turns into
Follow that advice for eighteen months and look at what you have. A few hundred small decisions about the world, each one encoded somewhere in the runtime: this response shape is legal and that one isn't, this action needs a human and that one doesn't, this is the escalation threshold, this is what a valid submission looks like, these are the fields that must be present before we are allowed to act.
Every one of those was true on the day you wrote it.
That is a rule base. And we have built rule bases before — thousands of them, across every regulated industry there is. We know exactly what happens to them over twenty years, because some of them are now old enough to autopsy.
I spent most of August reading one.
Two digits
Picture the end of a clinic day. A physician has seen a patient, examined them, worked out what is wrong and what to do about it, and written all of it down. One task remains before they can go home, and it has nothing to do with medicine.
They have to choose a number. 99213, or 99214.
Choose low, consistently, across a career, and you have quietly given away a meaningful part of your income. Choose high without the documentation to carry it, and the word for that is fraud. Somewhere in between is the code you actually earned, and the only person positioned to work out which one that is happens to be the person who has just spent nine hours thinking about anything else.
Nobody goes to medical school for this. It is a small tax of dread, paid daily, at the end of an already long day.
In 2006, my team was building an ambulatory EHR, and we decided to stop asking.
The idea
Our answer was audacious, and the rest of this depends on it, so let me put it plainly: never ask the physician.
The visit has already been documented. Every box ticked, every finding recorded, every system reviewed — all the evidence the code depends on is sitting in the chart before anybody thinks about billing. So read the chart and derive the code. Leveling as a by-product of documentation, rather than a separate act performed by a tired person at six in the evening.
That is a harness in the sense above, built two decades before the word arrived.
It is also the kind of thing that stops being visible once it works. The schema is wide enough that you can walk it for a long time without ever meeting the sixteen tables that hold the whole idea.
What was inside
The rules were in the database. Not written in code and deployed — stored as rows, and editable by anyone with the right screen.
Twelve thousand seven hundred and twenty-one stored predicates. Six thousand three hundred and forty-seven conditions. Three thousand nine hundred and ninety-one named condition sets, each a small boolean expression over what the physician had touched on screen.
And a vocabulary. Two hundred and six tokens, nine characters each, every one belonging to a body system:
| Token | What it stands for |
|---|---|
OPHPupIri | Exam of pupils and irises including shape, direct and consensual reaction, size and morphology |
OPHLmpAnt | Slit lamp exam of the anterior chambers including depth, cells, and flare |
HNKSinTen | Palpation and/or percussion of face with notation of presence or absence of sinus tenderness |
Every one of those descriptions is lifted, word for word, from the CMS 1997 Documentation Guidelines. The twenty body systems are the 1997 list. The eleven exam types are the ten single-organ-system exams of 1997 plus General Multi-System.
Somebody sat down with a federal document and typed all two hundred and six of them into a table, by hand, getting the wording exactly right — because in this system the wording is the rule.
That was the easy half.
Sixty conversations
The bullets are national. What counts as having documented one is entirely local.
One ophthalmologist records a slit lamp exam in a dedicated field with four discrete values. The man down the hall types the same finding into a free-text box at the end of his note. Both performed the exam. Only one of them did it somewhere a query can see.
There is a foreign key on the rule table that I misread twice before I believed it. provider_id. The rules are stored per physician.
Sixty distinct providers, each carrying their own copy of the same hundred and ninety-odd tokens. Which meant somebody had sat down with sixty doctors, one at a time, and worked out — for each of nearly two hundred federal exam bullets — which of that particular doctor's screen fields meant they had done it.
Sixty physicians. Two hundred bullets. That is the real reason those tables run to twelve thousand rows, and it represents months of somebody's working life, spent in rooms, asking a specialist to explain where exactly they write down a thing they do fifty times a day.
Nothing about that problem has gone away. Any system built in 2026 to read clinical documentation faces the identical question, and it is still the part that consumes the calendar.
The string in the middle
The engine walks a provider's rules, evaluates each condition set against the visit, and every set that holds concatenates its token onto a growing string:
VSTAmbNewHPXCplPrsHPXHpi=04HPXThrDocHPXRos=10HPXPstHisHPXKinHis
HPXLifHisEXMGenMltOPHPupResCPXFluRtnCPXImmPrvCPXDx0340CPXDx4011CPXi25000A visit-type prefix, the history elements with their counts, the exam type, each satisfied exam bullet, and the medical-complexity markers carrying diagnosis codes. The whole visit, compressed into something a machine can reason over and a human can still read at a glance.
Then the final step, and this is the part I keep returning to:
using CodingLibrary; // Referenced class for the licensed coding COM component.
int result = CodingLibrary.SetEvalManagementData(ICDList, EMVisitData);
if (result == 2)
{
EMCode = CodingLibrary.EMCode;
EMHistory = CodingLibrary.EMHistory;
EMExam = CodingLibrary.EMExam;
EMComplexity = CodingLibrary.EMComplexity;
}We did not write the part that turns tokens into 99214. We licensed it, from somebody whose entire job was keeping pace with CMS.
Our code answered what did this physician document, which is local, idiosyncratic and ours to know. A bought component answered what does the federal government say that levels to, which changes without asking you and carries audit liability when you get it wrong. The token string is the seam between the two, and it sits in exactly the right place.
Score it against the 2026 checklist
Take the list of principles every agent harness guide agreed on this year and hold the 2006 system up against it.
| The 2026 principle | What the 2006 engine did |
|---|---|
| The model proposes, the harness executes | Documentation produces a token string; a separate component turns tokens into a code |
| Rules as data, not code | 12,721 predicates, 6,347 conditions, 3,991 sets — every one of them a row |
| A typed intermediate representation | The token string |
| Stay vendor-neutral, keep the reasoning swappable | The leveling engine was a licensed component behind an interface |
| Observability on every decision | One summary row per visit: tokens, code, and the three component levels that justify it |
It passes. Comfortably.
It also worked. This was never a demo:
| Code | Visits |
|---|---|
| 99213 | 1,099 |
| 99214 | 1,037 |
| 99203 | 338 |
| 99215 | 172 |
| 99212 | 125 |
| 99202 | 110 |
A 99213/99214-dominated curve with a thin tail on either side is what an ambulatory practice actually bills. Somebody built a rule-driven decision engine with a clean intermediate representation and a swappable reasoning back end, in 2006, and it produced clinically plausible output on real visits for years.
The architecture was right. Every structural choice that engine made is a choice the 2026 guides would endorse, and most of them would endorse it more strongly than the teams shipping agents this quarter actually practice it.
It died anyway.
The part nobody plans for
I had spent two days mapping that rule structure — five levels of foreign keys, the parameter substitution, the way a condition is really a SQL query split across two tables with its FROM in one and its WHERE predicates in the other. Genuinely clever, for 2006, with nowhere else to put a rule.
Then I went to check which version of the guidelines it encoded, so I could write that down accurately.
That is when I found out the guidelines had been withdrawn.
In 2021, CMS revised how office visits are leveled. History and examination were removed from the calculation entirely. The 2023 update extended that to the remaining visit families.
Physicians still document history. They still document the exam. Those things no longer determine the code. Level is now medical decision making, or total time on the date of service.
Every one of those two hundred and six bullets, every one of the eleven exam types, the entire mapping layer, the counting logic, the history levels, the exam levels — all of it void for the purpose it was built to serve. Twelve thousand predicates that faithfully encode a rule which no longer exists.
The engine still runs. It still produces a token string. It still hands that string to the component. It answers, perfectly, a question that nobody is asking any more.
And it was not alone in there. Once I started looking, the whole system told the same story:
| What it encoded | How it was encoded | What happened |
|---|---|---|
| 1997 E&M guidelines | 12,721 predicates, 206 exam bullets, 11 exam types | Replaced 2021 and 2023 |
| ICD-9 | Throughout, including a million-row pairing table | Replaced 2015 |
| Meaningful Use Stage 1 | A dedicated layer in the rebuild | Replaced twice |
| PQRI quality reporting | Two copies of a generator | Became PQRS, then MIPS |
| X12 4010 | Claims and eligibility | Replaced 2012 by 5010 |
| CCD / C32 | 23,837 lines of generation code | Became C-CDA, then largely FHIR |
| UB92 | Four tables | Became UB-04 |
Every regulatory rule that system encoded has been replaced at least once. Not one of them was modelled with an effective date.
That last sentence is the whole essay. Every one of those changes arrived on a published schedule, announced years in advance, with a date on which the old rule stopped and the new one started. The information was public. The system had nowhere to put it.
Why this is about your agent
Open your repository and look at what you are actually shipping.
Your system prompt is a rule base with no effective date. Somewhere in it is a line about which requests to refuse, a line about the pricing tiers, a threshold above which something escalates to a human. Those were facts in March. Some of them are still facts. You have no way to tell which, and no way to ask.
Your tool descriptions are an API contract written in prose, versioned by nothing, read by something that changes underneath you.
Your permission matrix encodes a risk appetite from one specific quarter — the quarter in which somebody senior was nervous, or the quarter after the incident.
Your eval suite is a photograph of the world on the day it was written. When it passes, what it tells you is that the agent still behaves the way it behaved in March. Whether March was right is a separate question, and the suite has no opinion on it.
We had it easier in 2006. Our rules moved while the code stood still. Your rules move — and so does the thing reading them.
That is the genuinely new problem. The engine reading your prompt gets replaced roughly twice a year, and the replacement reads every ambiguous sentence you wrote slightly differently. You are maintaining a contract whose counterparty is swapped out on a schedule you do not control, against rules that change on a schedule you also do not control, with no record of which version of either produced any given decision.
Four ways it goes wrong
Nearly every architectural failure in that system reduced to one of four mistakes. All four are alive and well in agent codebases today.
Customisation by copy instead of overlay. In the old system, letting a physician tailor their documentation meant handing them a private copy of the entire tree. Eight hundred and fourteen physicians, eight hundred and fourteen forks, and a corrected baseline that reaches none of them. Those 3,991 condition sets are really about two hundred rules copied sixty times, once per provider.
The instinct behind it was sound — hand a clinician an empty authoring tool and they will never finish, so ship them something complete and let them bend it. The mechanism underneath was the problem. Nobody needed to tell those physicians to stop tailoring their own screens; what the system never gave them was a way to say this is the shared model, and this is my restriction of it, so every act of tailoring became an act of copying.
You are one forked system prompt per tenant away from the same position.
No shared model for a repeated shape. Thirteen copies of the patient matcher, in eight different versions, each of them deciding whether two records describe the same human being. Sixteen tables carrying an identical clinical shape, each with its own query code and the same undocumented magic number. Eleven work queues, each with its own schema and screens. Twenty-seven lab integration projects, one per partner per direction.
Count the retry logic in your agent fleet. Count the response validators. Count the places that parse a date.
No intermediate representation. Where that system built one, the code is still readable twenty years later — the E&M engine is comprehensible precisely because the token string sits in the middle of it. Where it built none, you get 5,952 lines of procedural XML generation in a single file, and a billing routine of 46,659 characters with two dated backups of itself sitting beside it in the schema.
An agent that goes from natural language straight to a side effect, with nothing inspectable in between, is the second kind.
Failure has nowhere to go. This one is the worst, and it is the most common.
catch (Exception e)
{
string x = e.ToString();
}That block is why 167 visits carry no billing code at all. The component failed, the exception was caught, a string was assigned to a variable nobody reads, and the visit quietly went unlevelled. Somewhere downstream a human either noticed and coded it by hand, or did not.
Elsewhere in the same system: 346,691 scheduling import errors sitting in a log file, and 44,637 claim errors in a table. Eleven queues for work, and not one queue for failure. Every one of those numbers is work a human being needs to do, and none of it reaches a person by design.
Your agent's graceful fallback is that catch block, wearing better clothes. So is the confident answer it produces when a tool returns nothing.
What to build instead
So build the dimension everybody skips, which is time. The 2006 engine was good engineering by any standard — layered, data-driven, honest about its own boundaries. It was simply built as though 1997 would hold.
1. Give every rule an effective date. A date range during which the rule is in force, stored as data and queryable — a changelog in git does not count, because you cannot join against it at decision time.
2. Stamp every decision with what produced it. Harness version, prompt version, rule set version, tool schema version, model identifier. A decision you cannot attribute is a decision you cannot defend, and in a regulated domain you will eventually be asked to defend one from eighteen months ago.
3. Build replay before you need it. The ability to re-run a decision under the rules in force on the date it was originally made. The old system needed this and never had it; the 2021 split made it mandatory rather than nice to have.
4. Date your eval suite. An eval is a claim about the world at a moment. Say which moment. When a rule changes, the cases that tested the old rule should fail loudly rather than quietly keep passing.
5. Make the proposed action a real object. Typed, diffable, loggable, replayable, reviewable — a thing that exists before it executes. That is what the token string was, and it is why that module survived long enough for me to read it.
6. Give failure somewhere to go. One work-item model: type, subject, owner, status, priority, due date, provenance. Then make every agent failure a work item. Eleven queues collapse into eleven filters, and nobody has to find the log.
7. Draw the build-and-buy line along volatility. What is local, idiosyncratic and yours to know, you build. What is national, volatile, liability-bearing and somebody else's full-time job, you license. That 2006 team drew that line twice, deliberately, and both times they drew it in the right place.
The seventh one is the piece of judgement in that old system that has aged best. A COM component is not how anyone consumes anything in 2026 — but deciding what your harness owns and what it rents from a model provider is the same call those engineers made, on the same seam, for exactly the same reason.
What I keep thinking about
The people who built that engine were not careless. They read a federal guideline, understood it properly, and built a machine-readable transcription of it with a clean architecture and a sensible vendor boundary. It holds up better than most of what ships today.
Fifteen years later a committee changed its mind, and twelve thousand carefully-written rules became an elaborate answer to a dead question.
The engineering holds up. What undid it was one unmodelled dimension inside a system that was otherwise modelled with real care.
Every agent harness being written this year is laying down the same kind of sediment: validators, thresholds, refusals, permission rows, eval cases. Almost none of them are writing down the one thing that decides how long any of it stays true.
The rules will move. They always do. The only real question is whether your system finds out from you, or from an auditor.
Part 2, When the Wrong Answer Is a Person, takes the other half of this: what changes in harness design when the failure mode is a human being rather than a bad answer.






