Why AI keeps hallucinating and how constraint files fixes the problem
Stop writing essay-length prompts. Start writing constraint files. Here's why targeted context beats broad knowledge and how it eliminates hallucinations.
Most people approach AI coding the same way.
They open a chat, type something like "please fix this bug" or "add a login page," and hope for the best. When the output isn't quite right, they add more detail. They explain the tech stack. The file structure. The coding conventions. The packages they want. The ones they don't.
And still, the AI hallucinates. It uses deprecated syntax. It suggests libraries no one asked for. It forgets the rules that were explained three prompts ago.
So they try again. Longer prompts. More detail. Maybe a different model.
This is the loop most developers are stuck in. And it's exhausting.
The Problem with "Just Prompting"
The issue isn't the quality of the prompt, it's that prompts are disposable. You write them, the AI reads them, and then they're gone. The next task starts from zero. Every conversation is a blank slate.
This is where the "prompt engineering" mindset falls short. People think the solution is better prompts. More carefully crafted instructions. But no matter how good your prompt is, you're still re-explaining the same context every single time.
There's a simpler fix: Remember DRY? Stop repeating yourself. Write it down once. Iterate on it only when needed.
Constraints Beat Prompts
Tools like OpenCode let you define an AGENTS file, a Markdown document that the agent reads at the start of every session. But the real power isn't in that one file. It's in building a system of interconnected documents that give the AI targeted knowledge instead of broad, generic understanding.
Here's what that looks like in practice:
AGENTS — The rules of engagement. Tech stack, coding conventions, import ordering, naming patterns, approved packages. Everything the AI needs to produce code that looks like mine. This is where each session begins.
PLAN — The project overview. What are we building? What are the success criteria? What's the design direction? This gives the AI the "why" behind every task.
TASKS — A phased breakdown of work with check-boxes. The AI knows what's done, what's in progress, and what's next. No more "where were we?" conversations.
JOURNAL — A running log of session summaries, key decisions, and progress. When you hit context limits or swap models, the new session reads this and picks up exactly where you left off.
BUGS — Known issues with file paths and descriptions. When I say "fix the validation bug," the agent knows exactly which file and which line I'm talking about. This is something that Agents can address at later time so they don’t get distracted.
The result? My prompts got stupidly simple.
What Simple Prompts Actually Look Like
Once you have this system in place, you stop writing essays. Here are real prompts I've used:
- "Begin Phase 3"
(Move on, the code you produced earlier is up to standard) - "Continue with the remaining steps"
(After a bug has been found that I want to address later) - "Merge to master and proceed with the remaining UX improvements"
(Here is where SKILLS are found useful for simple tasks like Git operations) - "Can you make the navigation smooth and indicative?"
( Constraints you set in PLAN will play huge role here )
That's it. No color codes. No "please use this library." No explaining the file structure for the tenth time.
To be completely transparent: These simple prompts come after I've reviewed the code. The workflow isn't blind trust. The agent proposes changes, I review them, I request adjustments if something isn't quite to the standard I expected, and only then do I say "proceed" or "merge." The simplicity of the prompt reflects the fact that the heavy lifting, the context, the constraints, the direction is already defined in the files.
The agent already knows:
- Which phase we're in and what tasks remain.
- What the design language looks like.
- Which packages I've approved.
- What I'm actually likely to accept during review.
I'm not begging for code anymore. I’m steering the predictable outcome.
Why This Reduces Hallucinations
Hallucinations happen when the AI has to fill gaps. When it doesn't know your conventions, it invents them. When it doesn't know your preferred packages, it guesses. When it doesn't know your file structure, it makes something up.
But there's another trigger most people don't talk about: context limits.
When you're deep into a session and approaching the context window limit, the AI starts losing track. Their brain is filled with data. It forgets earlier decisions. It contradicts itself. You either have to break the conversation down or start summarising for a new session to pick up where you left off.
This is where a JOURNAL file becomes invaluable. Think of it as a memory bank, a running log of what's been done, key decisions made, and where things stand. When you start a new session or swap to a different model, the agent reads the journal and catches up instantly. No more "what did we do so far?" back-and-forth. The context is preserved across sessions.
Constraint files eliminate the gaps in other ways too:
- Targeted knowledge beats broad knowledge. The AI isn't drawing from its entire training set, it's working within your defined boundaries.
- Explicit rules leave no room for invention. When the spec says "use interface for objects and type for unions," there's nothing to hallucinate.
- Phased tasks prevent scope creep. The AI knows exactly what "Phase 3" means. It's not trying to solve the whole project at once.
A Real Example: Phased Task Structure
Here's a condensed example of how to structure a TASKS file. This is a rough pattern to use and stay in control:
# Tasks
## Phase 1: Foundation
- [x] Set up project structure
- [x] Configure linting and formatting
- [x] Create base layout component
## Phase 2: Core Features
- [x] Implement user list view
- [x] Add loading and error states
- [ ] Create detail view with navigation
## Phase 3: Polish
- [ ] Add animations and transitions
- [ ] Improve mobile responsiveness
- [ ] Final accessibility audit
When I say "proceed with Phase 2," the agent knows exactly what that means. It checks the boxes as it goes. It doesn't revisit completed work. It doesn't jump ahead.
This structure alone has probably saved me more time than any "prompt engineering" technique I've tried.
The Compound Effect
Here's what surprised me: the benefits compound over time.
In week one, the constraint files saved me from repeating myself. By week three, the AI was producing code that felt like mine. It followed my patterns. It made decisions I would have made. The review process went from "fix all of this" to "ship it."
This is the real unlock with AI agents. It's not about finding the perfect prompt. It's about building a persistent context that makes every prompt more effective.
The AI doesn't need to know everything. It needs to know enough things. Targeted knowledge beats broad knowledge every time.
You might also like
Moving from one AI assistant to a team of agents
I stopped using just one AI chat and started using a team of specialized agents. Here is why I chose OpenCode, how I use it with Copilot, and why I prefer to own my own setup.
From Skeptic to Orchestrator: The 'Aha' moment that changed the way I build software
How a free t-shirt and a Tetris clone turned a skeptic into an AI orchestrator. Discover my journey from using GitHub Copilot to leading a 'team' of specialist agents with OpenCode.
Simulating API Responses with WireMock
Learn how to use WireMock to decouple your development process from external APIs, enabling faster and more reliable testing.