Postmortem

My Agent Wrote 149 Throwaway Scripts in 14 Days. The Bug Fix in Pass #102 Never Reached Pass #145.

August 3, 2026 · By Italo Campilii

My Agent Wrote 149 Throwaway Scripts in 14 Days. The Bug Fix in Pass #102 Never Reached Pass #145.

TL;DR

I counted the Python in one agent's working directory this morning. 164 files. 149 of them were written to run exactly once — 14,475 disposable lines against 1,087 durable ones, 93% of the code authored for a single execution. Nine groups are byte-identical; the largest is eight literally identical copies of the same 162-line script. A helper named get() is defined 101 separate times. There is a shared library — probe-lib.py, 84 lines, holding every dedupe fix the engine has ever learned — and nothing imports it. It cannot be imported: a hyphen is not a legal Python module name, so the library was unreachable from the moment it was named. The result isn't untidiness. It's 112 duplicate rows in the output file and the same company receiving two identical applications on the same day, because a fix written in pass #102 had no path to pass #145.

Two days ago I wrote about an analytics gate reading an instrument that could not see its audience. This is a different failure with the same signature: everything ran, everything exited zero, and the defect lived in a place no check was looking.

I found it by accident. I went into ~/career-engine/scripts/ to reuse a sweep I remembered writing, and I couldn't find it — because there were 310 files in the directory and none of the names told me which one was the good one.

What 14 days of agent-written code actually looks like

Here is the count, run this morning:

$ cd ~/career-engine/scripts
$ ls -1 *.py | wc -l
164
$ ls -1 *.py | grep -Ec 'pass[0-9]+|sweep-2026-[0-9]{2}-[0-9]{2}'
149

149 of 164 Python files carry a pass number or a date in the filename — sweep-2026-07-31-pass100k-slugprobe.py, jd-read-pass123b.py, fractional-pass140c.py. A name like that is a confession. It says: this file exists for one run, on one day, and nothing will ever call it again.

Fifteen files are durably named. Split by lines, the ratio is worse than the file count suggests:

Category Files Lines of code Share of code
One-off passes (passNN, dated sweeps) 149 14,475 93.0%
Durably named 15 1,087 7.0%
Total 164 15,562 100%

All of it inside a 14-day window — first file modified 2026-07-20, last 2026-08-03. The busiest single day produced 40 new Python files. The day before that, 31. The day before that, 37.

The pass numbers run to #145 across 66 distinct values. That is the shape of an agent doing real work and learning nothing structural from it.

Nine groups of these files are byte-identical

Sprawl on its own is survivable. Duplication is not. I hashed every file:

$ python3 - <<'EOF'
import glob, hashlib, collections
h = collections.defaultdict(list)
for f in glob.glob('*.py'):
    h[hashlib.md5(open(f,'rb').read()).hexdigest()].append(f)
dups = {k: v for k, v in h.items() if len(v) > 1}
print('duplicate groups:', len(dups))
print('files inside them:', sum(len(v) for v in dups.values()))
EOF

duplicate groups: 9
files inside them: 32

Nine groups. Thirty-two files. The largest group is eight files:

sweep-2026-07-30-pass85b.py
sweep-2026-07-30-pass86.py
sweep-2026-07-30-pass87.py
sweep-2026-07-30-pass88.py
sweep-2026-07-30-pass89.py
sweep-2026-07-30-pass90.py
sweep-2026-07-30-pass91.py
sweep-2026-07-30-pass92.py

Not similar. Not adapted. The same 162 lines, MD5-identical, eight times, across eight consecutive passes on a single day. The agent needed the same sweep eight times and wrote it out from scratch eight times rather than running the file sitting next to it.

The function-level view is the same story at finer grain. Counting every top-level def across all 164 files:

TIMES REDEFINED — ACROSS 164 FILES get() 101 ashby() 37 is_new() 37 probe() 36 lever() 35 strip() 32 norm() 31 101 independent implementations of one HTTP getter. Each is a place a fix must be applied.

An HTTP getter written 101 times. A record-normalizer written 31 times. Every one of those is an independent implementation with its own edge-case handling, and — this is the part that costs money — its own copy of whatever was wrong the day it was written.

The library exists. Nothing can import it.

The genuinely uncomfortable finding is that the agent did eventually build the right thing. probe-lib.py, 84 lines, opens like this:

#!/usr/bin/env python3
"""Reusable ATS slug-name probe. Usage: python3 probe-lib.py <namesfile>"""

It carries the engine's accumulated hard-won knowledge in its comments — every dedupe defect discovered and corrected, written down at the point of the fix:

# Pass #102 fix: dedupe on (company, ROLE), not company alone. Company-level dedupe
# suppressed every posting at any company already in the pipeline - including brand-new
# reqs for different functions - and made 5 straight passes wrongly report the well "dry".
#
# Pass #106 fix: strip parenthetical segments BEFORE normalizing the company name.
# "Amplify (Amplify Education)" normalized to "amplifyampli", which never matched the
# ATS slug "amplify" - so an already-submitted req read as never-touched and Italo sent
# Amplify a second identical application on the same day.
def norm_co(c):
    c = re.sub(r"\([^)]*\)", " ", c or "")
    return re.sub(r"[^a-z0-9]", "", c.lower())[:14]

That is a careful engineer's comment. It names the defect, the blast radius, and the fix. And it is completely inert:

$ grep -l "probe_lib" *.py | wc -l
0
$ python3 -c "print('probe-lib'.isidentifier())"
False

Zero files import it. Zero files can import it — probe-lib contains a hyphen, which is not a valid Python identifier, so import probe_lib was never going to resolve and import probe-lib is a syntax error. The library was written as a script you invoke, given a name no module system will accept, and then left in a directory with 148 siblings that each reimplement its logic from memory.

The knowledge was captured. The distribution mechanism was missing. In a fleet, those are two different problems, and solving only the first feels like solving both.

What it cost, in the output file

None of this would matter if the results were clean. They aren't. The engine's output is pipeline.csv, 1,315 rows:

$ python3 - <<'EOF'
import csv, collections
rows = list(csv.DictReader(open('pipeline.csv')))
k = collections.Counter((r['company'].strip().lower(), r['role'].strip().lower()) for r in rows)
d = {a: b for a, b in k.items() if b > 1}
print('rows:', len(rows))
print('duplicated (company, role) pairs:', len(d))
print('excess rows:', sum(v - 1 for v in d.values()))
EOF

rows: 1315
duplicated (company, role) pairs: 100
excess rows: 112

112 excess rows — 8.5% of the file. And the specific case the pass #106 comment warned about is right there in the data:

2026-07-31  Amplify (Amplify Education)  Senior Director, AI Transformation
2026-07-31  Amplify (Amplify Education)  Senior Director, AI Transformation
2026-07-31  Amplify (Amplify Education)  Director, Business Systems Technology
2026-07-31  Amplify (Amplify Education)  Director, Business Systems Technology

Two roles, each submitted twice, same day, same company. The fix for exactly this was written on pass #106. The duplicates are dated pass #113-and-later work. The fix existed, was correct, was documented — and had no route into the code that was actually running.

This is the failure mode I keep circling back to: a system where every individual step verifies clean but nothing compares one run to the next. Each pass checked its own output and found it fine. No check ever asked whether pass #145 knew what pass #102 had learned.

The surrounding artifacts tell you how normal this had become: 48 timestamped pipeline.csv.bak-* backups, 913 covers-pass* directories, 129 MB of working directory. The agent was treating the filesystem as an append-only log of attempts. That's a reasonable instinct for data. It is a poor one for code.

Three rules I'm applying

I am not going to pretend the answer is "make the agent write a well-factored library up front." Exploratory passes genuinely are disposable, and forcing premature abstraction on pass #3 would have slowed the useful work down. The problem isn't that one-off scripts got written. It's that the third identical one got written, and the fortieth.

1. The rule of three, enforced by a check, not by intent. The first script is a draft. The second is a coincidence. The third identical implementation is a defect the system should surface. A nightly hash-and-report over the scripts directory would have flagged the eight-file group on the day it appeared — the exact same shape as the scheduled-agent audit that found seven silent failures. The detection cost is one command.

2. Shared logic gets an importable name, and the import is the test. probe-lib.py becomes probelib.py, and the acceptance criterion for the refactor is not "the file exists" — it is python3 -c "import probelib" exiting zero from a sibling script, plus a nonzero count of files that actually import it. A library with zero importers is not a library. It's a document.

3. Fixes land in the shared path or they don't count as landed. The pass #102 and #106 comments describe real corrections to real defects. Both were applied to a file nothing ran. Going forward, a fix is closed when the code path that produced the defect imports the corrected logic — and when a duplicate-scan over the output file confirms the defect stopped recurring. Both are checkable, which is the only property that matters here; instructions that live only in prose drift, and so do fixes that live only in comments.

The broader pattern is one I already wrote about from the other direction. Two days ago I counted 480 installed skills against 49 the fleet actually uses — capability acquired and never invoked. This is the mirror image: capability authored, then abandoned one directory over. Both are inventory problems, and inventory problems in agent systems don't announce themselves. They compound quietly until you go looking for a file you know you wrote and can't find it among three hundred.

The 129 MB is not the cost. The two applications Amplify received on the same day are the cost.

FAQ

Why do AI agents write so many one-off scripts instead of reusing code?

Because writing a fresh script is locally cheaper than finding and understanding an old one. An agent starting a new task has no reliable index of what it wrote last week, and rediscovering a 162-line file's assumptions takes more context than regenerating it. Each individual decision is rational; the aggregate is 149 files and 14,475 disposable lines in 14 days. The fix isn't better intentions — it's making reuse structurally cheaper than regeneration by giving shared logic an importable name and a known location, and making duplication visible with an automated hash scan.

How do I detect duplicate code my agents have written?

Hash every file in the working directory and group by digest. Byte-identical duplicates fall out immediately — this run found 9 groups covering 32 files, including 8 identical copies of one 162-line script. For near-duplicates, count top-level function definitions across the directory: a helper defined 101 times, as get() was here, means 101 places a fix would have to be applied. Both checks are a few lines of Python and cheap enough to run nightly.

Is a library imported by zero files still useful?

It is documentation, not infrastructure. probe-lib.py held correct, well-reasoned fixes for two real defects and changed nothing about what ran, because no script imported it — and none could, since a hyphen is not a valid Python module name, making import probe_lib unresolvable and import probe-lib a syntax error. The practical test for a shared module is not that it exists but that importing it from a sibling script exits zero and that a nonzero number of files actually do so.

What is the rule of three for agent-generated scripts?

The first version of a script is a draft, the second may be coincidence, and the third identical implementation is a signal that the logic belongs in a shared module. The value of stating it as a rule is that it converts a judgment call into an automated check: scan the working directory, group by content hash and by repeated function name, and surface anything crossing three. Detection is what matters, because the agent writing script number three has no way of knowing it is number three.

Why didn't the duplicate applications get caught by validation?

Because every check was scoped to a single pass. Each run validated its own output and found it internally consistent, and nothing compared one run against the accumulated history in a way that would notice pass #145 lacked a correction made at pass #102. The defect only becomes visible at the level of the output file across time — a scan for repeated (company, role) pairs, which surfaced 100 duplicated pairs and 112 excess rows out of 1,315.

Does this mean agents shouldn't write disposable code?

No. Exploratory passes are genuinely disposable, and forcing an agent to build a clean abstraction on its third attempt would slow down the work that actually finds things. The problem is not that the first one-off script was written; it is that the fortieth was, and that a documented correction had no path into the code still running. Let the drafts be drafts, then make repetition and unreached fixes automatically visible so promotion into shared code happens on evidence rather than on remembering.

RUNNING AGENTS THAT GENERATE THEIR OWN CODE?

The expensive defects in agent systems aren't the crashes — they're the corrections that were made correctly and never reached the code path still running. Designing the shared-logic layer, the duplication checks, and the verification that catches the difference is the work I do. Get in touch, or see the press and hire page.

— Italo Campilii. Measured 2026-08-03 against ~/career-engine/ on my own machine: 164 Python files hashed and line-counted, probe-lib.py import-tested, and 1,315 pipeline.csv rows scanned for repeated (company, role) pairs. Every command above is reproducible over any agent working directory.

IC

Italo Campilii

AI systems builder and one-person operator. I run the infrastructure for five brands solo with Claude Code agent fleets — SEO, content, e-commerce ops, and the verification layer that keeps it honest. The Build Log is where I write down what actually works.