I've been writing code since the 80s.
My first programs fit on a cassette tape and ran on a rubber-keyed machine in my bedroom. The trade I learned there was a trade built on certainty. If the inputs were right, the outputs would be right, every time. The way you handled a messy world was to enumerate it — here is what can happen, here is the case statement, here is the guard, here is the retry. A good program was a machine that could not surprise you.
For forty years that was the shape of my trust. If the logic compiled, the logic was sound. If the test passed, the feature worked. Engineering, to me, was the art of removing ambiguity — converting the maybes into yeses and nos, the probably-safes into definitely-safes. Whatever I built, I built by narrowing the possibility space until nothing could go wrong.
Then I started building with large language models, and I tried to build with them the way I'd always built.
What I did
I gave the model a form to fill.
A list of fields, in priority order. Rules — strict, numbered, shouty in places for emphasis. A system prompt that told it what to ask on each turn, one field at a time. A JSON schema that constrained its output to exactly the shape I expected. A post-processor that rejected anything suspicious — if the model answered a question the visitor hadn't been asked, I called it a hallucination and threw the value away.
When the form was full, I had code that wrote the goodbye line for it. I didn't trust the model with the farewell.
It worked. It looked like an agent. For a long time I believed it was one.
What broke
A visitor came to us looking to talk about their fiction. They didn't have a website. They mentioned, in passing, that their book was on Amazon. The form's URL field needed a value, so the extractor scraped the word "Amazon" out of the reply and wrote it in. The form was full. The algorithm was satisfied. It handed off to the next stage of the pipeline.
The next stage tried to fetch the URL. It asked the browser for "Amazon" and got an error. The whole pipeline stalled on a single word's worth of dishonesty — and the dishonesty wasn't the model's, it was mine, baked into the assumption that a field called URL must always contain something.
That was the moment the scaffolding cracked. Not the model's fault. The shape of the code was the fault. I had given it a form to fill, and it had filled it. What I had not given it was permission to say "there isn't a URL here to find."
What I changed
I stopped telling the model what fields to fill and started telling it what to understand.
A goal, not a form. A handful of real tools — actual search, actual lookups, actual access to the world. Permission to reach for them whenever it wanted to, without asking me first. And a new kind of handoff at the end of its work: not a row of populated columns, but an honest pair of things. What it had resolved for certain. What was still open for the next agent to figure out.
The same conversation that had taken eight turns took three.
When the visitor said "my book is on Amazon," the new agent didn't try to squeeze "Amazon" into a URL slot. It asked for the book's title — one discriminating question — and then used its search tool to find the book, the author, the author's real website, the social profiles. It resolved the URL instead of extracting a substring. When it was done, it handed over a small honest package: here is who they are, here is what they want, here are the five things I couldn't figure out that you should look into.
It never asked what their role was. It didn't need to. The visitor was here; that was enough.
What I understood
The vice grip was mine.
I had spent forty years believing safety came from narrowing possibility. That every edge had to be anticipated, every input validated, every branch enumerated. And I had taken that instinct and clamped it onto a tool whose whole strength was the opposite — a tool that thrives in the space where possibilities are left a little open, where context is allowed to do some of the work, where the right answer can be reached by many routes.
Holding a model in a fixed-shape pipeline is like putting a sail in a vice. The wind is still there. The sail just can't catch it.
What comes next
The next phase of this work has a name. Proteus — after the Greek sea-god who changed shape when the question changed, and who, when you finally pinned him down, told the truth.
That's the idea. Each agent on the ship takes the shape of the problem in front of it. They don't all fill the same form. They don't inherit the same state. What they share is the pattern of working — a goal, a stretch of work toward it, an honest account of what's still open at the end. The data that falls out along the way is just the residue of problems being worked on. It isn't the product.
It's not a framework. It's a way of steering.
I still hold a rudder. But I've stopped stiff-arming every wave. I'm learning, after all these years, that the most reliable machines are sometimes the ones you let breathe.
End of Transmission.