The first session with a coding agent is crisp: it reads the code, makes a clean change, writes a test. By the thirtieth, something has rotted — it re-discovers the same files, contradicts a decision it made three weeks ago, guesses the test command, and quietly stops writing tests because nobody made it. The fix isn’t a better model. It’s an operating system around the model: a constitution, an autonomy boundary, tiered context, durable memory, a review panel, and a post-edit hook.

A useful way to say it: the agent is the model plus its harness — the prompts, the tools, the context policies, the hooks, the sandboxes, the sub-agents, the observability wrapped around the raw model. The model is maybe a tenth of what decides whether you get working software over a quarter; the harness is the rest. The evidence is blunt. On the public Terminal-Bench 2.0 benchmark, LangChain moved a coding agent from outside the top 30 to the top 5 — a jump from 52.8% to 66.5%, or 13.7 points — by changing only the harness (system prompt, tools, and middleware like self-verification and loop detection), keeping the same model.

Examined honestly, most agent failures aren’t just model failures — they’re configuration failures: a missing tool, a vague rule, an absent guardrail, a context window stuffed with noise. So when quality decays across a long project, the lever is almost never “wait for a smarter model.” It’s the harness — and unlike the model, the harness is yours to build.

The four failure modes this addresses:

  • Discipline — skips tests, expands scope → a constitution read every session
  • Context — re-learns the repo → tiered CONTEXT.md, maintained by a hook
  • Memory — repeats corrected mistakes → durable per-fact memory files
  • Review — one blind spot applied uniformly → a multi-lens agent panel

The Constitution

A lean, always-loaded file stating the non-negotiables: the workflow loop (Plan → Document → Implement → Test → Review → Commit), the autonomy boundary, the quality bars (tests in the same diff, no dead code, conventional commits), and adapter discipline (no vendor SDK in domain code). Keep it short — it’s read on every turn, so every line costs context budget.

The Autonomy Boundary

The highest-leverage single decision: let the agent run free on everything reversible, pause only on the two things that aren’t — pushing to a remote and deploying. As a permissions config:

{
  "permissions": {
    "allow": ["Read","Edit","Write","Grep","Glob",
              "Bash(git add:*)","Bash(git commit:*)",
              "Bash(npm test:*)","Bash(npm run:*)","Bash(npm ci:*)","Bash(pytest:*)"],
    "ask":   ["Bash(git push:*)","Bash(npm publish:*)","Bash(aws:*)","Bash(terraform apply:*)","Bash(kubectl apply:*)"],
    "deny":  ["Bash(git push --force:*)","Bash(git push -f:*)","Bash(*--no-verify*)"]
  }
}

Now it works for an hour and commits a dozen times; you review at the push, not at every keystroke. The blast radius of “autonomous” stays bounded because the irreversible ops are the only gated ones. Verify your runner’s match semantics — prefix vs substring differ — so --no-verify/--force denials and npm publish actually trip; broad globs like npm:* quietly allow npm publish.

Tiered Context

One giant context file rots and blows the budget. Tier it:

  • Root CONTEXT.md — the map: what this is, how to run/test, one-line module index, invariants, where state lives. Cap ~200 lines; the session-start read.
  • Per-module CONTEXT.md — responsibility, key files, deps, gotchas, how to test just this module. Read before editing that module.
  • DECISIONS.md — append-only: date, decision, why, alternatives rejected.

Rule: stale context is a bug, fixed in the same change that invalidated it — not “later.”

Durable Memory

Context describes the code; memory holds what the code can’t tell you across sessions — one fact per file, indexed:

memory/
  MEMORY.md                  # index: one line per fact
  user-prefers-X.md          # type: user | feedback | project | reference
  graph.jsonl                # {from, rel, to} — modules/decisions as nodes; depends-on/adapts/supersedes

The graph answers the question agents are worst at: “what breaks if I change this?”

The Review Panel

Instead of one self-review, run focused sub-agents in parallel, each one lens, strict output:

product   — solves the stated problem? scope creep?   (plan stage)
architect — correctness, data model, failure modes, coupling
infra     — resource limits, deploy/rollback, resilience
security  — authz, input validation, secrets, audit trail
test-eng  — is the suite real, or happy-path theater?  (per change)
→ each returns: [BLOCKER|MAJOR|MINOR] (confidence%) — file:line — issue — fix ; VERDICT

Only high-confidence BLOCKER/MAJOR gate. Diverse lenses catch what a single pass misses; the confidence threshold keeps it from drowning you in nits. These are parallel agents reviewing one change — distinct from parallel agents making changes.

The Post-Edit Hook

The piece that ties it together fires after every edit and emits a checklist (a PostToolUse hook). Wire it in settings.json, pointed at a small script:

{ "hooks": { "PostToolUse": [
  { "matcher": "Edit|Write|MultiEdit",
    "hooks": [ { "type": "command", "command": "python3 .claude/hooks/post-edit.py" } ] } ] } }
# .claude/hooks/post-edit.py — reads the tool event on stdin, emits a checklist as context
import json, sys
ev = json.load(sys.stdin)
path = ev.get("tool_input", {}).get("file_path", "the edited file")
checklist = (f"Post-edit refresh for {path}: (1) update the nearest CONTEXT.md if responsibility/"
             "key-files/gotchas changed; (2) append a memory/graph edge on a dep/API change; "
             "(3) log a DECISIONS.md line on a precedent; (4) update memory on a durable fact. "
             "Make these edits in THIS change — stale context is a bug.")
print(json.dumps({"hookSpecificOutput": {"hookEventName": "PostToolUse", "additionalContext": checklist}}))

The hook emits a checklist; the agent makes the edits in the same diff — reviewable, not a silent rewrite.

The Full Loop

session start: read root CONTEXT.md + MEMORY.md
per task:      plan → panel reviews plan → you approve →
               implement subtask (tests in same diff) → panel reviews diff →
               full test+lint → commit → hook refreshes context/memory/graph → next
only stops:    push and deploy

That’s the whole harness for one agent: six artifacts and a loop. Each is a few lines of config or a markdown file; together they’re the difference between an agent that’s brilliant for an afternoon and one that’s still trustworthy on the thousandth edit.

A diagram titled 'The Disciplined Build' showing two parallel agents coordinating via shared contracts and a 'shared world' rather than direct communication, with details on the 'Keeper's' role and an 'Append-Only Decision Log'.

Scaling to Multiple Agents

One agent, harnessed like this, stays productive for months. Run several on the same repo at once and a new failure mode appears that none of the artifacts above address: the agents collide. They edit the same files, undo each other’s work, and re-litigate decisions one of them already made. The instinct is to have them “communicate.” That doesn’t scale and isn’t reliable. What works is exactly what lets human teams parallelize: coordinate through shared, written state, not conversation — and write down the hard-won decisions so nobody, carbon or silicon, silently reverses them.

Agents shouldn’t message each other. They read and write a small set of shared files that encode the state of the work — who owns what, what’s decided, what’s claimed, what’s done. Each agent acts on the world (the repo plus these files); the next one reads the world to decide what to do. Coordination becomes a property of the shared state, not of a conversation — which means it survives a restart and is auditable.

Ownership Map

Who owns which paths. Default ownership by directory; editing outside your area requires a claim.

| path                  | owner    | notes                       |
| core/**               | agent-B  | agent-A reads, doesn't edit |
| services/service-a/** | agent-A  |                             |
| shared/contracts/**   | shared   | claim required to change    |

Claim and Release

Cheap mutual exclusion, no lock server:

## CLAIM 2026-06-10T14:20Z · agent-A · task-114 · services/service-a/**
working: add retry to the fetch step    est: 40m
## RELEASE 2026-06-10T14:58Z · agent-A · task-114 · commit a1b2c3d

Before claiming, scan for an open CLAIM on overlapping paths in the last few hours; if found, pick different work. This is advisory/optimistic, not a lock — two agents can both scan, both see nothing, and both claim the same path (a TOCTOU race). If you need real mutual exclusion, use a primitive with atomic check-and-set: a uniquely-named git branch (the push fails if it already exists), or a conditional write to a coordination store. The file-append claim is good enough when collisions are rare and a human merges; don’t treat it as a hard lock.

Progress and Decision Logs

A progress log is append-only and timestamped. An agent starting up reads the last day to orient itself: what got done, who’s working where.

A decision log is append-only and serves as the spine that stops agent-B undoing agent-A’s reasoned choice. Every non-trivial system accumulates decisions: which datastore to use, that agents only propose changes, that all model traffic goes through one gateway, which components may loop. Six weeks later nobody remembers why, someone “fixes” one of them, and something breaks. The decision log makes those choices explicit, dated, and durable — binding on every agent that reads the repo.

Rules for Multi-Agent Coordination

  • Branch per task; humans merge — prevents unreviewed changes hitting main; the merge is the human checkpoint.
  • No agent-to-agent calls — prevents hidden side-channels; all coordination stays in the auditable files.
  • Stable public surface (declared interface per module) — prevents parallel refactors breaking each other.
  • Decisions are append-only and binding — prevents silent reversal of a load-bearing choice.
  • Claim before touching shared or other-owned paths — prevents two agents editing the same file.

The single-agent harness and the multi-agent coordination layer are complementary: the constitution, context, memory, review panel, and post-edit hook keep each agent disciplined in isolation; the ownership map, claim protocol, and decision log keep multiple agents from undoing each other’s work. Together they form a system where agents remain productive and trustworthy not just for an afternoon, but across a project’s full lifetime.