Essay · July 8, 2026
It is always a maybe with the model
In 2025 I wrote an AI coding harness for a production codebase with a real product running on it, and I believed it was state of the art at the time. This year I audited it, because I was getting frustrated with the agents making the same mistake again and again. I sat down and asked one question of it: how many of these gates are mechanical, and how many are probabilistic? That is where I started to be honest with myself.
As I went through each of the skills and all of the convention rules, everything started to fall on the probabilistic side. There were no mechanical checks at all. That is when it hit me that I had been doing it wrong all along.
Nothing in the harness could block anything.
What we had built
The harness was not a toy. It took a raw idea through a requirements interview to flesh out the exact product requirements, wrote the stories from them, did a technical pass, and broke the stories down so that every ticket handed to an agent was verifiable through the acceptance criteria. Some tickets ran sequentially, some in parallel, based on the decomposition. And still, the agent would sometimes not follow the conventions and go write the same things we had asked it not to do in the codebase.
Our answer, every time, was more prose. The conventions file grew from around 5,000 lines to 12,000 lines over a period of time, as we found real issues with the agent’s behavior. We kept adding to it in the hope that it would help steer the agent, but that did not happen. The agent kept making the same mistakes again and again.
The part I would rather not write down is that we knew context engineering matters, and we kept on adding rules and rules to a conventions folder anyway. I knew better while I was doing it.
Why prose cannot enforce
The model is probabilistic. It is always a maybe with the model whether it reads a rule or not. With 12,000 lines, most of the time it misses some of them - the research on long context says models attend to the top and the bottom of what you give them, and the messy middle is mostly lost (Lost in the Middle, Liu et al.).
The obvious response is that 12,000 lines is the problem - keep the rules file at 300 lines and prose works fine. Ours was 300 lines. The root file just orients the agent to the respective areas of the repos, and different skills load different context for different tasks. Think of it as progressive realization of context. Even with that, the model kept violating the rules of the repo. And the 12,000 lines could not be cut down. These were real issues. These had to be followed.
We even put a router in between - a small agent that would go and fetch the specific sections of the conventions relevant to the task at hand. It did not save us, and the reason taught me something: the router finds what the prompt already knew to ask for. During the audit I underspecified a task on purpose, and the router never looked for the right convention at all. There was never an enforcement mechanism available to the model.
Where the line actually sits
Any rule that you can write as code - a lint rule, a dependency check, anything codeable - goes into sensors. Anything you cannot specify through code, that can only be done through judgement, goes into prose, as succinctly as possible. That’s it.
Two examples from our own conventions. We had all constants defined in a single file, with every other module importing from there. That is a simple grep - a lint rule. We had it in prose, and the model would sometimes follow it, other times not. It never needed to be prose. On the other side: simple queries can be written in the facade layer, complex queries always go in the service files. Every developer forms a mental model of what counts as simple. That is a pure judgement call. It cannot be enforced through code, so it stays in prose, with examples.
What the sensors do
Think of the rules, conventions, and skills as guidance for the agent. Think of the mechanical rules - the lint rules, the dependency checkers, the structural checks - as sensors. The guides-and-sensors framing comes from Birgitte Böckeler’s work, and it matched what I was seeing on my own codebase. The guidance steers the agent toward the right way, but since the model is probabilistic it will not follow everything exactly. When it tries to commit, the sensors fire. And when a sensor fires, the model has something to react to.
I tested this on the same codebase with the same prompts, hooks on and hooks off. With the hooks off, the same repeated violations. With the hooks on, the agent tried to commit, saw the problem, understood the actual issue, went back and fixed the issues, came back, committed, and pushed. When it hit another sensor it ran the loop again. It is a feedback loop - the same red-to-green rhythm as test-driven development, except the failing test is your own convention. This is a small N - five or six runs - so all I will claim is that it worked in those runs.
The tools were never the missing piece
Everything I just described runs on tooling that has existed for a decade or more. Pre-commit hooks. Lint rules. Dependency checkers. Required checks in CI. None of it is new, which raises the question I had to answer for myself: if the enforcement layer was always available, why did nobody wire it up - me included?
Because it was not actually required. Humans were writing the code, and humans knew what to do based on the code already in the repo. They read it, understood it, and formed a mental model of the standard over a period of time. We did not tell a developer “you need to do this” more than once.
Agents broke that. An agent always starts with a fresh state. It has no mental model of the code repo, and it never builds one - every session is day one. So the mental model has to live somewhere the agent cannot skip. That is what the enforcement layer actually is: compiled mental models. Everything your team knows that can be written as code, compiled into gates the agent has to pass.
That is also why the goal moved. In 2025 the goal was to hand over as much of the task to the agent as possible. Now the goal is long-running tasks without any kind of intervention. When you are watching every step, you catch what the guidance missed. An agent running for hours on its own has to be caught by the gates.
Count yours
If your team ships with agents, do the count I did. Go open your own setup and count the number of mechanical gates and the number of probabilistic ones - the rules, the conventions, the prose you have written for the agents. If, like me, you don’t find any mechanical rules, then you know what to do: take every rule that is codeable and move it to the mechanical side, and let the prose carry only the judgement calls.