Skip to specification

Evolution

Failures become infrastructure: a missed context becomes a retrieval rule, a dangerous command becomes a permission gate, a repeated workflow becomes a skill. Mine the repeats into a cluster, fence off what may change, and prove the fix against the tasks it never saw — the harness compounds while the weights stay frozen.

Evolution is where failures become infrastructure. Every other primitive handles the current run; this one makes sure the next run starts from a better place.

It is also the only primitive that edits the other ten. Which raises the question the rest of this sheet is about: once you have built the harness by hand, can something else improve it — safely — without you sitting there rewriting the code yourself?

The weights are frozen. The billions of numbers training produced never change, and you did not train them. Everything else — the limits, the gates, the retrieval, the compaction, the schemas — is software you wrote and can edit like any other software. So the target of improvement is not the model. It is the machine around it.

The rung you are standing on

Not every self-improvement is the same size. Lilian Weng, whose post on the subject gives the practice its name — loop engineering — sorts it into five levels, safest at the bottom.

Five levels of self-improvement

Riskier, and harder to undo, upward

  1. 05Improve the improver

    The loop that does the improving — the miner, the proposer, the grader, the acceptance rule.

    A change here silently re-scores every change beneath it. The measuring stick becomes a thing being measured.

    Edits ▸ The machinery in this sheet

  2. 04Improve the harness code⚑ This sheet

    The software wrapped around the model: limits, gates, schemas, the retrieval and compaction code itself.

    Every rung below is reachable from here. That reach is the reason it needs a fence drawn around it.

    Edits ▸ Any of the eleven primitives

  3. 03Improve the workflow

    The steps the agent takes — the order of the loop, when it plans, when it verifies, when it hands off.

    Behaviour changes now, not just inputs. A regression here reads as the agent doing the wrong thing competently.

    Edits ▸ Orchestration, sub-agents, skills

  4. 02Improve the context

    The material fed alongside the instructions: which files, which results, which slice of the history.

    Still an edit to inputs rather than machinery — and bounded by whatever the harness is already able to reach.

    Edits ▸ Context delivery and context management

  5. 01Improve the prompt

    The instructions handed to the model — the system prompt, AGENTS.md, the repo rules.

    Cheapest to try and cheapest to undo. It cannot recover anything that never entered the window.

    Edits ▸ Instructions

Each rung encompasses the ones below it — you can rewrite a prompt from level four, but you cannot rewrite the harness from level one. Knowing which rung you are standing on is the first question to ask of anything that claims to improve itself.

The five levels are Weng's, as the source talk relays them. Which primitive on this site each rung edits is our mapping, not hers.

Most of what gets called self-improving AI is level one wearing a bigger word: a system that rewrites its own prompt. That is a real improvement and a cheap one. It is also incapable of fixing anything that lives in the plumbing, and a great deal lives in the plumbing.

The rest of this sheet is a level-four story, run for real: an outside model reading a failure, editing the harness code, and proving the edit worked before anyone shipped it.

An agent that could not read the end of a log

The worked example, carried the whole way through, because the ideas stay concrete that way.

The harness has a clamp on it — six lines of code. When something the agent reads is too big, the clamp keeps the beginning up to a limit, drops everything after it, and leaves a small marker saying how much got cut. Simple on purpose, easy to reason about. The limit was 4,000 characters.

Ask that agent a question whose answer sits near the end of a long log file, and it fails. Not sometimes. Every single time.

But look at what it actually says:

The log ends abruptly with a truncated sequence. I cannot determine the password from the information provided.

It knew. It noticed the content was cut off, and it refused to guess. That reply is the whole diagnosis: a model that lied confidently here would be a much harder problem, and this one told you in plain language that the material never reached it. The bug is in the plumbing around the model, and nowhere in the model itself.

A failure is not yet a cluster

Before anything gets fixed, something has to decide what is worth fixing. The Self-Harness paper out of Shanghai AI Lab calls this step weakness mining, and the procedure is unglamorous: run the agent normally, let it fail, then look at the failures and ask whether they are one problem showing up repeatedly or a pile of unrelated one-off mistakes.

Only failures that share a provable cause get grouped. That group is a cluster, and the cluster — not the individual failure — is what the rest of the pipeline works on.

The log failure qualified twice over. Two different tasks tripped over it, and every time it happened the agent described what went wrong in almost the same sentence.

One other task in the suite came back flaky — passing most of the time, failing occasionally, no pattern. It got noted and set aside as noise. Nothing was proposed against it. That restraint is the point of the step: a system that tries to fix every failure will spend most of its effort fixing variance, and then take credit when the variance moves.

Memory, harness, or model

Here is the part that is easy to skim past and does the most work. Not every failure deserves the same kind of fix.

  • If the agent is missing a plain fact, it should just remember it. The cheapest move is usually the right one — drop the fact into memory.
  • If the failure is in how it routes a tool call, reads back a result, or follows a guardrail, that is a harness problem, and a harness edit is where it gets fixed.
  • If a failure keeps showing up no matter what you do to memory or the harness — across every task, every user, every project — that is the signal that you are looking at the model.

This is the site's whole question turned into a procedure. Which layer ran out of road? stops being a diagnostic mood and becomes a fork with three branches, and the branch you take determines what kind of change you are even allowed to propose.

The log failure took the middle branch, and the trace is what proved it. A missing fact would have pointed at memory. A failure appearing everywhere would have pointed at the model. A tool result being cut off before it ever reached the agent points squarely at the harness.

The version you already do by hand

Automating this loop is the ambitious version. The ordinary one is a habit, and it is worth seeing the shape before the machinery, because the machinery is only this done on a schedule:

observed failure                      →  becomes harness infrastructure
──────────────────────────────────────────────────────────────────────
a repeated context miss               →  a retrieval rule
a bad tool result                     →  a stricter schema
a dangerous command in the trace      →  a permission gate
a missed edge case                    →  a test
a recurring correction from the user  →  a memory
a repeated workflow                   →  a skill

Every row starts in observability — you saw it in a trace — and ends as a permanent upgrade to a different primitive. That is the loop: verification and observability catch the failure; evolution routes it back into instructions, schemas, gates, tests, memories, and skills.

In the wild

After an agent repeats a mistake, you add a line to CLAUDE.md — that is failure → instruction. You notice a risky rm -rf in a log and add a permission rule — failure → gate. You catch yourself explaining the same workflow twice and write it as a skill — repetition → capability.

Harness evolution is not exotic. It is the habit of never fixing anything only once. Everything below is that habit given a fence, a scoreboard, and a reviewer.

The editable surface

Before anything outside your agent can safely propose a change, the harness has to state exactly what is allowed to change. A short, named, versioned list.

That list is the editable surface, and everything outside it stays exactly as untouchable as it was before.

Building one is mostly bookkeeping. In this experiment every knob governing the agent's behaviour was scattered across five files; they were collected into one place — 35 lines, 11 values, and a version number — with the old code still reading from it, so the agent behaved exactly as before. Nothing changed except that the harness could now honestly answer a question it could not answer the day before: what, precisely, is editable about me?

The surface also decides how good the fix can possibly be. There was no field in that configuration for change the strategy of how content is clamped — only for the value. So every fix that could be proposed here was, structurally, going to be a bigger number. That constraint comes back at the end of this sheet.

How you know a fix worked

A fix that passes the test it was shown is not evidence. It might have understood the problem, or it might have memorised the example. Telling those apart takes four pieces of machinery, three of them from the Self-Harness paper.

Held in and held out. Split the affected tasks into two piles. The fixer sees one pile and is never shown the other. Afterwards you check the fix against both. Two tasks tripped over the clamp here; the fixer saw one. The hidden one is the only thing standing between a real fix and a fix that games the example it was given.

Miners and guards. Not every test exists to find something broken. Some you write expecting them to fail, because you already know the harness has a gap there — those feed the mining stage. Others you write expecting them to pass, and their entire job is to sit quietly and complain loudly if a fix for one thing breaks another. A suite made only of expected failures cannot catch a fix that helps here and harms there. (Those two names are the source talk's own coinage, not the papers'.)

Fractions, not verdicts. A small local model is not perfectly consistent — ask it the same question twice and you may get two answers. So every task runs several times and what gets recorded is a fraction. Two passes out of three is not a pass and not a fail; it is two-thirds. Compare fractions by averaging them, rather than taking whichever answer showed up most. Thirteen tasks at a few tries each meant every single candidate fix was measured over 49 live runs.

The acceptance rule. A candidate has to be at least as good on both piles, and strictly better on at least one. Better in one place and worse in another is a rejection. There is no partial credit.

Three candidates

The fixer here was a second, stronger model, kept deliberately separate from the agent being fixed — the small local model stayed frozen and only ever got tested. That is a disclosed departure from the paper, where one model diagnoses and repairs itself. The reason is that a small model asked to fix its own blind spot is being asked to see past something it cannot see.

It has a cost, which the talk names capability mismatch: a stronger model can propose something too clever, too nuanced, or too wordy for a smaller one to actually follow.

All three proposals raised the same number, because the editable surface left nothing else to raise. Each candidate was applied to a working copy, measured against all thirteen tasks — not just the broken one — and then reverted. A rejected candidate never became a commit; it existed exactly as long as it took to measure.

01Raise to 8,000

The two clamp tasks

Helped, and did not reach. The password line starts at character 8,690; reading stopped at 8,000. A near miss scores as a failure.

The other eleven

Nothing broke.

02Raise to 12,000

The two clamp tasks

Fixed, completely — including the held-out task the fixer never saw. The failing runs each took about 19 seconds to explain what they could not see; the fixed one answers in under two.

The other eleven

Nothing broke. This is the one that became a pull request.

03Raise it further

The two clamp tasks

Fixed the same two.

The other eleven

Broke one. A task that passed every time began failing every time — over a minute per attempt, then an empty reply — because a side effect changed how the harness manages a long conversation's memory.

The third candidate is the one worth slowing down for, because of how nearly it got through. On the same run, a flaky task happened to tick up by roughly the amount the broken one fell. Add everything into one total and the total barely moved. The acceptance rule, read on the aggregate alone, would have accepted a candidate that broke a working task. It was caught only because every task was read individually.

That limitation is disclosed in the paper the rule comes from. It is not a flaw in this experiment — it is a property of scoring by totals, and it is worth knowing before you build one of these.

The measuring stick had bugs

None of the above is worth anything if the suite is wrong, and the suite was wrong. It was written in one session and adversarially reviewed by a second session with none of the first one's context, deliberately hunting for the mistakes a tired author misses in their own work. That review found five real problems before a single live run.

Two are worth naming, because they are the kind anyone building this will hit:

  • A task that a do-nothing agent could pass. An agent that took no action at all would have quietly been credited with success.
  • Nothing stopped a candidate from rewriting the answer key — the very file the test checks against — instead of fixing the bug. The fix: fingerprint every seeded test file the moment it is written, and if that fingerprint ever changes, the task fails outright regardless of anything else. Editing the answer key has to count as a failure, not a loophole.

Then the first dry run errored out on a third problem, and this one is the sharpest. One test was comparing itself against the live value of the very number being edited. Any fix that raised the number far enough to work would have errored the test rather than passing it — the pipeline's own predicted best fix was structurally impossible to score. The measuring stick was coupled to the thing it was measuring. Pinning the test to the value recorded the day it was written fixed it, and because that changed the measuring tool, the entire baseline had to be re-recorded before anything else could be trusted.

Until a suite has been checked this hard, it is not a yardstick. It is a guess.

What the record has to hold

Pass-or-fail is not enough to learn from — a point the AReaL paper insists on. You need the trace: what the agent saw, what it did, what came back, stamped with exactly which version of the harness produced it.

So every run in this experiment is recorded in full — every tool call, every reply, tied to the exact commit of the agent and the exact version of the config under test. Candidate runs carry an extra flag marking the working copy dirty, plus a fingerprint of exactly what the dirt was. That record is what makes it possible to quote the model's own words back weeks later, and to say which harness produced them. This is verification and observability earning its keep one layer up.

The pull request that has not merged

The winning candidate opened a real pull request against a real public repository, on its own branch. The title states the change plainly: one configuration value, 4,000 to 12,000.

And then nothing happened. It passed every test and it is still sitting there, waiting for a person to read it.

That pause is deliberate. It would have been easy to close the loop end to end — mine, propose, validate, merge, with no human anywhere in it. The AReaL paper has a phrase for the alternative: safe, audited, staged deployment. Every change carries its own promotion path, and it is reviewed before it ships rather than after.

The gap between passing and shipping is what the word "safely" actually means here. A fix that can explain itself with real numbers and still waits for a person is a fundamentally different kind of thing from one that ships itself.

Reviewing it is more than reading the summary and clicking merge. Does the stated reason for the fix match the per-task numbers underneath it — the way it did not for the third candidate? Is this the smallest change that explains the improvement, or is it doing more than it needs to? Would I have proposed the same fix myself, and if not, why not? The whole pipeline — one pull request per fix, a full table instead of a single number — exists to make that review a few minutes of reading.

Where this loop runs out of road

The fix is real and it is narrow. All it did was make the bucket bigger, and it worked because this particular piece of content happened to fit under 12,000 characters. The harness is not one bit smarter about what to keep.

A genuinely better fix exists, and the harness already contains it. Keep the beginning and the end of something long, instead of only the beginning — which is exactly what compaction does for a long conversation a few files away. The answer was already in the building. But that trick is code, not a number, and the editable surface was values only. The loop could not reach it.

There is a second cost, and it compounds. The held-out task was hidden from the fixer, but it was still part of the score used to pick the winner — so information about it leaked into whichever candidate survived. Once is fine. Run the loop for many iterations and the hidden pile stops being hidden, one accepted fix at a time. The remedy is unremarkable and easy to skip: retire and replace held-out tasks periodically.

The checklist, for anyone claiming their agent improves itself

Ask these in order, and you will know in minutes whether it is engineering or marketing.

  • Was the failure real — found by looking at logs, not imagined?
  • Was it grouped with failures that share its cause, and separated from the ones that do not?
  • Was the fix tested against work the fixer never saw?
  • Was the change confined to a short named list of what is allowed to change?
  • Was it checked against every task, per task, not just the broken one and not just the total?
  • Was the suite itself adversarially reviewed, and can it catch a candidate gaming it?
  • Does every run leave a trace stamped with the version that produced it?
  • Does a change wait for a person, and can it be rolled back as a normal action?

The whole machine, assembled

Put all eleven primitives together and look back at any architecture diagram of Claude Code, Codex, or Gemini CLI — it stops looking like a random complex box-diagram. Every component has a reason to exist, and you now know each one.

Which leaves the practical test to carry with you. When an agent fails, don't only ask was the model good enough? Ask:

Was the instruction missing? Was the context wrong? Was the tool schema vague? Did the command run in the wrong environment? Did the workflow need durable state? Orchestration? Should it have been delegated? Was there no skill? No verification? No trace to look inside? And did we learn nothing from the last failure?

That is the shift. Harness engineering is how clever agents become dependable systems. The model still matters — but reliability is built in the system around the model, and that system can keep getting better long after you have stopped changing the model.