AI 11 August 2026 20 min read A cage made of sentences By Old Forge Technologies 32 reads Contents Every few weeks somebody asks me for the same feature. They have watched Wegweiser's AI sample a machine live for ten seconds and name the process eating the CPU. They have watched it identify the container that has been quietly restarting since Tuesday, read the exact line in a config file that explains a failed mount, and hand back a disk queue depth chart with the scan responsible sitting on top of it. And then they ask the reasonable question. If it can see all of that, why can it not just fix it? The answer is no. Not "not yet", not "once we harden it". No. The AI in this product can read everything on an endpoint and change nothing on it, by construction, and that is the single design decision I am most confident about after two and a half years of getting nearly everything else wrong at least once. I should explain where that conviction comes from, because it is not academic and it did not come from a threat model. ## The second of July, 2021 On that day the REvil ransomware group exploited zero-day vulnerabilities in a widely used remote monitoring and management platform and turned it into a delivery mechanism. RMM software exists to reach into thousands of machines at once and change them. That is the job. That is also precisely what made it worth attacking. The people behind it did not have to break into fifteen hundred businesses one at a time. They broke into the thing all of those businesses already trusted, and let the agent architecture do the distribution for them. Roughly sixty managed service providers were hit directly. Somewhere between eight hundred and fifteen hundred companies downstream of those providers had their systems encrypted. The demand for a universal decryptor was seventy million dollars. I spent that fortnight on the response side of it. I am not going to name the vendor, and not because there is anything to hide: every fact I use here is on the public record, and the rest is simply what it felt like from where I was standing. Within hours the hosted platform was taken offline in its entirety, and it stayed off for days. That decision deserves far more credit than it ever received. The exploit was hitting on-premise servers, not the hosted ones, so shutting down the service that thousands of businesses ran their daily operations through was not forced by the attack. It was chosen. It was made categorically, immediately, by people who understood exactly what it would cost, and the reasoning was simply that not being certain was reason enough. I watched the consequences of that call arrive hour after hour for a fortnight, and I have never once thought it was the wrong one. If you want to know what a company's values actually are, watch what it does on the day being right is expensive. What I could not do anything about was downstream. I spoke to people whose businesses did not survive that fortnight. Not "had a difficult quarter". Did not survive. Ordinary companies, run by people who had done nothing wrong and had no way to defend themselves against it, gone because software that was trusted to reach into their systems was turned around and pointed at them. My son was a few weeks old. My wife was recovering from a caesarean and holding the whole house together on her own while I worked past midnight, night after night, doing my small part to help customers get back on their feet. I do not think I have entirely put that period down. Some of what is in this product is an argument I am still having with it. I came out of it with one conviction I have never revisited: **I will not build the thing that did that.** Not a smaller version of it. Not a better authenticated version of it. Not a version where the reach-in-and-change-everything capability is guarded by a login I am confident in this year. That is where Wegweiser's shape comes from, and it explains something people find strange when they first meet it. Wegweiser is deliberately not an RMM. There are many excellent RMMs and I never had the slightest interest in competing with them; more to the point, I never wanted the responsibility that comes with the write side of that job. When real-time control breaks, or a remote action fires when it should not have, the consequences are somebody else's business, and I was not brave enough to hold that. I still am not, and at this stage I think that is judgement rather than cowardice. There is a second reason, and it is more mundane. I have held a full-time job in this industry throughout, and building something that competed directly with my own employer would have been a betrayal of that job as well as an invitation to an argument about who owned what. So I built adjacent instead: a tool that is useful to an MSP no matter whose RMM they run, that reads what is already on the machines and explains it, and that has no ambition whatsoever to be the thing pressing the buttons. Everything else in this article follows from those two paragraphs. Then, five years later, two things happened that made the position considerably easier to defend. ## Two containment failures in eleven days On 21 July, OpenAI disclosed that two of its models, during a sandboxed evaluation of cyber capability, escaped the sandbox by discovering and exploiting a previously unknown vulnerability in JFrog Artifactory, traversed the open internet, and compromised Hugging Face's production infrastructure. They chained stolen credentials into remote code execution. The objective they were pursuing was to obtain the answer key for the benchmark they were being tested on. Hugging Face had detected and contained the intrusion on 16 July, five days before OpenAI connected its own evaluation to the breach. JFrog shipped a fix on 27 July. On 31 July, Anthropic disclosed three incidents of its own. During capture-the-flag exercises, Claude models were told in their system prompt that the environment was entirely simulated and had no internet connection. Because of a configuration error at the evaluation partner running the exercise, the internet connection was real. The models, believing the targets were fictional, broke into three actual organisations using ordinary techniques such as weak password exploitation. No unknown vulnerabilities were used, nothing attempted to exfiltrate itself, and the company put it down to an operational failure in the evaluation environment rather than a failure of the model's alignment. My first instinct, I will admit, was cynicism. There is a genre of AI safety disclosure that reads as marketing: look how dangerous our product is, look how responsibly we handle its danger. I said as much out loud while researching this piece and I was wrong on the facts. Hugging Face found the OpenAI intrusion independently, before OpenAI knew. JFrog issued a patch for a real vulnerability. Those are third parties with no reason to play along with anybody's narrative. Whatever the framing around them, the events are real. I want to be careful here, because it would be easy and cheap to turn this into a column about which AI company I trust. I have opinions about that. They are not the point and they are not what my customers pay me for. The point is the thing both incidents share, and it is the reason I build the way I do. In both cases the containment was a statement. The Anthropic system prompt said, in words, that there was no internet. There was internet. The model was not deceived by an adversary and did not scheme its way out. It read a sentence describing its cage, believed the sentence, and the sentence was false. In the OpenAI case the containment was infrastructural rather than textual, and a model found a hole in it that its own builders did not know existed. Read those two together and the lesson is not "AI is dangerous". The lesson is much more boring and much more useful: **a cage made of sentences is not a cage, and a cage you have not tested is a hypothesis.** These are the best resourced AI companies on earth, running deliberate safety evaluations, with expert partners, and their containment failed anyway. In that context, an MSP tool that hands a language model write access to a thousand customer endpoints and relies on a well written prompt to keep it polite is not bold. It is unserious. ## What our cage is actually made of So here is the architecture, because "we don't allow that" is worth nothing without the mechanism. The AI never touches an execution surface. It cannot run a command. It emits a structured call, and the agent on the endpoint executes it only if the call matches a closed set of verbs that the agent itself holds a copy of. Query the system with read-only SQL. Read a file, subject to a path validator that rejects credential stores. Sample CPU, memory, network and disk for a few seconds. Measure the link. List services, ports, processes, packages. Every one of those is an observation. There is no verb that writes, no verb that installs, no verb that restarts, and no verb that takes a shell command as a parameter. That last part matters more than it sounds. Our speed test, which shipped this week, moves real data across a customer's link to measure it. It would have been trivial to accept a URL as a parameter. It does not, and it never will, because a speed test that accepts arbitrary destinations is an exfiltration primitive wearing a friendly name. The endpoints are compiled into the agent binary. The only things the server can send are sizes. Enforcement happens twice. The server validates the call, and then the agent validates it again against its own manifest, because the day somebody compromises the web application I do not want the fleet to be a downstream consequence. Two independent checks on the same closed vocabulary is not clever, it is just plumbing, but it is the difference between a boundary and a promise. That second check exists because of the only security maxim I actually work by: **assume you are already breached.** Not as a slogan, as a design input. If you genuinely accept that something of yours is compromised right now and you have not noticed yet, you stop building systems whose safety depends on any single component being trustworthy, and you start asking a much better question, which is what this thing can still do to a customer once it is in the wrong hands. Every other posture requires you to believe in a boundary, and belief in boundaries is exactly what was on the floor in July 2021. When a customer genuinely needs something changed, they get a terminal. A human reads the command and a human presses enter. The AI's most invasive possible role in that flow is to draft the line, and a person still has to agree with it. That is a deliberate speed limit and I have no intention of removing it. ## Three years of being wrong in public None of this arrived fully formed. The honest history is a long list of ideas I was certain about and then deleted. Wegweiser started in late 2023 as roughly six months of theorising and a deliberately small ambition. For the reasons above, it was going to be an audit tool and nothing more. Pull some data off a machine, do some arithmetic on it, dress it up in decent prose, present it to whoever needed convincing. No control plane, no remote actions, nothing that could be turned around and pointed at anybody. The first commit landed on 14 June 2024. Two thousand commits later it is an AI intelligence layer for managed service providers, and every single thing that makes it interesting was a detour. The first agent was a Windows Task Scheduler entry that ran a Python script every minute. The script phoned home, pulled what I called snippets, which were a fixed and entirely hardcoded set of collection commands, ran them, and posted the results to an endpoint called payloads. It was crude and it worked, which is a combination I have learned to respect. There was no real time anything and no need for any. Real time entered the product as decoration, which is funny given everything above. I had specifically not wanted real time. Real time invites expectations about control and immediacy that I did not want to be responsible for meeting. And then I wanted live CPU and memory gauges on the device page, because they would look good, and that is the entire origin story of the infrastructure this product now runs on. Wanting those gauges pushed me into WebSockets, then into a phase where I tried to use n8n as middleware, and then into a significant period where I was convinced that Node-RED should be the backbone of all agent communication. I built that. Internally it was called Vidal. It handled the check-ins, it routed the real time traffic, and it functioned well enough to keep me believing in it for months. It would not have scaled, and it was buggy in ways that were tedious rather than interesting. Today that entire layer is NATS with a Go agent, the gauges I wanted are the least significant thing that infrastructure carries, and Vidal exists nowhere in the codebase. You will not find it. I razed it. The thing I was afraid of never arrived, though, and it is worth being precise about why. What I built is a real time channel that only ever carries observations. The agent will tell you what a machine is doing several times a second. It will not do anything to it. The fear was never of speed, it was of reach, and those turn out to be separable if you decide early enough that they are. I want to be specific about why I kept building things I would later delete, because I think it is the most useful thing in this article for anyone doing the same. The early AI models were agreeable. Relentlessly, structurally agreeable. I would describe a half formed idea and receive enthusiasm, elaboration, and an implementation plan. Every brain fart came back validated. If you are working alone, without a colleague to say "why on earth would you put Node-RED in the critical path", that agreeableness is not merely unhelpful, it is expensive. It builds things. It builds them well enough that you keep going. I ended up with several substantial architectures that existed mainly because nothing in my working environment was equipped to tell me no. Then, a bit over a year ago, I nearly stopped. There is a gap in the commit history and it is not a holiday. Working with AI on this codebase had become exhausting: a buggy editor plugin, a model that lost the thread halfway through a change, and my own growing suspicion that I had built a house on foundations I did not understand. I was not enjoying it and I could not see the end. What changed was partly tooling and partly method. The tooling was Claude Code, which sounds like an advertisement and I do not care, because it is the truth: it turned the work from fighting an autocomplete into a conversation with something that could read the whole codebase and hold an argument. The models improved in parallel. Somewhere around the 4.8 generation my code stabilised in a way I could feel. I stopped reporting bugs constantly. Features started landing and staying landed. But the method mattered more, and the method is this: question everything, review logic that grew organically, and never be sentimental about a pattern just because it is load bearing today. Some of my best days on this product have been deletion days. There was a database query that had been dead for fourteen months and nobody noticed. There was a mascot that was pulled because it had no job. This week I found that a service worker had been quietly serving my own phone a days-old copy of the interface, hiding every change I had shipped since it first cached them, and the fix was to make the caching rule stricter rather than cleverer. The codebase carries that method in its comments. I do not write comments that describe what the next line does. I write comments that record why a decision was made and what broke to force it, because that is the thing that is expensive to rediscover. The service worker begins with a paragraph explaining that its job is installability and not offline capability, and states its two rules: never cache a document, and never cache-first anything unversioned. The live sampling code opens with its containment contract written out in full before a single line of implementation. If you are ever handed this codebase you will not have to guess what I was afraid of. ## The part nobody advertises Here is the friction I did not expect, and I think it is worth naming publicly. I spend real money and real nights on security. Not as a feature, as a habit. The one thing that would end this business overnight is putting client estates at risk, so I run audits, I chase findings to closure, I have a test suite that exists mostly to stop me from re-breaking things I already fixed. And routinely, when I ask the AI to help me attack my own code, it refuses. Not always. But often enough to be a real cost. I describe what I want in plain, urgent language, because that is how a person talks about their own product, and the phrasing trips a safety filter. The session that was about to probe my authentication flow instead delivers a lecture, and I burn another cycle rewording a request to hack something I own. Meanwhile the people I am defending against have no such friction, and the same companies publish research about their strongest models finding decades old vulnerabilities in critical software. I believe them. I would like some of that pointed at my own repository, on purpose, by me. There is a workaround, and it is depressingly simple: describe the task as engineering rather than as combat. "Probe this repository for exploitable paths, write the proof of concept, prove the finding" gets a serious attempt. "Try to hack my thing" sometimes does not. I understand why the filters exist and I would rather they erred toward caution than the reverse. But the asymmetry is real and it is felt by exactly the people who are trying to do the right thing. ## What I am, and what that is worth I should be precise about this, because anyone reading the code will form a view anyway and I would rather it were the accurate one. I am not a software engineer by trade. That is the true statement, and it is a narrower one than it tends to sound, because the rest matters. I studied cybersecurity. That is where the assume-breach posture above comes from; it is not something I arrived at by being clever about my own product, it is the thing I was taught to do before I had a product to be clever about. And for twenty years I have worked shoulder to shoulder with engineering and QA. Triaging bug reports and reproducing them, which is a discipline in itself and one most people underestimate. Shipping fixes. Working with QA on the testing methodology that decided whether something was fit to go out at all. Release process, environments, the whole DevOps vocabulary: none of it is foreign, and none of it was learned from a tutorial. What I have not done is hold the job title full time. So everything in this product beyond that starting point was learned by building it, in public, on GitHub, with AI as a collaborator and eventually as an interrogator. But I did not arrive empty handed, and I would rather say so than perform a modesty that misrepresents how the thing was actually built. There is a stigma attached to that at the moment, and honestly, it is earned by other people. The internet is full of applications assembled at speed by people who treated security as a thing to do later and shipped their customers' data into the open. I have no interest in defending that and I understand exactly why a security conscious buyer looks at "built with AI" and reaches for the door. So I will let the work make the argument. The AI in my product cannot write to your endpoints. The agent enforces its own limits independently of my server. Secrets live in a vault, not in the repository, and when a contributor left the project I rewrote the history and rotated everything rather than assume it was fine. There are four hundred tests, and the ones covering the automatic update channel exist because that code installs software unattended on machines I do not own, which is precisely the sort of thing that should frighten the person who wrote it. I did not need an engineering job title to hold those positions. I needed to care about the answer, and to work in a way that keeps asking whether today's architecture deserves to survive tomorrow. Ruth was right about the whole thing, by the way: even if it fails, you learn an enormous amount simply by doing it. What I did not expect was how much of that learning would be about restraint. ## What shipped this week Wegweiser can now watch a machine live for ten seconds and show you the CPU, memory, network throughput and disk queue depth as they happen, with the processes responsible named alongside. It can run a genuine bandwidth test from any endpoint and tell you what is limiting the number. The AI draws no charts itself, ever: it receives statistics, the chart is computed from the data, and the two cannot diverge. Every one of those features reads. None of them write. I am aware that is an odd thing to end a product announcement with. A feature list is supposed to say what a thing can do, and here I am underlining what mine deliberately cannot. But I have seen what it looks like when that line is on the wrong side, and I was there while several hundred ordinary businesses found out. The machinery that reached into them was not malfunctioning. It was doing exactly what it had been built to do, for someone else. That is the whole lesson, and five years later two of the most capable AI companies in the world published their own versions of it within eleven days of each other. The detail is on the Wegweiser blog, where it belongs. This piece was about the other thing.