One trajectory looping over a mountain range at sunset — the same path, drawn again and again
The mechanics

Deterministic
by construction.

A language model is a wonderful reader and an unreliable accountant. So it never does the arithmetic here. It shapes the question — which rows, which grouping, which window — and ordinary, testable code computes the answer. Everything below is a mechanism you can point at, not a principle we hope to keep.

you ask

“How much did we invoice in March?”

the model fills in a validated object
sourceinvoices
measuresum(total)
window2026-03
groupnone
no query string is assembled — there is nothing to inject
code walks the rows
Vermeer Studio€2,400
Kamerbeek B.V.€1,150
Noord Design€3,800
De Jong & Zn€950
from 4 rows€8,300
Illustration of the real path — sample figures, your own rows never leave your workspace.
Where the answer comes from

The model frames it; code counts it.

Ask “how much did we invoice in March?” and the model doesn’t answer. It fills in a constrained query specification — a small, validated object naming a source, a measure, a grouping and a date window. Plain JavaScript then walks the real rows and adds them up.

That single choice removes two whole classes of failure at once. There is no SQL for anyone to inject, because no query string is ever assembled. And a total can’t be hallucinated, because no total was ever generated — it was computed, and it comes back with the exact rows it came from.

debit
Bank€1,210
total€1,210
credit
Revenue€1,000
VAT payable€210
total€1,210
rejected at commit — debits ≠ credits
committed · March, entry 41
Not a validation in the app — a deferred constraint. The database is the one saying no.
Bookkeeping

A ledger the database refuses to unbalance.

Bookkeeping isn’t a report we render from your invoices; it’s a real double-entry ledger underneath them. Four guarantees live in the database, not in a promise: an entry whose debits and credits disagree is rejected at commit; a line is debit or credit, never both and never negative; the same event booked twice does nothing; and a closed month can’t be inserted into, altered or deleted — not even by the service role.

Which posting follows from an invoice, an expense or a VAT code is a pure function with a test that walks every code against six amounts. Corrections are counter-entries, never edits: your history stays what it was.

The interesting part isn’t that it asks permission. It’s that it couldn’t skip asking if it wanted to.

an approved draft leaves the building
do-not-contact
sending window
daily cap
Follow-up · Kamerbeek B.V.
append-only trail
Every attempt lands in the trail — the refusals too. Silence is indistinguishable from a bug.
Going outside

Approval is a property of the server.

Agents draft. Sending, publishing, invoicing, refunding — anything the outside world can see — waits for you. That isn’t enforced by hiding a button: the send path loads the recipient and the content from the database, not from whatever the browser posted, then re-checks the do-not-contact list, your sending window and your daily cap before it moves.

There is one narrow exception, and it’s allowlisted server-side: shop questions like “where is my order?” can auto-reply if you switch it on. Money, complaints, cancellations and address changes never can. Your settings can only make that stricter, never looser.

A dense band of filaments curving through space — thousands of runs of the same rule
the same question, the same gate
small model
draft spec
validator
one tier up
draft spec
validator
start on the cheap model — always
The escalation trigger is the validator failing — never the model reporting low confidence in itself.
Which model does what

Cheap first, escalate only on evidence.

Not every step needs the strongest model. Mechanical work — mapping a column, classifying a ticket — routes to a small one; judgement and anything a customer will read has a floor it never drops below.

When a cheap attempt produces a specification, it is escalated only if it fails the actual validator. Self-reported certainty is the one signal that correlates with nothing.

OUTBOUND_DISABLED
emailopen
messagingopen
publishingopen
paymentsopen
fulfilmentopen
production leaves it unset — the lock defaults to off
One environment switch closes email, messaging, publishing, payments and fulfilment at once.
Isolation

Something you can test, not trust.

Separation between accounts is row-level security in the database rather than a filter in the application, so another account can’t read your rows even if the app asks it to. Keys you connect are encrypted, decrypted server-side for the one action you approved, never logged, never sent to a model, and never returned to the browser.

There is also an environment-level lock that closes every outbound path at once — so a staging copy of real data cannot reach a real customer. It defaults to off, refuses loudly rather than silently, and a test reads the source to prove each path checks the lock before it ever unlocks a credential.

Next

This is the floor. You decide the ceiling.

All of the above is what the machine guarantees on its own. How much an agent is allowed to do without asking is a separate thing entirely — and that one is yours to set, per kind of work, revocable at any time.