← Back to Blog

What hallucination is and why it hurts most in code

What hallucination is and why it hurts most in code

How is it possible that AI calmly fixes a completely different function than the one you meant and is fully confident it did exactly what you asked? The answer is called hallucination!

For language models, it means the model generates an answer that sounds confident and logical, but doesn't match reality or the actual request. In code this takes a specific shape: AI tends to pick the nearest option by word similarity, even when that option doesn't match the real requirement.

Example: you ask for a fix to the function calculateDiscount(). But the code also contains calculateDiscountRate() and applyDiscount(). The model, especially without precise context, may "assume" you meant the similarly named function, and fix the wrong place. The result looks finished, tests (if there are none) say nothing, and the bug surfaces three steps later.

What reduces hallucination:

  • An exact file and line reference, not just a function name recalled from memory.

  • Business context - what the function is for, not just what it technically does.

  • An explicit ban on touching similarly named but different places.

  • Smaller, verifiable steps - hallucination in a small step gets caught quickly; in a giant step it gets lost.

This is exactly where the standard "write a prompt and hope" approach hits a ceiling. What's needed is a system that knows where things are before you even ask the AI agent and that's exactly what contracts solve, which we'll cover starting next week.

Why this isn't just about similar function names

The same problem isn't limited to picking the wrong function, it applies to finding information in the code itself. When the same topic (say, "invoice") appears across several classes, methods, events, and DOM elements at once, the AI searches the code only until it hits the first match that "makes sense" and stops there. If the real logic you need to fix lives elsewhere (say, in a separate TemplateInvoice class, not in the generic invoice calculation), the model never opens it. It's not that it searched too few files, it's that it compares only against the nearest match to the request and doesn't continue.

Having documentation or skills prepared in advance helps, the AI then reaches the right information faster and more accurately. The problem is that such documentation doesn't maintain itself: if nobody saves it after a task, or if the AI itself decides a piece of information "isn't important," it stays unsaved. The agent only saves what it considers most important from the whole run, not everything. On larger projects, search also gets slower: individual pieces of business logic gradually get lost, and if there are multiple documents on the same topic (say, invoice mentioned both in an invoice doc and in a templates doc), the AI often reads only the first one it finds, decides it's a sufficient source, and never opens the others.

This has a practical consequence for prompts: if every request has to say "don't forget this and that, also check there," it stops being programming and becomes constant reminding. That's a signal that the information belongs in the system (a skill, a contract), not in the head of the person who has to type it into a prompt every single time.

Experiment: same prompt, same model, different result

To test the hypothesis, I ran a simple experiment. In the prompt, I wrote: "open and read the instructions file and follow it." The file said: when working with a real number, display it on the frontend as a decimal number in the format #.00, and store it in the log using the same formatting.

I then gave a task to build a form with two fields: age (integer) and height (real number) plus the usual requirements (color, position, a Save button, saving to the database). I ran the same prompt ten times, each time in a clean session, with no memory carried between runs, on the same model.

Result: in 2 of 10 runs, the model ignored the number-formatting instruction from the referenced file. Same prompt, same conditions, same model and still 20% hallucination. Asked why, the answer was always the same: in that moment, the model had judged other parts of the request as more important and "forgot" the formatting instruction.

How to actually reduce hallucination

Letting the AI simply check its own work isn't enough. The check itself is just as prone to hallucination as the original task. In practice, it works better to split the work into two steps:

1. A small, explicitly defined task. It's better to put the rule's content directly into the prompt, rather than just referencing a file the AI "may or may not" read in full.

PromptTask:

  1. a form

  2. input fields formatted correctly by type - int with 0 decimal places, real with 2 decimal places (this can live in a file too, but it must be included directly in the prompt, not just referenced, so the AI isn't left to read it on its own),

  3. log real values with 2 decimal places

  4. save to the database.

2. A separate verification prompt (*CheckPromptTask*), run only after the first task is finished, with the same numbered structure as the request - we ask the AI exactly what we defined in PromptTask:

CheckPromptTask:

  1. how was the form implemented?

  2. how are the int and real input fields formatted?

  3. how are real values stored in the log?

  4. is the form's data actually saved to the database?

The key point is that the AI answers these questions based on the actual change in the code (the diff, the files), not from its own memory or a guess — at this step it has practically no room to hallucinate, because it's answering based on what's really in the file.

Then it's just a matter of comparing the CheckPromptTask answers point by point against the PromptTask requirements (1↔1, 2↔2, 3↔3, 4↔4) — whether the answer matches the request. If something doesn't match, the cause gets tracked down and the fix is targeted — not a redo from scratch.

With this approach, hallucination drops to low single-digit percentages — not a clean zero, but far below the 20% from the first test. Combined with unit tests, integration tests, and manual testing, hallucination on larger and more complex changes can be pushed close to zero.

Concrete comparison: same request, two outcomes

Request: "Fix the discount, it's not calculating correctly."

Plain AI chat: opens the file that looks closest to the name - say, calculateDiscountRate() instead of calculateDiscount(), because the prompt never said which exact function you meant. It fixes that one, the test (if one exists) for the correct function still shows nothing, and the production bug stays. Only a customer in production discovers the discount is still wrong.

AITM: before the task is even created, agent-chat calls contractsForVariable / searchDom and finds the contract that describes exactly the discount logic - with a concrete files: ["src/pricing/DiscountService.ts"] field and behavior: "calculateDiscount() applies the % discount after subtracting the coupon, not before it". The task prompt then cites exactly %PRICING-004, not a generic "discount," and the architect step (Day 17) opens only that one file. The risk of the agent touching calculateDiscountRate() by mistake effectively disappears. Not because the model got smarter, but because it doesn't have to guess anything.

What hallucination is and why it hurts most in code — screenshot 1

Why this beats a well-written prompt alone

The approach from the experiment above (small task + verification CheckPromptTask against the real diff) works — but only if a person prepares it themselves every single time and remembers to run it. AITM applies exactly this principle systematically and automatically, for every task:

  • Contracts replace "paste the rule into the prompt." Instead of the user having to retype number formatting, function location, or a business rule into every request, a contract (e.g. %PRICING-004) stores it once, with an exact file reference and a description of the behavior. The agent doesn't guess by word similarity, it gets the exact coordinate before it even starts searching.

  • The docs step actually writes documentation after every task - not "if the AI decides it's important." Writing/updating a contract is a mandatory pipeline step, not optional agent memory.

  • Verification against the real diff is built in, not a manual extra step. The review and test steps in the pipeline ask what actually changed in the files, following the same principle as CheckPromptTask in the experiment.

The result of my own test without contracts was 20% hallucination across ten runs of the same request. With the structure of small task + contract + verification against the diff (exactly what the pipeline does automatically), hallucination on an individual step drops to single-digit percentages — not because the model is different, but because it doesn't have to guess anything, and nobody has to remember everything to type into the prompt every single time.

What hallucination is and why it hurts most in code — screenshot 2

AITM optimizes the prompt, and the optimized prompt produces the result of the task. We then check that result against what the task required and what the AI actually did.