AI Engineering15 min readJul 2026 Last verified Jul 2026

The Model Is the Engine. The Harness Is the Car.

The same model that "can't fix the bug" fixes it the moment you let it read the error and run the tests. This is harness engineering: we build the blindfolded agent, add the four capabilities that make it work (with real code), and finish with a drill you run by removing each one.

AIAgentsToolsClaude CodeCoding Agents
SB

Sri Balaji

Founder · TheSimplifiedTech

On this page

It said "done", and nothing worked

You ask an AI to fix a bug. It confidently edits a file and reports "done". You run the app: still broken. You conclude the model is not good enough and reach for a bigger, more expensive one. Most of the time, that is the wrong diagnosis, and the more expensive model fails the same way.

The problem is almost never the model’s intelligence. It is that the model was working blindfolded: it never saw the actual error, never ran the tests, and had no way to check its own work. "Done" just meant it stopped typing. Fixing that is a discipline with a name, and it is where most of the real engineering in AI systems now lives.

Who this is for

Anyone who has been disappointed by an AI coding tool, or is wiring up an agent and deciding what tools to give it. No framework knowledge needed, we build the idea from a single model call upward.

The model is the engine. The harness is the car.

The harness is everything around the model call: the tools it can use, the environment it runs in, the loop that feeds results back, and the check that decides when it is actually done.
A world-class engine sitting on a workshop floorA powerful model with no tools, it can think but not do or check anything
Wheels, steering, a dashboard, brakesRead files, run tests, see the results, stop when it is right
The same engine, now in a car, goes somewhereThe same model, now in a harness, actually finishes the job
You rarely change the engine. You build the car around it.
actcheckretry if redwhen green
Task
Model

the engine

Tools

read, edit, run

Verify

run the tests

Done

A harness: tools to act, a verify step to check, and a loop back until the work is truly done.

See it for yourself

Below is the same AI fixing the same bug, twice. First with no tools: it guesses, edits, and declares victory on a fix it never tested. Then with tools: it reads the error, runs the tests, sees red, and keeps going until they are green. Watch which one is actually done at the end.

Same AI, same bug: blind vs equipped

Give the AI tools to check its work?

Same AI, same task: fix the bug in an app. Press Watch it try and see what changes when it can read the error and run the tests.

The whole idea: the second AI is not smarter. It could read the error and run the tests to check its own work. That surrounding kit, the tools and the feedback loop, is the harness. Most "the AI can’t do this" is a missing harness, not a missing brain.

The model does not change. The tools and the feedback loop around it do.

The naive harness: an expert, blindfolded

Here is the "harness" most people start with. It is a single model call. Nothing reads, nothing runs, nothing checks.

blind_agent.py
python
def fix_bug(repo, model):
    prompt = "Fix the bug in this code:\n" + repo.read_all()
    patch = model.complete(prompt)   # one guess, no feedback
    repo.apply(patch)
    return "done"                     # 'done' = the model stopped typing

Three things are missing, and each is a whole capability. The model never reads the specific error, so it guesses which file. It never runs anything, so it has no idea whether the patch worked. And there is no loop, so even if it could check, it gets exactly one attempt. This is a surgeon operating blindfolded and then announcing the operation was a success.

The four capabilities that matter

Turn the blindfolded model into a working agent by adding four things. They are not equally valuable, and they have an order: a retry loop is worthless without something to run, and running is worthless without something to read.

CapabilityWhat it addsWithout it
Read filesThe model sees the real code and the real errorIt guesses which file, and edits blind
Run & verifyA true pass/fail signal"Done" means "the model said done"
Retry loopFix, run, fix again: self-correctionOne shot, no chance to recover
SandboxTools run isolated from anything realA wrong command runs on your machine
Four capabilities. The biggest jump by far is read + run + loop together.

The one that changes everything: verify-and-retry

Reading is table stakes. The capability that turns a demo into a tool is letting the model check its own work and try again. "Done" stops meaning "the model stopped" and starts meaning "the tests are green". The harness, not the model, owns the definition of done.

verify_loop.py
python
def fix_bug(repo, model, run_tests):
    history = []
    for _ in range(6):                       # RETRY LOOP
        failing = run_tests()                # RUN: a real signal
        if not failing:
            return "verified: all tests pass"
        context = repo.read(failing.file)    # READ: the real code
        patch = model.edit(context, failing.error, history)
        repo.apply(patch)
        history.append((failing.error, patch))
    return "gave up after 6 tries (still failing, and it KNOWS)"

A retry loop with nothing to run is fake

Giving an agent "try again" without a real verification step just lets it generate six confident wrong answers instead of one. The loop is only worth adding once run_tests() gives an honest red or green. Capabilities in the wrong order buy nothing.

You do not have to write the loop

Once you see the shape, most of it is provided. A tool-runner SDK is exactly this loop, productised: you declare the tools, and it handles the calling, the feeding-back, and the looping until done.

runner.py
python
runner = client.beta.messages.tool_runner(
    model="claude-opus-4-8",
    tools=[read_file, edit_file, run_tests],   # the harness, declared
    messages=[{"role": "user", "content": task}],
)
final = runner.until_done()   # it runs read -> edit -> run -> loop for you

A full coding agent (Claude Code, or an internal one) is the same idea at the next scale up: the same read/run/verify loop, plus a sandboxed workspace, memory, and sub-agents, so it can take on a whole task instead of one call. The model inside is unchanged. The capability is the harness around it.

Now build one yourself (30 minutes)

The fastest way to believe "it is the harness, not the model" is to watch the same model succeed and fail on the same task as you add and remove one capability. Do this in half an hour with any model API.

  1. 1

    Make a tiny broken repo

    One function and one failing unit test (say, a password validator that does not reject empty strings). Confirm the test is red.

  2. 2

    Blindfold run

    Paste the whole file into the model, ask for a fix, apply the patch, and re-run the test yourself. Note two things: did it pass, and did the model CLAIM it passed? Often it claims success on a still-red test.

  3. 3

    Add READ + RUN + LOOP

    Now feed it the failing test name and error, apply its patch, run the tests in code, and if still red, feed the new error back, up to six times. Watch it self-correct into green. Same model, different outcome.

  4. 4

    Remove RUN, on purpose

    Take away the test run so it cannot check itself. Confirm it goes straight back to claiming success on a broken fix. That single removal is the entire lesson: without verification, 'done' is a guess.

  5. 5

    Add a SANDBOX

    Run the tools in a temp directory or container. Prove it by giving the agent a tool that could delete files and confirming a wrong move is contained, not catastrophic. Capability without isolation is a loaded gun.

What you will have proven

That a model’s success rate on a task can swing from near-zero to near-certain without the model changing at all. After this drill, "the AI can’t do X" becomes a question: what can it not see, do, or check?

Mistakes that send you shopping for a bigger model

  1. 1Upgrading the model to fix a harness gap. The model "couldn’t" fix the bug because it could not run the tests, not because it was dim. A better harness beats a bigger model here, at a fraction of the cost.
  2. 2Trusting "done". If nothing in your harness checked the result, "done" means "the model said done". Gate every success on a real check: tests green, output validates, the file compiles.
  3. 3A retry loop with no verifier. Six attempts and no way to tell which one worked is six guesses, not self-correction. Add the verifier first, then the loop.
  4. 4Tools with no sandbox. A shell and file access on a real machine means one confused or injected instruction can run a destructive command with your permissions. Isolate first.

The whole thing in one screen

The four capabilities

  • The model is the engine; the harness (tools, environment, loop, verification) is the car. You change the car far more than the engine.
  • Read: let it see the real code and error, so it stops guessing which file.
  • Run & verify: give it a true pass/fail signal, so 'done' means green, not 'the model stopped'.
  • Retry loop: fix, run, fix again, but only once there is something real to run. Order matters.
  • Sandbox: every tool runs isolated, so a bad step is contained, not catastrophic.
  • Before you upgrade the model, ask what it could not see, do, or check. Usually that is the fix.

Where to go next

This article is the on-ramp. The interactive lesson lets you bolt capabilities onto a bare model and watch the same task's success rate climb from almost never to almost always, then reason about the tradeoffs:

Was this article helpful?

Want to go deeper?

This article covers concepts taught hands-on in the Cloud Engineer and DevOps career paths, with real terminal labs, production scenarios, and structured lessons.