ResearchUpdated Agents, harnesses

Inside Harness²

Google Research open-sourced Harness², an agent that rewrites its own harness while it works. We ran it, read the code, and wrote down what we think it's actually good for.

Harness² on one task, as it ran for us: the base run gave 105.25, four probes of edited harnesses each gave 85.15, two compositions gave 85.15, one was adopted blind, and its lesson went to the accounting library that the next task starts from. Input 01 Run 02 Propose and probe 03 Compose 04 Adopt Taskledger-1 Base runh0, as shipped105.25 same task, 4 edits inv1 general 85.15 inv2 general 85.15 dom1 field 85.15 dom2 field 85.15 Composeagg1, agg285.15 Adoptedagg1, picked blind85.15 Library, accountingharness tree + EXPERIENCE.md1 lesson ledger-2 starts here, lesson in hand Within a task Across tasks The same run, top to bottom: base run 105.25, four probes at 85.15, composed 85.15, adopted blind, lesson to the library for the next task. Taskledger-1 Base runh0, as shipped105.25 same task, 4 edits inv1 general 85.15 inv2 general 85.15 dom1 field 85.15 dom2 field 85.15 Composeagg1, agg285.15 Adoptedagg1, picked blind85.15 Library, accountingtree + EXPERIENCE.md1 lesson ledger-2 starts here, lesson in hand
Figure 1. One task in parallel mode with k = 2, as it ran for us. The model's weights never change: every edit is to the harness, the prompts, tools, scripts and memory around it.

Summary

  • Harness² doesn't touch the model. It edits everything around it: the prompts, tools, scripts and memory. On each task it tries a few edits, runs the task again under each one, and keeps what actually changed the result.
  • Every harness it keeps comes with a short written lesson, filed by field, so the next task in that field starts from what the last one learned. The paper reports gains of up to 11.8 points on legal, office and professional work.1
  • We ran it ourselves. It caught a bug in the agent's own script, fixed it, got both tasks right and wrote the lesson down.
  • Its weak spots are cost, a judge it can't check, and lessons that never really stick. We think all of them are fixable, and we lay out how near the end.

The harness is the product

A model by itself turns text into text. What makes it an agent is everything around it: the instructions it starts with, the tools it can call, its memory and skills, the scripts it runs, the helpers it hands work to. That's the harness.

Put two teams on the same model and you'll get very different work out of them, and nearly all of that gap is the harness. Most people still tune it by hand, reading transcripts and fixing one failure at a time. Harness² asks whether the agent can do that tuning itself, on the job, on tasks nobody built the harness for. We think that's the right question to be asking.

How does Harness² work?

It turns eight parts of the harness into files it can edit: the system prompt, guardrails, memory, skills, tool guidance, scripts, subagents and plugins. Then it works at two levels.

Within a task: propose, probe, compose

The agent runs the task once with what it has. An editor suggests changes, some general and some specific to the field. Each change gets tested by running the same task again under it. Then a composer lays the runs side by side and builds one harness out of the edits that clearly made a difference. It never looks at the right answer. The only signal is how the agent's own runs differ from each other.

You can run it wide or deep. Parallel mode tries k general and k field-specific edits at once and makes k combined versions. Sequential mode takes the improved harness and its evidence through k rounds, one after another.

Across tasks: a library per field

When a task is done, the harness it settled on is kept whole, not summarized, with an EXPERIENCE.md that says why it was picked and what was learned. Lessons are filed by field, so a new accounting task pulls up accounting lessons on its own. There's no search involved.

Choosing the answer

The finished candidates go to a selector with their labels shuffled, seeded per task so a rerun picks the same way. The original harness isn't allowed in the running, and anything that didn't produce an answer gets dropped first, with the reason written down.

What our run showed

We ran the version in the repo that works without any model credentials. Its agent has to reconcile two ledgers, and the script it's handed has a bug: it only adds up positive amounts, so every credit goes missing.

scripts/summarize.pyedit adopted by the composer
amounts = [Decimal(row['amount']) for row in csv.DictReader(source)]
total = sum((amount for amount in amounts if amount > 0), Decimal(0))
print(f'Total: {total:.2f}')

We ran both modes with k = 2. Every run saved its answer to disk, and Figure 2 shows all 28 of them.

Base harnessProbesComposed finals
base1base2inv1inv2dom1dom212
ledger-1parallel105.25105.2585.1585.1585.1585.1585.1585.15
ledger-1sequentialshared with parallel85.1585.1585.1585.1585.1585.15
ledger-2parallel35.5035.5020.2520.2520.2520.2520.2520.25
ledger-2sequentialshared with parallel20.2520.2520.2520.2520.2520.25
  • Wrong: credits left out
  • Right total
  • The final the selector adopted
Figure 2. Every execution in our run. Ledger-1 is 100.25, −20.10 and 5.00; the right total is 85.15. Ledger-2 is 35.50, −10.25 and −5.00; the right total is 20.25. 28 executions and 32 editor calls in all.

Then it wrote the lesson into the accounting library. By the time ledger-2 started, this was already sitting there waiting for it:

library/k2/agg/accounting/harnesses/ledger-1/EXPERIENCE.mdverbatim
## Transferable lesson
- cue: When a ledger includes credits and debits
- lesson: Include both signs when summing in scripts/summarize.py.
- evidence: The scripts/summarize.py row -- removing the
  positive-only filter changed the probe total to include the
  credits omitted by the base trajectory.
- confidence: high for this observed arithmetic contrast
Figure 3. The lesson as Harness² stored it: a cue for when it applies, the lesson, the evidence from the runs, and its confidence.

Worth being clear about: in this run the editor's suggestions and the selector's picks are scripted, not made by a model. So it shows the whole loop holds together, end to end. How good a real model is at the suggesting part is what the paper's benchmarks are for.

Where it applies

It earns its cost when one agent does a lot of similar work and the model is something you can't change.

Professional work in one field

Legal memos, accounting, office docs. Lessons pile up per field, so each task starts from the one before it.

Benchmarks: LAB, JobBench, WorkBuddy-Bench
Models you can't retrain

Every edit lives outside the weights, so it works with any model behind an API.

Reported on GLM-5, Gemini 3.5 Flash
Diagnosing a harness

Each edit it keeps comes with the runs that justified it, which turns out to be a pretty good map of where your prompts and scripts fall short.

One EXPERIENCE.md per task
Agents that repeat a craft at scale

An agent making the same kinds of fixes across thousands of sites or documents. That's exactly what the library is built for.

Lessons compound with volume

The paper's headline results, one Harness² step over each base harness:1

BenchmarkWorkGain, up to
WorkBuddy-BenchOffice, web and code11.5 points
LABLegal work11.8 pp partial pass
JobBenchProfessional work4.5 points

Limits

  • Cost. Every task runs several times, so model calls multiply fast. Parallel mode at k = 2 ran the script eight times per task for us.
  • No ground truth. It judges candidates against each other. A better harness doesn't mean a right answer.
  • Isolation is on you. Executors get full network access and the Codex executor runs with its sandbox off. Benchmark answers can be found online, so lock it down yourself.
  • Status. It's a research release under Apache 2.0, not an officially supported Google product.

Our view

The part that matters most isn't the recursion. It's that the harness becomes a real thing: a tree of files you can diff, keep, reuse, and trace back to the runs that justified each change. Most teams tune their prompts and scripts by feel. Harness² treats them as data with a history, and that habit is worth copying whether you ever run the loop or not.

Reading the code, four choices stood out to us, and each one has a catch that's easy to miss:

  • The original never wins. The base run can't be picked, so every task ends on an edited harness, even when the original was the best one. That's the right call when the base is weak. When it's already good, it's an invitation to drift.
  • Lessons advise, they don't add up. Every task starts from the original harness again, and the library is just reading material for the editor. The gains live in what the editor knows, not in the agent's defaults. Turn the loop off and the agent is exactly what it was.
  • Lessons stay in their field. Filing by field makes lookups exact and cheap. It also means "check the signs before you sum," learned in accounting, never reaches a finance task filed somewhere else.
  • The judge is the ceiling. With no right answer to check against, everything depends on the selector telling a better run from a worse one. If the output can be checked (a total, a test suite, a schema), wire that check in. If it can't, that's still the open problem.

None of these are dealbreakers. They're the places we'd start.

How we'd make it better

Most of what bugged us is fixable without touching the core idea. Here's what we'd change, roughly in the order we'd do it, and how we'd know each change worked. None of it is tested yet, apart from one number we could work out from our own run.

  • Stop when the runs agree. Cost is the first thing anyone hits. In our run, every probe and both compositions came back with the same right total, so most of those runs taught the loop nothing. We'd probe in pairs: if the first general and the first field-specific edit land on the same answer, compose once and stop. Two runs can agree and both be wrong, so this gets a lot safer with a check behind it (more on that below). On our run that's 5 runs a task instead of 8. We'd know it worked if the paper's benchmarks hold their pass rates with a lot fewer model calls.
  • Let the original compete. The base run can't win today, which is why a strong harness drifts. We'd put it back in the pool and only adopt an edit when it beats the original by a clear margin. Otherwise the task keeps the original and the ledger says "no change", which is a real result too. We'd test it on a harness that's already tuned, like a support team's macros, and count how often the loop picks something worse.
  • Check before you judge. The judge is the ceiling, so don't lean on it when you don't have to. We'd let a task declare a check (a total that has to tie out, a test suite, a schema, an audit score) and rank runs on that first, with the model judge only breaking ties. Where there's no check, we'd measure the judge on a held-out set with known answers before trusting it. The test is simple: on tasks with a check, how often does the judge alone pick the run the check would?
  • Let lessons graduate. Right now lessons are reading material and the agent always starts from scratch. When a lesson keeps getting adopted in a field, say five times, we'd fold it into that field's starting harness, with its evidence attached and a way to roll it back. We'd compare later tasks that start from the promoted harness against the original plus the library.
  • Share lessons across fields, carefully. "Check the signs before you sum" shouldn't stay stuck in accounting. We'd index each lesson by its cue as well as its field, and hand the editor the closest cues from other fields, marked as coming from elsewhere, so it decides. We'd watch two things: whether they help, and how often they mislead.
  • Sandbox by default. Executors should get no network unless a task needs it, an allowlist when it does, and the Codex sandbox on. Benchmark pass rates shouldn't move. If they drop, that tells you something too: the agent was finding answers online.
Parallel mode, k = 2, on our runRuns a taskBoth tasks
As shipped: 2 base, 4 probes, 2 compositions816
Stopping once the first two probes agree510

That's worked out from Figure 2, not run. On our example every run agreed, so it's the best case. On real tasks the probes disagree more often, and that's exactly when the extra runs are worth paying for.

What we'd push on after that: how an open model on modest hardware does as the editor, and what each point of gain really costs once the loop knows when to stop.

Reproduce it

About two minutes. No model, no account. The guide is written for Linux, and it ran fine for us on macOS too. You'll need uv, which installs Python 3.12 for you.

Terminalour output below the command
git clone https://github.com/google-research/harness2.git
cd harness2
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python -e .
.venv/bin/harness2-demo --output runs/demo --k 2

  [accounting] 1/2 ok           ledger-1
  [accounting] 2/2 ok           ledger-2
Local demo: 2 tasks completed; 0 failed.

Answers are under runs/demo/executions, one folder per run, and the library is under runs/demo/library. Model-backed benchmarks need model credentials and are covered in the repository's setup guide.2

References

  1. Xu, Chen, CuiZhu, Dalvi Mishra, Ming, Yu, Han, Lee and Pfister. Harness²: Recursive Agent Harnessing for an Open World. arXiv 2610.14224, 2026.
  2. google-research/harness2, commit 1cfe254, October 13, 2026. Apache 2.0.