The AI draft quotes a price that is in no rate card: tracing the number
In short
A number in an AI-drafted itinerary that matches no rate sheet came from 1 of 4 places: historical figures sitting inside retrieved text, a pricing tool that returned nothing and was never told to fail loudly, a unit or currency mis-carry, or a rounded marketing figure restated as a quote. Trace the digits through the run's retrieved context and tool log before touching the prompt.
Key takeaways
- Every figure in a draft must resolve to a row identifier and a read time, or it is not a quote.
- The commonest origin is a real number from last season, sitting inside an indexed example itinerary.
- An empty tool result returned with a success status is the second: nothing failed, so nothing stopped.
- Ratios identify unit errors fast — an exact multiple of the party size is a per-pax mis-carry, not a hallucination.
- Render commercial figures at document time from the row, so a stale number cannot survive inside prose.
Start with the digits, not the prompt. A figure in a drafted itinerary that reconciles against nothing has 4 realistic origins, and 20 minutes with the run's artefacts tells you which: the number was present in retrieved text, a pricing call came back empty and the model filled the gap, a unit was mis-carried between per-person and per-party or between currencies, or a rounded marketing figure was restated as though it were a quote. Each has a different fix, and 3 of the 4 are not model problems at all.
This is a tracing exercise rather than a definitional one. Which fields a model is allowed to write and which it may only read is settled in what grounded means when a model drafts a trip; assume that split is agreed and that something is leaking through it anyway.
Walk the number backwards through the run
- Freeze the artefacts. You need the run identifier, the exact draft as generated, the identifiers of every retrieved chunk, the tool call log with requests and responses, and the version of the rendering template. If a run cannot be reconstructed this way, that is the first defect and nothing below will work.
- Grep the retrieved context for the literal digits, then again with separators and decimals stripped. A hit ends the investigation: the model did not invent the number, it copied one you supplied.
- Read the tool log. Was a pricing call made at all, with what parameters, at what time, and what came back? An HTTP 200 carrying an empty result set is the classic finding, and it looks like success in every dashboard you have.
- Compare the wrong figure to the right one as a ratio. An exact multiple of the traveller count is a per-pax mis-carry. An exact multiple of the night count is per-night against per-stay. A difference of a few per cent is usually a stale rate version rather than a fabrication.
- Inspect the rendered document. Is the figure literal text inside the model's output, or was it resolved at render time from a row? If it is literal text, the defect is architectural and the specific number is a symptom.
- Only now look at the prompt, and expect to find nothing useful there. Prompts explain why a model chose to write something; they rarely explain where a number came from.
Four origins, and the signature that identifies each
| Origin | Signature | The fix |
|---|---|---|
| Historical figures in retrieved text | The number is real, and was correct 1 or 2 seasons ago. It appears verbatim in an indexed past itinerary, proposal or brochure | Remove numerals from anything indexed. Index descriptions, never rate sheets |
| Empty or failed pricing call | Tool log shows 0 rows, a timeout or a partial response, and the drafted figure is suspiciously round | Fail closed. An empty result must abort the document, not a paragraph |
| Unit mis-carry | The figure is an exact multiple or divisor of the party size, the night count or a room count | Carry units as structured fields — per pax, per party, per night, per departure — and never as prose |
| Currency mis-carry | Magnitude is right for a different quoting currency; the figure came from a supplier-currency row | Bind the currency to the row and convert at document time, never in generation |
| Rounded marketing figure | It matches a public 'from' line on your own website, ending in a round number | Keep marketing price copy out of the index entirely; it is the least reliable text you own |
The unit and currency rows are worth separating even though they feel like one problem, because they are found differently. A unit error shows up as an exact arithmetic relationship to something in the brief; a currency error shows up as a magnitude that is right for the wrong market. Neither is a hallucination, and calling them one sends the team to fix the wrong layer — the mechanics of quoting across markets are in customer currency against supplier currency.
Empty is not zero, and a timeout is not a price
The most damaging pattern in this family is a pricing service that answers politely with nothing. The model receives an empty payload, has an itinerary to complete, and completes it. No error is raised, no alert fires, and the draft looks exactly like every good draft — the general shape of which is set out in silent failure with no error and no alert.
Routing matters as much as refusing. A refusal that lands in a log is an outage; a refusal that lands in a consultant's queue naming the component, the dates and the missing rate is a contracting task somebody can close that afternoon. The full abstention path, including the briefs that should never reach a drafter at all, is modelled in when the drafter should refuse to draft.
Take the digits out of anything the model can retrieve
Most teams reach for a prompt instruction here, and it holds for a while. The durable version is to make the number unavailable: if no retrievable text contains a price, no retrieval can surface one to copy.
- Index what a component is, not what it costs. Descriptions, inclusions, durations, region and season belong in the index; the rate belongs in the pricing system and is fetched.
- Redact numerals at chunk time when you index past itineraries, PDF proposals or supplier CSV exports, which are otherwise the richest source of confidently wrong figures.
- Keep a standing test over the index that greps for currency-shaped tokens and fails the build when one appears. New document types get added by well-meaning people, and this is how a corpus quietly reacquires prices.
- Version the index and record which version a run retrieved from, so a wrong figure can be pinned to a specific ingestion rather than argued about.
- Keep rate loading a separate, traceable pipeline of its own — loading a rate sheet so prices stay traceable — because a figure that cannot be traced to a contracted sheet is not improved by being retrieved rather than generated.
Resolve figures when the document is built, not when the words are written
The architectural fix is short to state. The model emits component identifiers and quantities. The renderer resolves each identifier against the pricing system at document build time and writes the figure, alongside the row identifier, the rate version and the time it was read. Generated prose never contains a numeral in a commercial field, so there is nothing to go stale and nothing to restate 3 paragraphs later in a slightly different form.
That also gives the answer to the question consultants ask next: how long is this figure good for? A resolved price carries a read time, and anything held on the supplier side carries its own countdown — the behaviour described in the rate key, an opaque token with a countdown. Carrying the row identifier through to the finished document is what makes review fast, the mechanism in every line of the draft should point somewhere.
A figure with no row identifier and no read time is not a quote. It is a sentence that happens to contain digits, and it will be read as a commitment by the only person who matters.
The sweep that catches whatever survives
Even with the architecture right, run a mechanical check before a human reviews anything. Extract every numeric token in the assembled document and require each to match either a provenance record or an allow-listed non-commercial field — day numbers, durations, group sizes, altitudes. Anything unmatched is flagged, and the flag blocks the send rather than colouring it yellow.
Two neighbouring failures look similar in a draft and are not this one. A drive time that cannot be true is a constraint-supply problem, worked through in six stops and nine hours of driving on day two. A component that is priced correctly but closed on those dates is a metadata problem, covered in the model that keeps proposing a place that is shut. Running all 3 checks in one pass is the cheapest hour in this whole build, and the tooling around it is ordinary internal tools and operations work rather than anything exotic. The rest of the guardrail set sits in letting a model draft the trip, within our wider travel and tourism practice.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
How do I tell a hallucinated price from a stale one?
Search the run's retrieved context for the digits. If the number appears there, it is stale rather than hallucinated — the model copied a real figure out of text you supplied, usually a past itinerary or proposal. If it appears nowhere in the context and no pricing call returned it, the number was produced during generation, which is a different fix: remove the model's ability to emit a figure at all.
Should the model call a pricing service or read a retrieved price?
Call the service for anything that can change between retrieval and send, and never let the model write the result into prose. Retrieval is appropriate for descriptive content whose staleness is visible; a price, an allotment state and a cancellation term are not, because a wrong one looks exactly like a right one. The renderer places the figure from the row at document build time.
What should the drafter do when no rate exists for the dates requested?
Stop and say so, naming the component and the dates. An unpriced component is a contracting gap, and a refusal routed to a consultant turns it into a task somebody can close; a draft that quietly writes around the gap ships a document that looks complete and fails at booking instead. Distinguish this from a service error, which is an operational problem with a different owner.
Is a rounded figure in a draft always a sign of a fabricated price?
No, but it is worth checking first, because 2 common origins both produce round numbers: a model filling an empty tool result, and a public 'from' figure copied out of marketing copy that was indexed by accident. Compare the number against your own website text before assuming the model produced it — the second case is a corpus hygiene problem and is fixed by what you index, not by how you prompt.
- itinerary drafting
- pricing
- provenance
- guardrails
The work behind this page
Builds from our portfolio that this page draws on.
QuoteForge
An AI CPQ and proposal platform that builds enterprise quotes from your catalog, guards every discount against the margin floor, routes approvals, and generates the proposal.
Sales AIAskVault
An AI internal knowledge-search platform that answers employee questions from your own docs — grounded in citations, with knowledge gaps surfaced and deflection tracked.
Productivity AIRead next
- Drafts that put a closed property on day four: fixing seasonal blindnessSeasonal blindness is a metadata failure, not a prompting failure: the closure lives in a sentence nobody can filter on, so the shut property stays in the candidate set the model draws from.diagnostic
- Hallucinated, not contracted, or not available: three different failuresOne symptom, three defects. An invented property, a real one you do not hold, and a contracted one that is sold out need three unrelated controls — and the middle case is the one that reaches the client.definition
- The draft packs an impossible day: constraining pacing without hard-codingAn over-packed day is not a prompting failure. The generator was handed no durations and no travel times, so it had nothing to violate — the fix is a mechanical day budget and a validator with a bounded retry.diagnostic
- Bookings confirm on your site and the supplier has no recordA confirmation email proves the checkout finished, not that a supplier accepted anything. Here is the timed comparison that shows whether your booking script reads live availability or a copy.diagnostic
- Enquiry-to-booking conversion: the metric that lies at six monthsGroup enquiries by the month they arrived and follow them until they close. The calendar-month ratio moves when volume moves, so a growing month looks like a bad one.definition
- Follow-ups still chasing a client who already paid: the state gapA paid client getting "still thinking it over?" is not an email problem. It is two systems holding quote state, with the exit condition wired to the wrong event or to no event at all.diagnostic
Working on something in this space?
Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.
Start the conversation