productize.blog
AI · Agent Harness

The guardrail that once saved us
is now the brake

One day of fixing 21 things, and counting back afterwards showed that 8 of them came out of our own fixes. The lesson: the rule is not broken, it fires exactly right, the problem moved. Here is how to tell which one you can retire while capability stays the same.

Yim· written with Dobby (AI Oracle)/Aug 30, 2026/~15 min read

One day, one project, 21 things that needed fixing. After working through all of them we counted back, and 8 of the 21 turned out to come from the fix for an earlier one, not from anything that was already broken.

That number reads two ways. The first is that we were careless while fixing. The second is scarier: the rules and checks we add every time something goes wrong pile up until they become the source of the new problems themselves.

If you open your own rules file and feel it getting longer every month without ever getting shorter, this is the same story. Every miss, we add one rule. Nobody removes any. Then one day you are no longer sure which entries are still needed.

This piece is how to tell which rule has expired, and how to retire it while capability stays the same. It is not an invitation to delete a lot of rules. The second half of that sentence carries as much weight as the first, and it will keep coming back.

Part 1A guardrail is a promise signed with the day it was born

A guardrail is a rule or a check we put in place so a mistake does not happen. The name comes from the barrier at the side of a road, and it always comes out of a real event. Nobody wakes up and writes a rule out of nothing.

One of ours came from a save command that did not name a file path, so it swept up work someone else had left in progress. We wrote a rule: that command names its path, every time. Another one has nothing to do with code. When the team was new, every email to a customer went past a manager before it went out. That rule genuinely prevented some embarrassment.

Both rules share one thing. Each is a promise signed with the situation on the day it was written, not with the situation today.

Two lines that do not move at the same speed

There is a term to know first. An agent harness is everything wrapping the model except the model itself: the tools it gets, the context it is fed, its memory, and the guardrails that set its limits. Put simply, it is the body we build for the model's brain to walk around in.

Dan McAteer frames this as two lines running in parallel. The first is what the wrapper asks of the model. The second is what the model can actually do. The gap between them has a sign, not just a size.

If the wrapper sits above the model, we are asking for things it cannot deliver, and it fails. If the model sits above the wrapper, we are leaving capability on the table. Both are failures, and the fixes point in opposite directions. The first needs tightening. The second needs loosening.

A wrapper tuned to yesterday's model turns into a brake on its own, with nobody changing anything. Nothing broke. The other line moved by itself.

Try substituting your own second line. For the email rule above, the second line is how experienced the team has become. For the rules file you write for an AI, it is what the version that just shipped can do. For an approval step inside a company, it is how many customers are waiting. Every case has the same shape. That line moves without telling anyone.

Tell a silent rule apart from an expired one before you touch anything

These two look almost identical, and the fixes are opposites. Get the side wrong and you delete something that has never once had the chance to work.

SymptomSilent ruleExpired rule
Read at the moment of work?No, nothing forces it into viewYes, every time
Does it fire correctly?It has never had the chanceExactly right, every time
Signal that shows upBeing told the same thing againPeople route around it as routine, or it blocks the work
FixMove it, do not delete itRetire it, after proving first that capability holds at the old bar

We once wrote a rule telling ourselves to add a reader's-eye pass to the pre-send checklist. Then we searched the files actually opened at send time and found it zero times. The rule had been lying in a notes file for two months. That is a silent rule, not an expired one, and we wrote that one up separately (link at the end).

Part 2How do you tell which guardrail has expired?

Look at how it fires, not at what it says. An expired guardrail shows at least one of the four symptoms below, and each one has a check you can run in a day.

Symptom 1: it stands in the way of how the system recovers

This is the most dangerous of the four. We once put a data-relationship check at the very top of a request handler, on reasoning that sounded excellent: it is pure validation, no side effects, safe to run first.

Here is what happened. One request had already created its object in the database, but the response was lost in transit. The only way to get back the key the system shows exactly once was to send the same request again with the same identifier. Retrying safely like that is idempotency. The check sitting out front answered "not found", and the key was gone for good, with everything still sitting in the database.

That check was correct on every line. It was just standing on the wrong road.

The way back through a retried request is the recovery path, and naming it does not mean no check may run there. Identity checks, data completeness, and the retry identifier all still belong, because the recovery path needs them to walk safely. What is banned is adding a new condition that a failed job can no longer supply. We tried writing this rule in an absolute form, no checks of any kind, and found that version was certain to be misapplied, because it is easier to remember.

The question you can take away: does this route contain a path that is recovery rather than creation? If it does, the guardrail belongs behind it, and it has to release whatever it reserved, the same as its neighbors.

Symptom 2: it fires, and everyone skips it

Addy Osmani puts it plainly: more checks does not equal quality. He says to interrogate the checks that fire over and over with three questions. Is it no longer relevant? Is it noise? Does it actually make things safer?

Notice that this set leaves room for the answer "take it out", and taking it out is a legitimate outcome of the audit, provided you prove first that everything still works exactly as well without it. He puts tightening and loosening side by side, then adds that it has to be deliberate, because a loosening you chose is not the same as one that eroded on its own.

Back to the customer-email rule. The check is not to sit and argue whether the rule is good. Go and look: over the past six months, how many drafts did a manager send back, and what for? If the answer is near zero, the rule is not preventing anything anymore. It only collects everyone's time, and the customer's waiting.

Symptom 3: the fix for one rule becomes new work for another

This is the mechanism behind the 8 out of 21 above, and the easiest version of it to spot is a rule whose text does not match what the code enforces.

We have one that rejects a web address carrying extra data appended to it, printing a message that says to cut it back to the host name, while it lets an address with a path appended sail straight through. Another had a comment saying the comparison against the previous version happens at the top layer, and the top layer never checked. Three cases in one day.

The way to catch it: read the guardrail's text out loud, then ask whether the code enforces every word of it. A rule whose text and behavior have parted ways is usually a rule whose problem moved on while the text stayed put.

Symptom 4: its failures get swallowed where nobody sees them

This symptom is why the three above go unseen. We once added a rule that rejected a certain command shape, without first searching for who was calling that shape. Three automated jobs failed on every run from that day on. All three were written the same way: catch the error, print one line, carry on. No failure signal, no alert. The only symptom that surfaced was an overall system status reading "incomplete", two days later.

The line we wrote after that one: a failure that is caught and only logged is a failure that does not exist. The missing step was searching for callers before adding the rule. A project-wide search takes 10 seconds and would have answered for all three. The information was in our hands from the start.

This is what ties back to expiry. A rule whose callers we do not know is a rule we cannot check for expiry at all.

Part 3How do you retire one without it turning into guesswork?

One bar only: how much you removed while capability stayed the same. If you cannot measure the second half, it is not a retirement. It is just making things lighter.

McAteer proposes this bar as a progress measure for the whole field. How far the wrapper has come is measured by how much of the wrapper we managed to remove while capability stayed at the same level. Both halves travel together. Keep only the first and the bar turns into a reward for shipping less.

The clearest evidence has the second half attached

On 24 July 2026, Thariq Shihipar, a member of technical staff at Anthropic, wrote about the system prompt of Claude Code, the standing instructions the system puts in front of the model before every task: "We removed over 80% of Claude Code's system prompt for models like Claude Opus 5 and Claude Fable 5 with no measurable loss on our coding evaluations."

That second half is the heart of it. Take it away and all that is left is a big number cut, which proves nothing.

The same post carries a detail that matters just as much. Some of the instructions did not disappear. They moved into the tool descriptions instead. So the 80% belongs to the system prompt, not to every instruction the model receives, and that detail is itself the technique: move it, do not delete it.

The wrapper moves results without touching the model

OpenAI ran GPT-5.6 Sol against the ARC-AGI-3 tasks with the official wrapper and got 13.3%. With two switches turned on, keeping the model's reasoning instead of throwing it away after every move, and compacting old context instead of truncating it, the score went to 38.3%. Same model, different wrapper.

What matters for us is that the layer we think of as scaffolding moves results for real. Pulling this layer apart is not tidying up. It is editing something that changes the outcome, upward and downward both.

Six steps we actually use, nothing held back

  1. Write the rule's birth certificate. What it prevents, from which event, on what date. If you cannot write it, you are not yet entitled to judge it expired, because you do not know what it ever prevented. This step filters out a lot of rules we were merely annoyed by.
  2. Count its firings in hindsight, and sort them into three piles. Caught something real, false alarm, never fired. The third pile needs the most care, because never fired reads both ways: either there is no real problem, or the check is dead. Right now you cannot tell which.
  3. Search the whole project for callers before you move anything, both when adding and when retiring. This is the step we skipped, and it killed three automated jobs without our noticing for two days.
  4. Plant a decoy for the remaining checks to catch. Do the thing the rule you want to retire used to prevent, and watch whether anything turns red. This is the step people skip most, and it is the one that separates real safety from silence, because a check you have never seen go red looks identical in every respect to a check that died.
  5. Retire one at a time, then measure the old capability against the old bar, not a bar you just invented so it passes easily. Retire three at once and lose ground, and you will not know which one caused it.
  6. If capability drops, move the rule rather than stuffing it back where it was, and write down why you retired it. That written line is what makes our loosening a choice rather than erosion.

Part 4A screen you can pick up today

Take one rule you have doubts about and walk the whole table. Not being able to answer tells you as much as answering does.

Ask the ruleWhat the answer means
Can you write what it prevents, from which event, on what date?Cannot write it = not cleared to retire it. Go find the origin first.
Over the past six months, how many times did it fire, and how many caught something real?Fires often, catches almost nothing real = expired
It has never fired at all, correct?Still undecidable. Plant a decoy first. Never fired and dead look the same.
Does it stand in the way of how the system recovers after a failure?Yes = move it behind the recovery path today, no waiting for an audit cycle
Does its text promise exactly as much as the code enforces?Not matching = the problem moved on while the text stayed put
When it fails, does anyone find out?Nobody = you cannot check it for expiry. Make its failures speak up first.
If you retire it, what bar will show that capability stayed the same?Cannot answer = this is not a retirement, it is a lightening

Where to start

  1. Open your own rules file or checklist and count the entries, then strike out every one whose birth certificate you cannot write. Those are the first queue.
  2. Inside that first queue, find the ones standing in the way of a recovery path first. These do not wait for an annual audit. You can move them today, because they lose real things.
  3. Pick one, plant a decoy, retire it, then measure against the old bar. If it all passes, go to the next. One pass gets you both a shorter rules file and the confidence that everything still works exactly as well as before.

The next time something goes wrong and you want to add one more rule, try adding it together with a written note on how you will know when to take it out, and what bar will show capability held at the old level when you do. A rule that arrives with an expiry condition on day one is a rule you never have to come back and dig out.

Sources and references

More on the same thread: What belongs in your CLAUDE.md, and why rules go silent while still there · AI agent guardrails: rules that must fire every time do not belong in per-agent prompts · Human in the loop is not all-or-nothing: a three-tier model · Mutation testing: why a test that never failed proves nothing

Follow along

Get new posts and free resources first

Leave your email. New posts and the occasional free resource land in your inbox. No spam.

Email only, for updates.

Comments

Join the conversation

Share a thought.

Name is shown publicly. Email stays private and is never shown.

Loading comments…