You do not stop hallucinations with the prompt
Data first, then tools, then hard rules. The prompt comes last.
The question I get asked most about the bot is how I keep it from making up prices. The short answer is that I do not do it with the prompt. I did try at first, and I learned the hard way that every new rule in the prompt fixed one case and broke two neighbors.
What I use today is a ladder with four rungs. When a problem shows up, it gets fixed at the lowest rung possible, and the prompt is the last resort, not the first.
- 1. Data Fix the catalog or the normalization. If the data is right, the model has nothing to invent.
- 2. Tool The rule travels in the value the tool returns. It exists only in the turn where it applies.
- 3. Guard A hard rule reviews the reply before it goes out. If it fails, the model regenerates.
- 4. Prompt Last resort. A rule here spills over every neighboring case.
Rung 1: the data
The trade-in price is the clearest example. At first the tool that quoted a trade-in took the price as a parameter, and the model pulled it from the conversation. Sometimes from yesterday’s transcript, at yesterday’s rate. Sometimes from nowhere.
Today the tool takes which phone the customer wants and reads the price from the database. The daily exchange rate does not go through the model either: it is read from the catalog mirror on every call. If the model cannot touch the figure, it cannot invent it.
Data fails too, and when it does the bot lies with total confidence. One day the trade-in sheet came through with a single row, the sync copied it as if it were fine, and the bot spent the day refusing trade-ins as if that were store policy. Out of that came a sanity guard: if the sheet has fewer than ten rows, the sync raises an alert instead of copying. That fix is also rung 1.
Rung 2: the tool
This is the discovery that changed how I work the most. A rule written in the prompt is static: it applies on every turn, including the ones where it should not. An instruction that travels in the value a tool returns exists only in the turn where that tool was called.
The case was the waiting list. The rule said something like “if a model we restock is out of stock, offer the waiting list”. In the prompt, that rule spilled over into questions where it made no sense, and the bot offered a waiting list for phones that will never come back. Moved into the search result, next to the rows it returns, it shows up only when the search came back empty for a model that gets restocked. Same text, different place, zero side effects.
Rung 3: the guard
Some rules cannot be guaranteed from the data or the tools, because the model can still ignore them. That is what guards are for: twenty-eight reasons today, reviewing the draft before it goes out. The ones that fire most are an amount with no backing in any tool, a stock claim the search did not return, and a trade-in quote given without asking for model, capacity, and battery.
When a guard fails, the model regenerates inside the same run, with a note saying what was wrong. If it fails again, the reply is discarded and the chat goes to a person. The customer never sees the discarded attempt.
Guards have their own cost, and I paid it. The amounts guard became so strict that it discarded correct replies: repeating a price the customer themselves had said counted as an invention. The rule that came out of that is that every new guard gets calibrated against about six thousand production turns before merging, measuring false positives. That deserves its own post.
Rung 4: the prompt
The prompt exists and has rules. What it does not have is the freedom to grow. A test pins a budget of 900 lines: to make it bigger you have to raise the cap in the same PR, and the diff makes it visible in review. A prompt grows without limit if nobody defends it.
What stays in the prompt is what covers most turns: who the bot is, how it talks, what it does when it does not know. Everything that is a special case lives lower on the ladder.
Why the order matters
Every rung you climb loses precision and gains reach. A correct piece of data fixes a problem for good, with no side effects. An instruction in the tool fixes a problem in the turn where it applies. A guard catches the problem after it happened, and it can be wrong. And a rule in the prompt changes behavior on every turn, including the ones that were fine.
Rung 1 is the one most often skipped, because it is the most expensive: normalizing data is boring work and the prompt is one git push away. But it is where every hour invested pays the most. That is where Chatty’s biggest debt sits today, and the work in progress.