Skip to content

When Agents Fail Silently

There's a bug in Everywhen that never happened, and I think about it more than most of the ones that did.

Everywhen is a geography-and-history learning game I shipped to the App Store. It tracks how many times you've recalled a place. The obvious way to store that is a counter (a column called attempts, incremented on every answer). It's one integer. It's fine.

It isn't fine. Answer three questions on your phone in airplane mode, answer one more on your iPad, then reconnect. Last write wins. The count that syncs last overwrites the other instead of summing with it, and three attempts vanish. Nothing errors. Nothing logs. The app looks like it's working, because by every check it makes, it is. The user notices weeks later that their numbers feel wrong, and by then there's no record of what was lost.

So Everywhen doesn't store counters. It stores an append-only log of attempts and derives the count from it, which makes every sync an idempotent upsert (no merge algorithm to get wrong). The row-level security works the same way: an event trigger makes a forgotten policy impossible instead of just unlikely, because I'd rather a migration refuse to run than have a table quietly start serving someone else's rows.

I bring this up because it's the shape of just about everything I believe about building software. The dangerous failure is the quiet one. A crash tells you it crashed. A 500 tells you it's a 500. The bugs that actually hurt people are the ones where the system reports success and is wrong.

That's the lens I brought to working with AI. It turned out to be the whole game.

In the last five months I've built seven products as a one-person studio, and all seven are live on the App Store. Games, edtech, a journaling app, native utilities. Most of that code was written by agents.

I want to be precise about what that did and didn't change, because this is the part that usually gets skipped. It didn't turn me into a faster typist with extra steps. It changed which half of the job is scarce.

It used to be that writing code was expensive and reading it was cheap (I'd just written the thing, it was still warm, I knew where the bodies were). Now writing code is nearly free and reading it is the whole cost. My actual working day is specification and review. The agent proposes. I decide.

And the thing about an agent's output is that it's confident. It compiles. It has tests. The tests pass. The naming is good, the structure is plausible, and it'll explain its reasoning to you in fluent, well-organized paragraphs. Nothing in it tells you which parts were carefully worked out and which were pattern-matched off something adjacent and almost right.

So: an agent's characteristic failure mode is silence. It's the exact failure mode I'd spent years learning to design against, showing up now at volume, with excellent grammar.

The clearest case I've hit: I was building a writing tool (you speak a revision out loud, the model returns a diff, and nothing touches your words until you accept it).

Somewhere in the save path there was a branch where, under one particular sequence of events, the editor's contents resolved to empty before the write. The app would save. It would report success. It would write a blank page over a chapter.

Every test passed. Of course they did - the tests were written against the same understanding that produced the bug. I found it reading the write path out loud, the way I read a schema before a migration, asking the only question I've learned to trust: what does this do when it's wrong?

I was on a deadline. I nearly didn't look. That's the part I keep sitting with - not that I caught it, but how completely ordinary it would have been to ship it.

Four practices came out of this, and they're all downstream of the same idea.

The usual framing here is trust (how much do you trust the model, when do you check its work, what's your confidence threshold). I think trust is the wrong axis entirely.

I don't trust a compiler either. I just know exactly what it guarantees and what it doesn't.

The useful question isn't how much do I trust this? It's what is this thing's failure mode, and have I built somewhere for that failure to be loud? You can work very fast with a reckless collaborator, as long as you know the exact shape of how they go wrong and you've made that shape visible. That isn't a compromise with AI. That's most of engineering, and it always was.

Seven apps in four months is a velocity number, and velocity numbers are boring. The number I care about is zero - the number of times a user has written to me about lost work.

I design and ship products end to end - see the work or get in touch.