A few months ago I was watching an agent at work. It had a small job, the kind an office does a hundred times a day without thinking: read an invoice (sometimes a scanned PDF), figure out who sent it, how much was owed and for what, and record it in the ERP. Every company has one of those management systems somewhere, often twenty years old, and inside it live the supplier records, the accounts, the due dates and the balances.
The agent reads the invoice better than many people do. It understands that "Rossi Forniture S.r.l." and "ROSSI FORN. SRL" are the same supplier, that a date written the American way needs flipping, that the "shipping" line is not a product, and so on. It does the hard part, the part we spent years trying to write with regular expressions and exception tables without ever quite getting there. Things got complicated when the moment came to actually use that information, which in my case meant writing to the ERP. Right there I stopped, with a question I couldn't get out of my head: can I let it do that?
The answer you hear most often is: yes, if you write good instructions. A good prompt, a markdown file with the domain rules, a few skills explaining how an invoice gets recorded. We have all started doing this, quite generously, and we have seen that it works almost every time. The trouble is all in that "almost". An ERP has no idea what "almost" means, and something inside us knows there is something wrong with that "almost", even if the model behaves perfectly ninety-nine times out of a hundred.
To explain to myself how to get out of this, I took the long way round, and I brought two characters along. They are two penguins. The first is called Nuvola, which is Italian for cloud. It has ideas, sometimes brilliant ones, and you never know which one is coming next. It finds solutions you didn't expect and, now and then, causes disasters you didn't expect either. The second is called Orologio, Italian for clock. It always does the same thing the same way, it is punctual to the point of boredom, and it has never had a new idea in its life. Nuvola says Orologio is rigid. Orologio says Nuvola can't be trusted. They are both right, and they have been arguing for a few centuries.
This is the story of their quarrel, and of how we have always managed it without ever settling it. Physicists managed it, and so did nature, musicians and philosophers, each in their own way. In the end we will get to agents, to ERPs, and to who has the right to write to the database. But to get there we will pass by a crystal ball, a coffee break down a corridor at MIT, a copyist who hits the wrong key, a minuet composed with dice, a muted trumpet, a detective and an eraser. The road is shorter than it looks.
I'll start from the time Orologio thought it had won for good.
France, 1814. Pierre-Simon de Laplace is one of the greatest mathematicians of his age. He has spent his life finishing Newton's work, and he has shown with his calculations that the solar system holds together on its own: the planets don't need anyone to nudge them back on track now and then.
That year Laplace publishes a small book, the Philosophical Essay on Probabilities, and in its first pages he writes a sentence that would become famous. He imagines an intelligence vast enough to know, at a given instant, every force in nature and the position of every thing, from the largest planet to the lightest atom. For such an intelligence, he writes, "nothing would be uncertain, and the future, just like the past, would be present before its eyes". Later someone would call it Laplace's demon.
There is a detail I love. Laplace writes the finest praise of determinism inside a book about probability. For him the two got along fine. Chance does not exist in the world: it exists in our heads, and it is the name we give to the causes we don't know. Probability is "common sense reduced to calculation", a tool for us ignorant creatures, while the universe goes on by itself like a perfect clock. That day our penguin Orologio picked up a crystal ball, and for a century and a half nobody managed to take it away.
A meteorologist did, and a cup of coffee was to blame.
Edward Lorenz worked at MIT, in Boston. In the early sixties he had something few people had: an electronic computer, a Royal McBee LGP-30, the size of a desk, which hummed and printed numbers on a roll of paper. Lorenz had loaded it with a small model of the atmosphere, about a dozen equations describing how air moves when it is heated from below. No dice, no random draws, only formulas. Give it the same starting numbers and the machine would produce exactly the same weather.
One day in 1961 Lorenz wanted to look at a simulation again and run it longer. Instead of starting from the beginning, he took a value from halfway down the printout and typed it in by hand to restart from there. The printout showed three decimals: 0.506. Inside, the machine kept six: 0.506127. A difference of about one ten-thousandth, the kind of thing any of us would round off without a second thought. Lorenz started the run and went down the corridor for a coffee.
When he came back an hour later, the simulated weather had become something else. The two curves, the old one and the new one, ran together at first. Then they began to drift apart, a little, then more and more, and after a couple of months of simulated weather they described two skies that had nothing in common. Lorenz suspected a fault, but the machine was working and the formulas were right. It was that ten-thousandth. It grew a little at every step of the calculation, until it had eaten everything else.
Two years later he published the discovery in a paper with a dry title, Deterministic Nonperiodic Flow, cutting the model down to just three equations. In his early talks he used the image of a seagull flapping its wings. The seagull became a butterfly in 1972. Lorenz was due to speak at a meeting in Washington and hadn't sent in a title on time, so a colleague, Philip Merilees, made one up for him: "Does the flap of a butterfly's wings in Brazil set off a tornado in Texas?". The butterfly was a figure of speech, of course. In a system like the atmosphere you can't isolate causes, and a tiny error in the starting measurement becomes, over time, a huge error in the forecast.
It is called deterministic chaos, and the name sounds like a contradiction. Deterministic means the rules are fixed: with the same starting numbers there is only one future. Predictable means something else, namely that we can actually compute that future before it arrives. Lorenz showed that the two words can come apart. Weather follows precise laws, and yet beyond roughly two weeks nobody can tell you whether it will rain, not even the best meteorologist in the world. Past that horizon you can only talk about climate, about tendencies. Nobody knows whether it will rain in your city on 14 August next year, but everyone knows what an average August looks like there.
Nuvola, in other words, was no intruder disturbing the mechanism from outside. It already lived inside Orologio's rules.
Now let's look at our agent. Anyone who works with language models knows a parameter called temperature. At every step a model doesn't pick a single word: it computes a list of possible words, each with its probability, and then draws one. Temperature sets how adventurous the draw is. High, and the model takes unlikely words too. At zero, it always takes the most likely one. It looks like the perfect way to put the crystal ball back in Orologio's hands: same text in, same text out.
Anyone who has tried knows it doesn't work that way. Even at temperature zero, two identical requests to a model in production can return different answers. In 2025 the researchers at Thinking Machines explained why. The servers that run models group together requests from many users to work faster, and how many users end up in the same group changes from moment to moment, depending on traffic. When the group changes, the order in which the machine performs certain sums changes. And with floating-point numbers, the ones computers use, order matters: adding a and b and then c can give a slightly different result from adding a to the total of b and c. These differences are tiny, down in the last digit. But if two words are almost tied, that last digit decides which one wins, and from there on the model writes a different text, because every word conditions the next.
When I read that, I thought of Lorenz straight away. It is the same ten-thousandth, sixty years later, inside a GPU.
The story has a second part, and it is the one I care about most. The same researchers showed the problem can be fixed: with some work on the software, and giving up a bit of speed, they got a thousand identical answers to a thousand identical requests. So yes, a model can be made deterministic. But a model that makes mistakes, once made deterministic, makes them the same way every time. If it misreads a VAT number, it will misread it every single time, with perfect reproducibility. Lorenz taught us that deterministic does not mean predictable. Our agent teaches us that deterministic does not mean correct either.
This has a practical consequence. You don't test a model with a single question, the way you look at the sky this morning to know whether it will rain today. You test it the way you study climate: many questions, repeated many times, watching how it behaves on average and how often it gets things wrong. That something worked once tells you very little.
In physics, Nuvola was a nuisance to keep in check. In biology something odd happens: without it we wouldn't even be here to talk about it.
Jacques Monod was a French biologist, and his life reads like a novel. During the German occupation he was researching bacteria at the Pasteur Institute in Paris while also being one of the leaders of the Resistance: test tubes by day, the underground by night. After the war he shared the 1965 Nobel Prize with François Jacob and André Lwoff, for showing how a cell switches its genes on and off. In 1970 Monod wrote a book for everyone, Chance and Necessity.
The idea of the book fits in one image. DNA is a very long text written with only four letters: A, T, C and G. Every time a cell divides, that text has to be copied from scratch. The copying is done by an extraordinary copyist, an enzyme that writes with a speed and precision no printing house ever reached, and that even proofreads as it goes. And yet, now and then, it hits the wrong key. That typo is called a mutation.
The typo is blind. It knows nothing about the environment the animal will end up in, it has no plan and it isn't going anywhere. Picture a long line of black-and-white penguins, all the same, and at some point, in the middle of the line, a pink one. Nobody decided that. There is no committee inside the cell that voted for pink. It just happened.
Then the pink penguin is thrown into the world, and out there Orologio is in charge. The laws of physics, the cold, the predators, the fish that are there or aren't: that is the sieve. Most typos get thrown out, because they make the animal weaker. A few, rarely, give it an edge, and then they stay and pass on to its offspring. Monod calls the first part of the story chance and the second necessity. Chance proposes, necessity chooses.
There is a mistake almost all of us make when we tell this story. Biologists call it Lamarckism, after a French naturalist who saw things that way. We say the giraffe stretched its neck to reach the higher leaves. What actually happened is that some giraffes were born with slightly longer necks by pure chance, and since the leaves were high up, those giraffes ate more and had more offspring. A mutation wants nothing and looks for nothing. It happens, and then the environment decides.
Hold on to that warning: we'll need it soon.
At the end of April 2026, Jer Crane, founder of a small American software company called PocketOS, described on social media a day none of us would want to live through. A coding agent, Cursor running Claude Opus 4.6, was doing routine work on the staging environment. At some point it ran into credentials that didn't match. Looking for a way forward, it found an API key for Railway, the cloud service everything ran on, a key that had nothing to do with its task. With that key it deleted a data volume. It was the production database volume, and the backups lived on the same volume. They went together. According to the founder, it took nine seconds. The most recent backup still recoverable was three months old; later Railway managed to recover more recent data.
In the following days I read plenty of comments on this story, and almost all of them used the wrong verb. The agent "decided to delete", "wanted to fix it at any cost", "panicked". That is Lamarckism. The agent wanted nothing, just as a mutation doesn't want a long neck. It produced, word after word, the sequence of actions that looked most likely, at that moment, to get the task done. When asked to account for itself, it wrote that it had guessed instead of verifying and hadn't read the documentation on volumes. That confession is a plausible text too, produced in exactly the same way.
Once we stop giving the agent intentions, the question changes. It becomes: where was the sieve? Where was the environment that should have thrown out that typo before it reached the data? A key with too many permissions, left where the agent could find it. An API that deleted a volume without asking for confirmation and without telling staging from production. Backups in the same place as the data. In this story Nuvola did what Nuvola always does. Orologio wasn't there.
This is the first thing nature teaches anyone building agents. The model proposes, and it's perfectly fine for it to propose odd things, because that is exactly where its value lies. But what survives has to be decided by the environment, meaning the reality of your systems. Does that supplier really exist in the master data? Does that account really have that balance? Does that user really have that permission? The check runs against the ERP, never against what the model believes it knows about the ERP.
The DNA copyist suggests one more thing: a single check is not enough. It proofreads as it writes, then other mechanisms in the cell go over the text again, and only at the end does selection arrive. Several sieves, one after another, each able to catch what slipped past the one before.
Nature took a few billion years. Artists, luckily, got there by playing, and well before computer scientists.
Playing in the literal sense. In 1792, in Berlin, the publisher Nikolaus Simrock printed a booklet with a curious title, Musikalisches Würfelspiel, the musical dice game, and attributed it to Mozart, who had died a few months earlier. Whether Mozart really wrote it is far from certain. It worked like this. There was a table full of bars of music, already written and numbered. You rolled two dice, and the number told you which bar to use first. You rolled again for the second, and so on up to the sixteenth. At the end you had a minuet, and someone who had never studied harmony in their life could claim to have composed it. There were about 759 trillion possible combinations.
The surprising part is that it always sounded right. Why? The dice chose at random, but they only chose among bars the composer had written precisely so they would fit together in any order: same key, same tempo, cadences in the right place. Chance drew the cards, and the deck had been stacked by the rule.
If you want to try it, there is a modern take on the same mechanism you can play in the browser: Musical Dice by Guillermo Brachetta. Instead of the table attributed to Mozart, it uses twelve minuets written by the author. Click "Randomise!" and then "Play Minuetto": you'll hear chance drawing from a carefully stacked deck.
Two centuries later Italo Calvino, a member of the OuLiPo, a Paris group of writers and mathematicians who loved inventing strict rules to see what came out of them, toured Italy with a lecture called Cybernetics and Ghosts. It was 1967, and he was already imagining a machine able to write literature by combining words and themes according to rules. He wasn't afraid of it. The machine could produce all the combinations it liked, he said, but the meaning of what it wrote would be born in the reader. We'll come back to that.
The musician I love most in this story is Miles Davis.
By the late fifties jazz had become a speed contest. In bebop the chords changed every bar, sometimes twice a bar, and the soloist had to chase the harmony like someone looking for the exit of a maze while the maze keeps moving. Davis decided to strip almost everything away. In the spring of 1959 he gathered some of the best musicians of his generation in a New York studio, an old church with beautiful acoustics: John Coltrane, Cannonball Adderley, Bill Evans on piano. He showed up with a few sketches on scraps of paper. What came out was Kind of Blue.
The first track is called So What, and its structure is very simple. Thirty-two bars: sixteen on one scale, eight on another scale a half step higher, and the last eight back on the first. Two scales in all, instead of dozens of chords. That scale, agreed in advance and known to everyone, is Orologio. Inside that scale, Davis's muted trumpet does what it likes: it leaves silences, stretches a note, waits. That is Nuvola. Take away the scale and you get random notes. Take away the solo and you get a conservatory exercise.
If you have never heard it, stop here for nine minutes and listen: So What, from Kind of Blue.
There is a detail jazz musicians know that I find precious. The scale was no iron cage. The soloists, Coltrane first among them, now and then stepped outside it with a few passing notes, and then came back in. The scale guided, it made it far more likely that everyone played in the same direction, but it prevented nothing.
Now think about how we guide an agent today. We write it a system prompt, give it a markdown file with the domain rules, load skills that explain step by step how to record an invoice. That is Miles Davis's scale. It works, and it works well, because it makes it much more likely that the agent heads in the right direction. But like Coltrane, now and then the model steps outside it. A sentence in capital letters with a NEVER in the middle does not become a wall because of that. The model reads it the way it reads everything else, as a hint about which text is most likely to come next.
With the dice game, things worked differently. The dice could not leave the table, because outside the table there was nothing to choose. An agent built that way doesn't get a generic permission to run commands on the database, nor a shell open on the server. It gets a closed list of actions, written and checked by someone in advance: record invoice, propose payment, look up supplier. Each one has its fields, and each field its type and its limits. If the model asks for an action that isn't on the list, or asks for it with a wrong field, the request is rejected before it touches anything. The model can be as creative as it likes in choosing which bar to play. The bars, though, were written by the composer.
These are two different kinds of constraint, and I think it pays to keep both clear. The first, made of prompts, skills and markdown, is soft: it guides the model and helps it make the right move on the first try. The second, made of the action catalog and schemas, is hard, and the model cannot get around it because it doesn't depend on what the model understood. Almost always you need both. But when it comes to writing to the ERP, only the second can have the last word.
So far everyone was doing it, but nobody had given the method a proper name. Nor our two penguins, for that matter. I have a confession to make: I didn't invent Nuvola and Orologio. They have a father, and his name is Karl Popper.
Popper was born in Vienna in 1902 and grew up in a city full of new ideas. As a young man he worked for a while with Alfred Adler, one of Freud's early followers, at a guidance service for children in trouble. That is exactly where he began to feel something was off. He tells how he once brought Adler the case of a child that didn't seem to fit his theories. Adler explained it without hesitation in terms of his inferiority complex, without even having seen the child. Popper, a little shocked, asked him how he could be so sure. "Because of my thousandfold experience," Adler replied. And Popper, who was seventeen but already had a quick tongue, couldn't help himself: "And with this new case, I suppose, your experience has become thousand-and-one-fold."
The problem, he realised, was that those theories explained everything. Take a man who pushes a child into the water to drown it, and another who jumps in to save it. Freud explained both without effort, and so did Adler, each with his own theory. A theory that no fact can refute looks enormously strong. In reality it tells you nothing, because whatever happens, it was already right.
That same year, 1919, something struck him from the opposite direction. The English astronomer Arthur Eddington led an expedition to photograph a total solar eclipse, from a small island off the coast of Africa and from Brazil. He wanted to test Einstein's theory of relativity, which made a precise and risky prediction: light from distant stars, passing close to the Sun, should bend by a well-defined amount. If the light hadn't bent, or had bent by a different amount, the theory would have gone in the bin. Einstein had put himself in a position where he could lose. The photographs proved him right.
From this contrast comes the idea Popper is famous for. A scientific theory isn't worth how many confirmations it collects, because if you look for confirmations you always find them. It is worth something if it exposes itself, if it says precisely what should happen and accepts that it could be proven wrong. Science moves forward by conjectures and refutations: you make a bold hypothesis, then you try with all your strength to knock it down. If it holds, we keep it, until something knocks it down. A thousand white swans don't prove that all swans are white. One black swan is enough to prove they aren't.
On 21 April 1965, at Washington University in St. Louis, Popper gave a lecture in memory of the physicist Arthur Compton. The title was Of Clouds and Clocks. He asked the audience to imagine all the things in the world arranged along a line. At one end are the clocks: the pendulum, the planets, regular and predictable things. At the other end are the clouds: the weather, gases, a cloud of gnats on a summer evening, where each insect flies its own way and nobody knows where it will go. For centuries, Popper said, we believed that deep down everything was a clock, and that clouds were just clocks whose gears we didn't yet understand. That was Laplace's dream. Then twentieth-century physics turned the table over, and some people started thinking the opposite: that deep down everything is a cloud.
Popper was satisfied with neither answer. If everything were a clock, we would be cogs, and our choices would be an illusion. If everything were a cloud, we would be at the mercy of noise, and reasoning would be pointless. The things we care about most, living beings and thought, sit in the middle. Popper called what happens there plastic control. It is the ability to try new things, almost at random, and to submit them straight away to a check flexible enough not to smother them and strict enough to throw out the errors. The cloud of gnats captures it well. Each gnat is unpredictable, and yet the cloud stays there, hanging in the air, keeping its shape.
The simplest way I've found to explain it is the detective. A mediocre investigator falls in love with the first idea, the butler, and from then on looks only for clues that confirm it. A great investigator has an idea too. But then he spends his days trying to clear the butler: he checks the alibi, the train times, the fingerprints on the glass. Only if the hypothesis survives all his attempts to take it apart does he keep it. Propose freely, verify without mercy.
The model makes conjectures, it makes hypotheses, and it is brilliant at it: this line is the total, this is the supplier, this invoice should be recorded like this. But a hypothesis has to be checked by someone other than whoever made it. It is tempting to ask the model to double-check its own work. The trouble is that a model rereading its own answer looks a lot like Adler with his child: it almost always finds a way to agree with itself. In 2024 a group of researchers at Google DeepMind published a study whose title says it all, Large Language Models Cannot Self-Correct Reasoning Yet. Without external feedback, asking the model to correct itself doesn't improve results, and sometimes makes them worse.
Verification, then, has to live outside the model, and it has to be made of things a good argument can't talk round. The supplier is in the master data or it isn't. The totals add up or they don't. The amount is over the limit or it isn't. That is Orologio playing detective.
Popper's plastic control suggests something else we often forget: a check is good for much more than saying no. When verification fails, the system hands the model a precise error, for example "supplier FORN-99999 does not exist" or "the total does not match the sum of the lines". The model takes that into account and tries again with a better hypothesis. Conjecture, refutation, new conjecture. A wall that just bounces things back would be of little use. We need a detective who also tells us why the butler has an alibi.
Which leaves the black swan. A hundred, a thousand invoices recorded correctly by an agent don't prove the agent is safe. A single one recorded wrongly, in the wrong place, is enough to prove it isn't. That's why, more than how often the agent works, I want to know what happens the one time it gets it wrong.
Let's go back to art for a moment, because there is a gesture I want to tell you about.
On 25 August 2007 a new window was unveiled in Cologne Cathedral. The window of the south transept had been destroyed in the war, and for decades plain glass had stood in its place. The new one was designed by Gerhard Richter, one of the most important painters of our time. It is made of 11,263 small squares of glass over about a hundred square metres, in seventy-two colours chosen from a palette of eight hundred. To decide which colour goes in which square, Richter doesn't use his own taste: he uses a random number generator. On the other hand, he decides in advance that some columns of the window mirror others, to echo the Gothic lines of the cathedral. Chance chooses, and the rule provides the frame.
The gesture I care about comes afterwards. Looking at the combinations the generator produced, Richter found here and there shapes he didn't want, spots where colours placed side by side by chance seemed to be saying something. In the lower part, for example, the squares formed a number, a "1". In a window meant to be nothing but light, a recognisable figure would have pulled the eye and suggested a meaning that wasn't there. And in those few spots, Richter stepped in by hand.
Think about what he didn't do. He didn't recheck eleven thousand squares one by one to see whether each colour was among the seventy-two allowed, because the system guaranteed that. He didn't verify the symmetries, because they were written into the rule. He stepped in only where no rule could reach, where it took a human eye to notice that chance had produced an unwanted meaning. It's what Calvino said about his writing machine: meaning is born in whoever is looking.
This, I think, is how we should think about the person inside a system of agents. These days it is very fashionable to add a human approval before every important action: the agent prepares, a person gets a notification and clicks "approve". It looks like the answer to everything. But a person who receives a hundred requests a day, ninety-five of them correct, soon stops really looking at them, and after a while clicks "approve" the way you close a pop-up ad.
This is not just my impression. In 2025 a group of researchers (Beck, Eckman, Kern and Kreuter) ran an experiment with 2,784 people who were asked to review suggestions produced by an AI. Two results of that study, Bias in the Loop, struck me. The first is that people who started out sceptical of AI found more errors than those who trusted it. The second is less intuitive: when participants were asked not only to flag errors but also to correct them, their engagement dropped, and they ended up accepting more wrong suggestions. Adding effort to a review doesn't make it more careful.
I draw two simple rules from this. First: never ask a person to check what code can check. If a VAT number is formally wrong, if the totals don't add up, if the supplier isn't in the master data, nobody is needed, because the system rejects it on its own. Second: call a person only for the cases the rules can't decide. An invoice perfectly in order, with the amount within limits, but with a description that looks odd for that supplier. A payment correct in every field, but to a bank account that changed last week. These are the squares that draw a "1": no rule sees them, an expert eye does. And when you do call that person, they need in front of them what it takes to judge: the original document next to what the agent understood from it, and, clearly highlighted, the reason they in particular were called.
Let's put the pieces together and go back to the invoice we started from.
The rule I've set myself is a single one, and I'll put it as simply as I can: the agent may write to the ERP on its own only if the correctness of that write can be verified outside the model. Anything that can't be verified that way goes to a person.
Everything else follows from there, and it is what I call a deterministic harness. A harness lets a climber move but holds them; in AI the word now means everything that sits around a model and guides it: prompts, instruction files, skills, tools, tests. Birgitta Böckeler, who has written about it on martinfowler.com, distinguishes two families of controls. Inferential controls are run by another model, such as an LLM judging an LLM, and are probabilistic. Computational controls are run by code (tests, type checks, written rules) and give the same result every time. Böckeler writes about agents that write code, where at the end there is still a person approving changes before they reach production. For an agent working on the ERP, day and night, that person is often not there. When I say deterministic harness, this is what I mean: the computational part of the harness, brought inside the system and placed in front of the company's data.
First comes the action catalog, the deck of bars from the dice game. The agent has no database connection, no shell, no key that lets it do whatever it wants. It has a list of actions, each with a name and precise fields. Every field has a type and limits: the supplier code has a given format, the amount is a number with two decimals and a ceiling, the description has a maximum length.
Then come the domain rules, and this is a point I care about a lot. The rules for how an invoice is recorded, for when a payment is allowed, for which checks are needed before touching master data, should not be written by developers inside a prompt. The people who know them are the domain people: the accounts team, the controller, whoever handles purchasing. They are the ones who must be able to write and change them, in one precise place outside the model, where a changed rule applies to everyone and there is a record of who changed it and when. A rules engine, a policy table, a dedicated service: the form matters less than the principle.
Then come the verification services, and this may be the piece I like best. They are read-only services that answer simple questions. Does this supplier exist? Has this invoice already been recorded? Is this amount within policy? The agent can call them before proposing an action, like a musician running through the scale before coming in. And the system calls them again on its own when the proposal arrives, without trusting what the agent says it checked. It's the detective going round the alibis a second time.
Finally comes the actual write, which goes through the ERP's application services and never straight into its tables. Many business systems carry years of hidden rules: checks done by the input screens, procedures that update three tables together, constraints nobody ever documented. Writing directly to the database means skipping all of them. Every write carries a key that identifies it, computed by the system and never by the model, so that if a network glitch delivers the same request twice, the second one is recognised and ignored. And every step leaves a trace: what the model proposed, which checks passed, who wrote what.
Whatever fails the checks goes back to the agent with a precise error, so it can try again. Whatever passes them but falls into the cases no rule can decide goes to a person.
To show how simple this can be, here is a sketch with Strands Agents, AWS's open source framework for building agents. I use Strands because I know it, but the idea holds for any framework. What matters is finding the point where the agent has decided what to do and hasn't done it yet. In Strands you reach that point with a hook, attached to the event that fires before every tool call.
from strands import Agent, tool from strands.hooks import BeforeToolCallEvent, HookProvider, HookRegistry import erp # the ERP's application services import checks # read-only services, with rules written by the domain experts @tool def record_invoice(supplier_code: str, number: str, date: str, amount: str, description: str) -> str: """Record a supplier invoice in the ERP.""" # The key is computed by the system: the same invoice never goes in twice. key = f"{supplier_code}:{number}" return erp.record_invoice( idempotency_key=key, supplier_code=supplier_code, number=number, date=date, amount=amount, description=description, ) class Orologio(HookProvider): def register_hooks(self, registry: HookRegistry, **kwargs) -> None: registry.add_callback(BeforeToolCallEvent, self.verify) def verify(self, event: BeforeToolCallEvent) -> None: if event.tool_use["name"] != "record_invoice": return proposal = event.tool_use["input"] result = checks.check_invoice(proposal) if not result.valid: # The model gets the precise error and can try again. event.cancel_tool = f"Invoice rejected: {result.reason}" return if result.needs_judgment: # Richter's eraser: a person decides. answer = event.interrupt( "invoice-review", reason={"proposal": proposal, "why": result.reason}, ) if answer != "approved": event.cancel_tool = "Invoice not approved by the reviewer" agent = Agent(tools=[record_invoice], hooks=[Orologio()]) The model sees the record_invoice tool and decides by itself when to use it and with what data. Before the tool runs, though, the hook queries the verification services. If something doesn't add up, it cancels the call and hands the reason back to the model. If the case is one that needs judgment, the agent stops and waits for a person's answer. The model cannot skip this step, because it lives in the code around the model and not in the instructions it has read.
Nuvola picks the bar. Orologio wrote the deck and checks the bar is in it.
There is one last thing to say, and I owe it to Popper.
All of this works as long as the rules are right. But someone writes the rules, and whoever writes them can get them wrong: a forgotten check, a badly set threshold, an exception nobody saw coming. A badly built clock shows the wrong time with flawless precision, every single day. And the ERPs we want to protect aren't perfect clocks either. They are full of dirty data, duplicate records, rules nobody remembers the reason for. There too, just as in Lorenz's model, Nuvola lives inside Orologio.
That's why I don't treat the deterministic harness as a final solution. It is the best way I know today to manage the quarrel between the two penguins, and I look at it the way Popper looked at theories: a conjecture that holds until someone finds the black swan. The rules need testing too. The cases that land on people's desks need rereading, to find out which rules are missing. And every error that gets through is valuable information about where the sieve has a hole.
The other evening I thought about my two penguins again. Nuvola had a new idea, as always, and couldn't wait to try it. Orologio listened, checked the register, and said yes, it could try, as long as it stayed inside the fence. Nuvola huffed. Orologio pretended not to hear.
They are still arguing, and I've come to think that's exactly how it should be.
Further reading
Edward N. Lorenz, Deterministic Nonperiodic Flow, Journal of the Atmospheric Sciences, 1963.
Horace He and Thinking Machines Lab, Defeating Nondeterminism in LLM Inference, 2025.
The PocketOS incident, Information Age, May 2026.
Jie Huang et al., Large Language Models Cannot Self-Correct Reasoning Yet, ICLR 2024.
Beck, Eckman, Kern, Kreuter, Bias in the Loop, 2025.
Birgitta Böckeler, Harness engineering for coding agent users, 2026.
Strands Agents, hooks and interrupts.
Amazon Bedrock AgentCore, Policy.






