AUKINFOField Notes
← The Series

Article 03

Guardrails and Poka-Yokes

The choice is guardrails or guardrails.

Everybody talks about AI guardrails — a way of keeping your agents under control. Honestly, at the start I didn’t pay guardrails much heed. Then I learned the hard way: the choice is guardrails or guardrails.

Left to its own devices, an agent will find the most efficient route from A to B. This behaviour can manifest in many forms: repetitive and unmaintainable monolithic code with hardcoded semantics; skipping steps in workflows; dangerous assumptions; failure to follow instructions; telling you a task is complete when actually it was too difficult, so it made the whole thing up. Essentially anything without a failsafe is potentially at risk.

There are a few things you can do to provide guardrails. Some temporarily make you feel better but are useless; others work.

First, what doesn’t work

Claude.md / Agents.md / memory files / READMEs and the like. Put your rules in here — “always do this, never do that” — completely unreliable for implementing workflows using skills. Similarly, ‘memory’ files: I lost count of how many times serial workflow issues were written to memory. LLM memory is useless as a quality control layer. You have to go deterministic.

Walls

The simplest way to prevent a bad action is to make it unavailable.

The first wall is the tool surface. Rather than give an agent access to the codebase, I exposed the system’s capabilities to agents through MCP — a controlled set of tools with typed inputs and defined behaviour. Underneath, everything is routed through the service layer, which means that, in theory, there is exactly one bullet-proofed path to fetch a page, persist an entity or run a quality check. This is harder to ensure when working with skills, due to the agent’s free rein.

The second wall is enums, everywhere. Any field with a finite set of values — a status, a type, a category. An enum is a fence around the output space, and a narrower output space is an entire class of bugs that can never occur.

Walls are cheap and they compound. Every degree of freedom removed is a quality minefield removed. Walls also require centralisation of logic and pathways, encouraging DRY, robust programming.

Poka-Yoke — the design-based solution

The Japanese invented the ‘poka-yoke’ concept to solve human error in industrial manufacturing processes. It involves designing the system to prevent the error from happening in the first place, or immediately stopping the process so it can be corrected. For example, the clipped corner on a SIM card prevents users from accidentally inserting it incorrectly.

I used poka-yoke to make it impossible (or difficult) to perform an act without hard proof that the preceding steps have been taken. For example, many third-party agentic search services work on the basis of the SERPs themselves, or a paraphrasing of the actual target content. These services do not actually seek and find the real target content. Therefore you cannot be sure that data is actually present on the target document and not paraphrased or hallucinated. So what can you do? Answer: when performing any database write, an agent must provide the load-bearing verbatim text extract fetched from the target document, and a second agent must verify the text before the next action can proceed. Simple and effective.

Another example is ensuring that agents have read the necessary context from the semantic layer. For example, if you want to understand the regulatory impact of an industrial event — say, the issuing of a ‘land permit’ for a data centre in Spain — how would you compare this to the issuing of a similar permit in France? Does this mean both data centres have permission to move into construction? This problem can be solved by tight regulatory definitions in the semantic layer and ensuring your LLM has read the relevant part of the semantic layer during its analysis. How can you be sure? You implement a ‘proof-of-read’ gate, similar to the proof-of-fetch above. If the agent can’t verbatim quote the relevant regulatory text from the semantic layer then the database cannot be written to, simple.

Alarms

You will not think of everything straight away. For every solution there should be a test to prove it works across all your imaginable scenarios, and an alarm for when the guardrail fails. This provides the feedback loop that tightens the ratchet. Fail loud and fail early. The last thing you want is production errors discovered six months later.

However you are fighting the LLM on this one. Coding harnesses are designed to write code that doesn’t fail. ‘Soft landings’ are everywhere — default values, fallback parameters, backward-compatibility branches that keep the pipeline flowing when something is missing. This is poison in your quality. If key data is missing or defaulted, you need to know.

For what it is worth, you can instruct your agent not to write code like this [and it will write it anyway]. Its far better to use post-processing to look for these fallbacks and cruft patterns in the code — either using an agent or deterministically at gate-time, i.e. commit or push.

There is an (elegant) exception to every rule. Sometimes I give the agent permission to lie, with confession. Some failures are not worth stopping the whole flow for. Allow an imperfect result, and require it to be flagged. The mismatch surfaces as a visible signal in the audit instead of a hidden error in the data.

Gates

The backstop: encode it once at a boundary and enforce it forever.

My boundaries were the commit and the push. Nothing reached the remote without clearing a set of automated checks, and every check was a lesson learned the hard way and then nailed down so it could never recur. I had some basic checks - no credentials, no secrets, no hardcoded colours; every enum needs a description in the semantic layer; and strong type-checking and linting. A curated set of tests has to be green before a push is allowed, and nobody pushes straight to the main branch — it goes through a branch and a review. Tests are cheap and fast to implement.

You can also lock out regression. Every time something bad happens, the routine shoudl be the same: ask the agent why, fix it, and then write the test that makes that specific failure impossible to reintroduce. The fix solves it once. The test keeps it solved. Do that for two hundred days and your gates become a sedimented record of every mistake the system is now incapable of making — the ratchet at work.

Conclusion

Build a world in which your agents can operate safely, and you can move forward confidently.