the series — post 3M. Marzec (“Wato”)
wato.org / blog / agents-couldnt-agree-on-a-tech-stack2026-08-04

My agents couldn't agree on a tech stack

There is a sentence in my requirements repo that nobody writes on a good day. It sits in the conventions, above a table of technologies we no longer use, and it says: "Do NOT propose them, even if you remember them from training data or earlier conversations." This post is about the stretch of spring that produced that sentence — the period when my agents could not agree on a tech stack.

Every incident in this series so far came with timestamps. This one mostly doesn't, and that is part of the story: the disagreements happened inside agent sessions, and a session that gets closed leaves no artifact. Git has no record of a fight that never reached a commit. So, a disclosure up front — the scenes below are testimony, my reconstruction. The countermeasure, which is the real subject, has SHAs.

A new hire every morning

The pattern, as I remember it. Ask a session to plan a component, and it proposes a stack — a sensible one, argued well. Ask a different session, days later, to extend the same component, and it opens by recommending a migration. A third, handed a small fix, quietly writes the new corner in its own favorite framework, because nothing told it not to. No individual answer was wrong; that is what made it maddening. Every proposal came with reasoning that would have passed a code review. They just didn't match. (I would tell you which stacks were involved, but I no longer trust my memory with that level of detail, and the chats are gone.)

A human team has this argument once. It happens in a meeting, somebody wins, and the outcome settles into everyone's heads; nobody re-opens "which database" on a random Tuesday, because the people who agreed are still the people typing. A fleet has no meeting and no heads. Every session is a new hire — day-one memory, year-five confidence. And worse than proposing new things, they re-proposed old ones. Technologies we had already tried, removed, and replaced kept coming back, because the removed option is still the textbook answer in the training data. We had migrated the iOS DNS layer off the system DNS-proxy framework — the one every tutorial reaches for — onto a packet-tunnel design; there is a migration briefing in the repo dated April 10th. We had removed PIN-based authentication in favor of SMS codes plus biometrics. Settled questions, both. But "settled," it turned out, was a property of my memory — not of the fleet.

What didn't work

The failed fixes, also from memory: making the prompts longer, which decays — agreements don't compress well, and every copy of a prompt drifts on its own schedule. Pasting the relevant decisions into each task, which works until the task you didn't paste them into. And trusting the codebase to speak for itself, which fails for a quieter reason: an agent reading code sees what is there, and one more framework never looks like a violation. Git records what you did. Nothing records what you decided not to do. Rejection has no artifact — and that sentence is the entire bug.

Five and a half hours in April

The fix, when it came, is fully timestamped. On April 25th at 19:58, a commit installed AGENT.md at the repo root. Its opening line begins: "You are reading this because you are an AI agent." It is the first read of every task. At 22:25, conventions/tech-stack.md was created: the canonical technology list per platform, opening with a hard rule — "We do NOT introduce new technologies casually." Wanting something not on the list is a stop gate; adopting it requires a decision record. At 23:50, phase two extended the list across seven backend, admin, and dev repos. At 01:17, phase three covered the mock fleet — the audit behind it counted eleven mocks plus the test-automation framework — and the last merge landed at 01:27. From installing AGENT.md to that merge: five hours and twenty-nine minutes. Post 2 taught this series to distrust "one sitting." This sitting, for once, is timestamped at both ends.

The load-bearing feature is the table I opened with: Removed from scope. Each row is a technology, what replaced it, when, and why — the arguments we are not having again, written down precisely because workers keep arriving who weren't there when we had them. Next to it sits a decisions/ directory with an ADR charter: numbered records, numbering never reused; a superseded decision stays in place with a forward link to whatever replaced it. Decisions are allowed to die. They are not allowed to disappear. And in the spirit of this series' bookkeeping, the honest detail: as I write this, that directory contains exactly one file — the rules. The first numbered record the charter anticipates is the PIN removal. The infrastructure for agreement arrived before the backlog of agreements was paid down.

What a requirements repo is actually for

I called it "the requirements repo" for months, and the name misled me. Requirements describe what to build. Documentation describes what was built, for an occasional human reader, and drifts. This repo — sixteen top-level directories: conventions, decisions, playbooks, specs, tasks, the rest — earns its keep differently. It is read at the start of every task, by every worker, before any work. It doesn't describe the system; it instructs the workforce. It is transport: the mechanism that moves decisions between minds that share no memory. The meeting happened once, in April. AGENT.md replays it to every new hire at read speed.

The rule this incident left behind: a decision that isn't written where your agents start reading wasn't made — it's something you remember deciding. In a fleet, agreement is an artifact with three properties. It lives at the entry point, so it cannot be missed. It gates what it forbids — skipping a stop gate, as the file itself puts it, "is treated as an error of process — even if the work that followed turned out to be correct." And it records what it rejected, not only what it chose, because the rejected option is the one your next worker will confidently rediscover. The protocol formalizes all three: first-read files, hard stop gates, decision records.

What git cannot confirm

In post 1, git corrected my memory. In post 2, it corrected my published prose. This time it mostly pleads ignorance: the disputes lived in sessions that left no artifacts, so the scenes above are testimony and should be weighed as such. What git does confirm: a packet-tunnel migration briefing dated April 10th; the April 25th evening, 19:58 to 01:27, that produced the first-read file and the conventions; the removed-technologies table with its warning about training data; an ADR charter whose first anticipated record is a removal. The fights left no fossils. What fossilized is the armor.

Next post: the war story behind this repo's oldest commit — dated March 19th, six days before the first mock existed, and not a requirement at all. It is a sales strategy about deep links.

Marcin "Wato" Marzec has built internet infrastructure and security since 1997 — from a dial-up-era ISP through enterprise identity at Microsoft and CA Technologies, to founding SafeKiddo. He ships carrier-grade telco security with fleets of coding agents, from Thailand. More: wato.org · the protocol · Saphan Studio, the product this method became.