From prompt to loop
Four disciplines in three years. Each one names something the previous one assumed.
Jesús Pérez
·
Prompt, context, harness, loop — the sequence is not a ladder of improvements, it is a series of admissions. Each discipline exists because the previous one was caught assuming something it had no right to assume. And the last one still assumes one thing: that somebody declared what «done» and «safe» mean, and that the declaration is still true. A walk through what ontoref has been putting under each station — declared vocabulary, governed context provision, checks that declare their own coverage, a loop that proposes its memory and never applies it — with the counter-evidence included: four mechanisms that already forbade a failure, in writing, and not one of them fired.
Three years, four disciplines
2023 prompt engineering the words you send the model
2025-06 context engineering everything the model sees before it answers
2026-01 harness engineering what wraps a single run so it is safe
2026-06 loop engineering what decides when it runs, and when it is done Tobi Lütke named the second. Boris Cherny described the fourth from the inside:
"Now I don't prompt Claude anymore, I have loops that are running.
My job is to write loops."
My job is to write loops."
The sequence is not a ladder
It is a series of admissions.
prompt assumed the model knows enough
→ context: it does not. Feed it.
context assumed what you feed it is true, and it will comply
→ harness: compliance is optional. Constrain it.
harness assumed a human starts the run
→ loop: nobody should have to. Trigger it.
loop assumes ???The distinction that actually bites
A request
"Please follow our coding style guide."
Relies on the model choosing to comply.
Probabilistic. Unverifiable. Silent when ignored.
Probabilistic. Unverifiable. Silent when ignored.
A constraint
The linter rejects the pull request.
Cannot be skipped.
Deterministic. Checkable. Loud when violated.
Deterministic. Checkable. Loud when violated.
Harness engineering is the discipline of making bad behaviour
structurally difficult — not discouraged.
structurally difficult — not discouraged.
The loop needs exactly three things
while not goal_met(state):
task = find_next_task(backlog, state) # 1. find work
result = agent.run(task)
state = update_state(state, result) # 3. persist state
if attempts_exceeded(state) or blocked(result):
notify_human(state)
break # 2. know when to stop Find work. Know when to stop. Persist state between runs.
Remove any one and the loop is not autonomous — it is a cron job with a language model in it.
The car
The analogy everyone uses
The engine is the model.
The harness is brakes, seatbelts, sensors, dashboard.
The loop is the driver and the navigation.
The harness is brakes, seatbelts, sensors, dashboard.
The loop is the driver and the navigation.
A car with perfect brakes and no driver is safe — in the parking lot.
A car with a route planner and no brakes is a disaster with a schedule.
A car with a route planner and no brakes is a disaster with a schedule.
Station 1 · Prompt
Asks: what words do I send?
Unpaid bill: a prompt is prose. Prose has no arity, no type, no identity. "Follow the conventions" cannot be violated, because it cannot be evaluated.
ontoref's contribution — the vocabulary is declared, not described
term bilingual definition, aliases, category
origin typed warrant — WHERE this meaning comes from
forbidden the phrasings this term rules out, by name
related_* edges into the graph, not prose cross-references A controlled vocabulary in the Z39.19 sense: scope note, warrant, associative relations. The prompt stops carrying the meaning. The graph carries it, and the prompt cites it.
Station 2 · Context
Asks: what does the model see before it answers?
Unpaid bill: context engineering optimises the filling of the window and never asks who owns what goes in, or whether any of it is still true.
ontoref's contribution — context-provision is governed
ADR-074 — one source of truth about the protocol. Carriers (a CLAUDE.md, a memory file, a hook) invoke it live. They never hold a copy of it.
ADR-046 — substrate views: context is composed from a declared level chain for a discipline, not hand-curated per session.
A copied instruction is a fact frozen at copy time. It cannot go stale loudly — only quietly, and only in the direction of confidently wrong.
And the deeper move under context
The industry's answer to "the context does not fit" is
a bigger window
The protocol's answer is to stop needing the whole thing.
Sufficient verification over complete knowledge
ADR-056 — an invariant, not an optimisation
Any actor can verify that a slice is coherent
with what is declared, without loading the whole.
And it has teeth: it forbids any gate of the form
"you may not change X until you understand the whole system".
with what is declared, without loading the whole.
And it has teeth: it forbids any gate of the form
"you may not change X until you understand the whole system".
Station 3 · Harness
Asks: what wraps a single run so its behaviour is trustworthy?
Where I agree completely: a constraint beats a request. The linter beats the paragraph.
ontoref adds two things the discipline has not named yet
1 · A check declares its coverage
ADR-072. A mechanism declares its extent, and the witness carries that extent. A green check that will not say what it looked at is a harness that lies by omission.
2 · The check decides, never the reporter
ADR-066. The agent does not report "done". An externally-owned contract is evaluated against a witnessed deliverable, and the evaluation is the verdict.
The governance vocabulary, declared
Three pieces, each with a rendering declared per language — not translated on the fly:
Statement of Work the terms: scope, a falsifiable contract, validation mode.
(SOW) Owned by the HUMAN, outside the agent's editable surface
· es: Pliego One SOW authorises many Work Orders. Rust type: `Sow`
Work Order the run: disposable, contained, owned by the agent.
(WO) Carries the deliverable, the witness, a contained verdict
· es: Orden de 'Accepted | 'Rejected | 'Escalated Rust type: `WorkOrder`
Trabajo (OT)
Verified witness the receipt a Work Order deposits when it completes:
content-addressed, Ed25519-signed. It proves THAT a check
· es: Testigo ran and what it returned — structure, never truthfulness
verificado And the constraint the glossary declares on it: a witness records, it does not refuse. It becomes a gate only when a control point won't proceed without one.
No scope + contract, no start.
No witness, no done.
No witness, no done.
The counter-evidence I owe you
ondaod in the CLAUDE.md, with a consultable procedure
assertion ⇒ witness ADR-072, accepted, anti-pattern named
qa:expediente-howto 267 lines, warning about the exact traps
mode:generate-expediente 11 steps with their actor, prints itself Four mechanisms. All older than the incident. All correct. All consultable in a second.
In a 4-hour agent session: eight false assertions, zero error messages.
Not one of the four fired.
Not one of the four fired.
Station 4 · Loop
Asks: when does it run, on what, and when is it genuinely done?
The loop's three requirements already have typed homes
1. find work backlog.ncl + 31 modes as DAG workflows
a mode is a declared workflow with steps, actors and guards
2. when to stop FSM state dimensions (current → desired, with a blocker)
gates with declared permeability
criteria as typed provenance — normative vs discovered (ADR-049)
3. persist state the ontology core IS the authoritative state (ADR-025)
NCL on disk is its manifestation, not the source
the witness binds every act to what it changed (ADR-023/031)The one rule I would give any loop
On completion, the loop proposes state, backlog and proof deltas.
It never applies them.
ADR-052 — memory feedback loop
A loop that writes its own memory is a loop
that drifts, confidently, forever
— and every subsequent run reads the drift as ground truth.
that drifts, confidently, forever
— and every subsequent run reads the drift as ground truth.
The loop assumes
that somebody declared
what "done" and "safe" mean —
and that the declaration is still true.
The linter is a constraint. Who constrained the linter's rules?
Harness engineering does not remove trust.
It moves it one level up, into a place
with fewer eyes on it and no gate of its own.
It moves it one level up, into a place
with fewer eyes on it and no gate of its own.
The stack, completed
engine the model what can be generated
harness constraints, gates what is allowed to happen ← reflection axis
loop triggers, cadence what happens next ← reflection axis
─────────────────────────────────────────────────────────────────
ontology declared substance what any of it is FOR ← the missing axis
witness the seam what actually happened, provable Harness and loop are both act. Neither is substance.
ADR-031 holds them as co-equal axes — ontology (what IS) and reflection (what DOES) — and fixes the witness as the formal seam where they meet. Every act that mutates substance emits a witness; every state mutation is the deposit of a witnessed act.
The car analogy, finished
What the analogy gives you
engine · brakes · seatbelts · sensors · dashboard · route planner
What it quietly skips
Who chose the destination — and the logbook that lets someone who was not in the car verify where it has actually been.
A perfectly safe vehicle, perfectly navigated, to a destination nobody wrote down.
The diagnosis, extended
The article’s framework, which is good and which I keep:
unsafe during a single task? → harness problem
completes fine, needs a human start? → loop problem
both? → fix the harness first —
a good loop only runs a broken harness more oftenThe third question
Is your definition of "done" written where the machine can read it,
and does anything FIRE when it is violated?
no → you do not have a harness problem or a loop problem.
You have an ontology problem, and the other two layers
will amplify it faithfully, on schedule, forever.What "queryable" means, concretely
onre describe project identity, axioms, tensions, practices, FSM dimensions
onre describe constraints 240 typed constraints from 72 accepted ADRs
onre describe state current → desired per dimension, with the blocker
onre mode show <id> the workflow: steps, actors, guards
onre qa show <id> session-verified procedure, with what it cost to learn
onre view mount <discipline> the context slice for a discipline, composed not curated Every claim in this talk was printed by one of these commands while writing it.
Not because that is impressive — because a claim about verification
that you cannot verify is the exact failure mode the talk is about.
that you cannot verify is the exact failure mode the talk is about.
Was this useful? Rate it
Got something to add?
Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
·
reads