The Model Was Fine. Everything Around It Was Missing.

You point a coding agent at a migration of sixty endpoints and leave it overnight. In the morning the first session has tried to do all sixty at once and ran out of context halfway through endpoint fourteen. The next session looked at the half-finished state, decided things seemed mostly done, and stopped. CI is red, and nothing in the repo says what was attempted.

Swapping the model won't fix that, because the failure is in the code around it. A harness is everything that wraps the model: the loop, the tools, the permissions, how context is managed, where progress is stored, and how work gets checked. InfoQ's 2026 trends report lists harness engineering among the innovators this year. Agent SDKs started by helping you write the loop, and now they ship memory management and code execution too.

If your agent runs for more than one sitting
  • Long tasks stall, or end with the agent declaring victory early
  • A new session spends its first ten minutes working out what the last one did
  • The agent marks work as done that does not work end to end
  • You are asking whether multi-agent would fix this, and nobody can say why it would

What a Harness Actually Owns

ConcernWhat the harness doesWithout it
LoopCalls the model, runs tools, enforces turn and cost limitsRunaway sessions
ContextClears tool results and compacts historyDrift on long tasks
StateKeeps progress outside the window, on disk and in gitEvery session starts blind
PermissionsDecides what runs freely, what needs approval and what is deniedThe model polices itself
VerificationGives the agent tests, browsers and logs to check its own work“Done” means “I wrote it”
IsolationRuns tools in a sandbox with limited network accessYour laptop is the blast radius

The Long-Running Pattern

Anthropic's write-up on harnesses for long-running agents is the best primary source on this, and it starts from a useful admission: compaction alone was not enough. Given a high-level prompt, the agent tried to one-shot the app, ran out of context mid-feature, and later sessions declared the job finished too early. What worked was treating each session like an engineer picking up a shift.

  • An initializer session sets the stage. It writes an init.sh, a progress log, a feature list, and an initial git commit. In their setup, that is the same agent with a different first prompt.
  • The feature list is JSON, and every entry starts failing. They wrote over 200 features with "passes": false, and later sessions may only change that field. JSON was chosen because the model is less inclined to rewrite it than Markdown.
  • One feature per session. Each ends with a descriptive commit and a progress note, so a bad change can be reverted.
  • Every session starts the same way. Check the directory, read the git log and the progress file, pick the top unfinished feature, run init.sh, and run a basic end-to-end test before starting anything new.

sequenceDiagram
    participant H as Harness
    participant A as Agent session
    participant R as Repo and progress file
    H->>A: Start session
    A->>R: Read git log, progress, features
    A->>R: Run init.sh and a smoke test
    A->>A: Build one feature
    A->>R: Run it end to end
    A->>R: Set passes to true, commit, note
    H->>A: Next session starts clean
      
// features.json — sessions may change "passes" and nothing else
[
  {
    "id": "orders-v2-list",
    "description": "GET /v2/orders returns paged orders with the new schema",
    "steps": ["Seed 3 orders", "Call the endpoint", "Check paging links"],
    "passes": false
  }
]

Checks the Model Cannot Talk Its Way Past

The most useful line in that post is about verification. The agent marked features as done without testing them end to end, and giving it browser automation, so it could use the app the way a person would, improved results dramatically. Unit tests the agent wrote itself are weak evidence of anything.

The same idea applies to safety. Put rules where the model can't argue with them, at the tool boundary:

import re

DENY = [r"\brm\s+-rf\b", r"\bgit\s+push\b.*--force", r"\bterraform\s+destroy\b"]
NEEDS_APPROVAL = [r"\bgit\s+push\b", r"\bkubectl\s+apply\b"]

def check_command(command: str) -> str:
    if any(re.search(p, command) for p in DENY):
        return "deny"
    if any(re.search(p, command) for p in NEEDS_APPROVAL):
        return "ask"
    return "allow"

A regex list is a seatbelt, not a sandbox, and a determined model can get round it with a script. It stops the common accidents. For anything untrusted, the real boundary is the sandbox, which the durable agents topic covers.

One Agent or Many?

I'd start with one. Anthropic's research system did beat a single agent by 90.2% on their internal eval, but that is breadth-first research, where work parallelises well, and multi-agent systems used about 15 times the tokens of a chat. The same post says most coding tasks involve fewer truly parallel pieces. Their later harness write-up leaves the question open: it is unclear whether one general agent or a team of specialists does better across contexts. Add a second agent when you can name what it isolates, such as a reviewer who hasn't seen the implementation.

What Goes Wrong

⚠️ Common Mistakes

1. Letting the agent rewrite its own task list

If a session can edit the list, it can remove the hard item. Restrict it to flipping a status, and enforce that outside the agent: have the harness diff each update and reject anything else.

2. Trusting self-reported completion

“All tests pass” in a final message is a claim. Run the tests from the harness and read the exit code yourself.

3. No smoke test at the start of a session

If the last session left the app broken, the next one builds on the wreckage. Check health before starting new work.

4. Storing state only in the conversation

A summary is lossy and dies with the session. Files and git history survive restarts, and a person can read them.

What I Would Do First

Add a progress file and a rule that every session reads it first. Move your definition of done into something the harness can run. Then look at where your agent spent its time in the last failed run. It is usually working out where it was, and that part is cheap to fix.