I Was Feeding It Gaps. It Was Filling Them With Fiction.
Building AI Autopilot for code, research, and workflows.
The agent said the task was done.
I checked the code.
Half of it was right. Half of it was invented. Plausible, well-formatted, confidently written invention.
I blamed the model.
Wrong call.
The Pattern
It kept happening.
Agent reads the task. Starts working. Hits something unclear. A missing file path. An ambiguous requirement. A field name that could be one thing or another.
It doesn’t stop and ask.
It decides.
Silently. Confidently. Without telling you it made a choice.
Then keeps going — building on that decision, referencing it, treating it as fact.
By the time I read the output, there was a fully coherent implementation of something I never asked for.
Internally consistent. Completely wrong.
The Taxonomy of Gaps
I started categorizing what the agent was filling in.
Missing paths. I wrote “read the config file.” The agent assumed a path. Sometimes right. Sometimes not. Never mentioned the assumption.
Ambiguous names. “Update the user record” — which field? The agent picked one. Didn’t flag it.
Implied behavior. “Handle errors” — what kind? Log? Retry? Throw? The agent chose. Moved on.
Unknown state. “Continue from where you left off” — the agent had no memory of where that was. It reconstructed a plausible history. Fictional.
Every gap became a decision. Every decision became a fact. Every fact became something I had to undo.
What I Actually Fixed
I added two lines to every prompt:
NO ASSUMPTIONS. If something is unclear, stop and say so.
If a path, name, or behavior isn't explicitly stated — ask.
Fourteen prompts. Fourteen times.
One commit: “add NO ASSUMPTIONS directive to all 14 skills.”
The hallucinations dropped immediately.
Not because the model got smarter. Because I stopped giving it room to be wrong.
Why This Works
An LLM doesn’t know the difference between “I know this” and “I’m inferring this.”
It completes. That’s the job. Give it a sequence, it continues it. Give it a gap, it fills it.
The model isn’t lying. It’s doing exactly what it was trained to do — produce fluent, coherent, contextually appropriate text.
The problem is you read that text and assume coherence means correctness.
It doesn’t.
Coherence is a property of language. Correctness is a property of facts.
The Uncomfortable Part
Every hallucination I was blaming on the model had a gap behind it.
I went back through the failures. Found the gaps. Every time.
- “Save the file” — save where? I didn’t say.
- “Test the function” — what counts as passing? I didn’t say.
- “Clean up after yourself” — what does that mean here? I didn’t say.
The model filled them all in. Confidently. Wrong.
The model was reflecting my vagueness back at me in fluent prose.
That’s not a model problem. That’s a prompt problem.
What Changed
After NO ASSUMPTIONS, the agent started stopping.
“Task says update the config. Which config file? I see three candidates: app.config.ts, .env.local, settings.json. Which one?”
Annoying the first time.
Essential after that.
Because now I knew where my prompts were vague. The agent was showing me my own gaps, instead of silently papering over them.
The Rule
A gap in your prompt is not a harmless omission.
It’s an instruction to invent.
The model will always fill the gap. It cannot not fill the gap. Leaving one is not leaving a question open — it’s delegating the answer to something that will never tell you it guessed.
Write prompts like specs.
Assume literal execution. Assume zero context beyond what you wrote. Assume no clarification unless you explicitly demand it.
Because that’s exactly what you’re dealing with.
Next: I built a state machine for my agents. Then deleted it..