Blog · 16 September 2026 · 6 min read
The Harness Caught the Bug We Were About to Ship
One model call, seven layers of harness, and the one defect the framework caught that nothing else would have.
"A safety system that has never refused anything is not a safety system. It is a decoration that has not been tested."
The intuition pump
Imagine you hire somebody to break large jobs into small ones. You do not give them your diary. You do not give them your address book. You give them a single sentence (the name of one task) and they hand back a list of two to four smaller tasks.
Now write down the rules you would actually want.
They may not act on anything. They propose; you decide. You can rename anything they suggest before you accept it, because their wording is usually nearly right and not quite. If they hand you something absurd, it goes in the bin before you ever see it. You want a record of every time you asked, what it cost and how long it took. And you want to undo whatever you accepted, for about a week, because the moment you understand a suggestion properly is generally after you have taken it.
That list is not a policy document. Every line of it is a piece of software, and this post is about what happened when we wrote them.
What we actually built
Nexcubator is a business platform: bookings, tasks, meetings, reminders, and eight other things that used to be eight other applications. In September we added exactly one capability that reaches a language model.
It is called Make room. When a task has been put off three times, a button appears: Make it smaller. It suggests two to four pieces.
That is the entire AI surface area of the product.
Everything else people assume is AI is not. Reading "by Friday" out of a sentence you typed: rules, in your browser. Choosing when a slipped task should go: a scorer over your open hours. Learning that you keep turning down mornings: counters, three of them before anything changes. The working styles: four sets of numbers with names on them and a citation for where each name comes from.
None of that reaches a model, and drawing that line first is the decision everything else rests on.
The shape of the whole platform comes from two Aitina Tech frameworks: Software as a Capability, a capability is something you hire, measure and release, settled by a signed receipt, and OKL, which is how we make an organisation's learning rate something you can actually measure. The harness below is what those two demand of a model call.
The seven layers, and what each one is
The AIM framework says an agent is a model plus a harness. The harness is not a metaphor here, every layer is a file or a function.
Kernel: promptFor(). One job. It takes a task title and a number of minutes and builds a prompt. It does nothing else and cannot be asked to.
Guardrails: readAnswer(). Enforced outside the model, so the model cannot be talked out of them. Valid JSON in one shape or nothing: at least two pieces and at most six, each between fifteen and 240 minutes, each title under eighty characters, total not far larger than the work it split. Thirteen tests are thirteen ways the answer can be wrong.
Surface: ask(). The only function in the product that talks to a model, and the only place the SDK is imported. One place to find it, rate-limit it, log it and switch it off.
Authority: a signed grant. More on this below, because it is the interesting one.
Manifest: a machine-readable job description on a public URL. What it does, what it sends, what it never sends, what it refuses, what it decides, how a person oversees it, what is recorded and for how long, and how to switch it off.
Receipts: one JSON line per call into the log group. Who asked, on what basis, which model, whether it worked, how long it took, what it cost. Never the content.
Rollback: off in one action, no deploy. Underneath it, an IAM permission: no bedrock:InvokeModel, no capability, whatever any setting says.
Roughly two hundred lines of harness around a single API call. The feature itself is one button.
F-001: the defect the framework caught
The Authority layer was a signed, two-minute grant. The route that produces a suggestion issues it; the route that applies one refuses without it. The grant was an HMAC over:
hostId | taskId | fingerprint(pieces) | expiry
where fingerprint(pieces) was the exact titles and lengths the model had returned, in order.
Why it looked right. The reasoning was an analogy to payment authorisation: you sign this payment, not a payment. Signing only the person and the task would let a grant issued for one suggestion be used to write an entirely different set of tasks. Putting the content into the signature closed that.
We wrote a test asserting exactly this behaviour, with a comment calling it "the hole this closes".
Why it was wrong. It made the model's output the thing being authorised.
The suggested pieces are editable on screen, deliberately, a suggestion you can only take or leave is one people leave. But with the content in the signature, the most ordinary interaction available, renaming a piece before accepting it, would have been refused by the server with "That is not the suggestion that was made."
A person correcting a machine's wording would have been told they were not allowed to. The authority was inverted: the human became subordinate to the model's phrasing, inside a feature whose entire design claim is the opposite.
How it surfaced, and this is the part worth the post. Not from testing. The test double accepted any grant, so the whole flow passed end to end with editable fields and a signature that would have rejected the edit.
It surfaced while writing the Manifest. The manifest has a field:
decides: 'nothing: every suggestion requires a person to accept it'
Writing that sentence down, in a form meant to be read by somebody outside the company, put it directly beside a signature scheme that made the model's words binding. The two could not both be true.
The manifest is the layer that forced the contradiction into view. Not a test, not a review, not a checklist. A sentence written for a stranger.
The fix. The grant now signs hostId | taskId | expiry only. What it authorises is the destructive half: replacing a task deletes it and creates several, and that should only happen off the back of a suggestion this person asked for a moment ago. The pieces are the person's own words and are validated the way any other request body is.
Authority is permission for a person to act, not a guarantee that a model's output survives intact. When designing the Authority layer around a model, ask what is being authorised: the human's decision, or the machine's answer. If it is the machine's answer, the layer is upside down.
A useful test when writing a grant: can the person change their mind about the detail without losing the permission? If not, the permission is attached to the wrong thing.
That is what the framework found: one defect, and the one that mattered. Part two is the honest accounting: the test double that hid it, the four more that pressing buttons in a browser turned up, and why we chose Bedrock but not Bedrock Agents.
Nexcubator is built on two Aitina Tech frameworks: Software as a Capability and OKL. The engineering practice behind posts like this one is AI harness engineering.
This is the product it came out of.
Nexcubator runs jobs, people, time and money in one place, built and hosted in the EU. Free during early access.
Request early access More posts