The draft promised a refund window that does not exist
In short
When an AI support reply invents a policy, search your corpus for the asserted term first: if it is absent, the model inferred it from what similar products usually do; if it is present but stale or contradicted, the corpus is the defect rather than the model. The fix is a commitment vocabulary that cannot be written without a citation, checked after generation.
Key takeaways
- Search the corpus for the exact term first. Absent and stale are different defects with different owners.
- A drafted commitment that an agent sends is a commitment the company made, in full.
- Numbers, durations and the words refund, credit, guarantee and cancel are the commitment vocabulary.
- Enforce the rule after generation, not only inside the instructions the model may ignore.
- Blocking a sentence is better than blocking a draft — an all-or-nothing guardrail gets switched off.
A draft asserted a term nobody at your company ever wrote — a refund window, a credit, a cancellation right. Before touching the prompt, run one search: look for that exact term across every source the drafting system can read, including retired documents and every localised version. What comes back tells you which of 3 defects you have, and they need 3 different fixes.
This matters more than the average drafting bug because of what a support reply is. When an agent sends it, the company has said it. Whether a model composed the sentence is a fact about your tooling, not a defence, and it is why a human-in-the-loop review layer exists at all.
One search, 3 possible answers
- Search every readable source for the specific claim — help centre, internal policy store, macro library, past sent replies, terms pages, and anything in the retrieval index that is no longer published anywhere a customer can see.
- Search for the concept as well as the wording. A model that wrote "within 30 days" may have grounded itself in a document saying "one month", which is a match for this purpose.
- Check the localised and market-specific copies separately. A term that exists only for one region, retrieved for a customer in another, is a corpus scoping problem rather than an invention.
- Check the account state the model was given. A correct policy applied to a stale entitlement produces a false sentence built entirely from true inputs.
- Record which of the 3 outcomes you got — absent, present but wrong, or present and contradicted — because the remedy branches here and nowhere else.
| Search result | What happened | Who owns the fix |
|---|---|---|
| The term appears nowhere | The model inferred a norm from what products like yours usually offer | Engineering: the generator was allowed to assert without a source |
| The term appears, but is out of date | The corpus is wrong and the model reported it faithfully | Whoever owns the policy document, plus whoever owns re-indexing |
| The term appears in 2 documents that disagree | Retrieval picked one; a coin flip decided what the customer was told | Policy ownership: 2 documents cannot both be authoritative |
| The term is right, the account is not | A true policy applied to entitlement data that had not synced | Integration: the state feeding the prompt lags the source system |
That last row is missed constantly, because everything reads correctly in isolation. The policy is accurate, the sentence is grammatical, and the plan name in the prompt was simply hours out of date — the sync failure argued in polling against webhooks for keeping tickets in sync. Check what the model was told before you conclude it made anything up.
Why absence produces confident text rather than silence
A generator asked to answer a question it has no source for will still answer, because nothing in the objective rewards refusal. It fills the gap with the most probable version of the thing — and for a product in your category, the most probable refund window is whatever your competitors offer. The output is fluent, plausible and specific, which is precisely the combination a reviewer under time pressure accepts.
A model has no way to distinguish a policy you have from a policy a company like yours would probably have. Only your corpus can make that distinction, and only if the system is required to consult it.
So the durable fix is structural: make the ungrounded sentence impossible to emit, rather than instructing the model not to want to. An instruction is a preference the model weighs against everything else in its context. A check that runs after generation is not.
The words that may not appear without a source attached
You do not need a citation on every sentence — that produces a wall of markers agents stop seeing, and it slows drafting for no benefit. You need one on the sentences that can bind you. That set is small enough to enumerate, and enumerable is what makes it enforceable.
- Any sentence containing a number or a duration. Days, months, percentages, counts, limits and thresholds — the shape of nearly every commitment a support reply can make by accident.
- The commercial verbs: refund, credit, waive, cancel, extend, upgrade, downgrade, guarantee, compensate. Each names an action with a cost attached, and none of them should ever be improvised.
- Eligibility and entitlement language — "your plan includes", "you qualify for", "this is covered" — which asserts a fact about the account rather than about the product.
- Future-tense operational claims. "This will be fixed in the next release" is a commitment on a team that did not agree to it, and it is the one support most often makes on engineering's behalf.
- Anything naming a legal or regulatory position. Support drafts are not the place to characterise a right or an obligation, and a model asked to will produce something confident and unverifiable.
This is also the honest boundary for macros. Wording that is legally or procedurally fixed should stay fixed text a human wrote and approved, not something regenerated each time — the line drawn in keeping the macro library or letting it become the training input. Everywhere else, a generated sentence with a citation beats a macro nobody has read since it was written.
Check after generation, and reject the sentence rather than the draft
Put a deterministic pass between the generator and the compose box. It does not need to be clever, and it should not be a second model asked politely to review the first.
- Split the draft into sentences and flag every one that matches the commitment vocabulary. Pattern matching is enough here, and its predictability is a feature — an agent can learn what will be flagged.
- For each flagged sentence, require an attached source reference that the retrieval step actually returned. No reference, no send, regardless of how confident the generator reports itself to be.
- Verify entailment, not overlap. The cited document must support the specific number or term in the sentence; a document about refunds generally is not a source for a 30-day window.
- Replace the failing sentence rather than the draft. Strike it, mark the gap visibly, and let the agent write that one line — an agent who loses only the sentence keeps the other 90% of the draft, and does not learn to disable the check.
- Log every rejection with the sentence and the reason. Those logs are the shortest route to the missing policy documents, because they are a list of questions your corpus cannot answer.
The same architecture catches a related class of defect at the same point, which is a good argument for building the pass once and reusing it: the pre-send validator that refuses any outbound text containing unresolved delimiters, described in an unrendered placeholder shipping in a live reply, belongs in exactly this position in the pipeline.
When the corpus is wrong, do not patch it in the prompt
If the search found the term and it was stale, the model behaved correctly. Adding an instruction that overrides the document is the worst available fix: you now have 2 sources of policy, one of which is a prompt, and the next person to change the policy will change the document and wonder why nothing moved.
Fix it at the document, then confirm the index actually picked the change up — a corrected policy that is still serving from a stale index is indistinguishable from no fix at all. Where 2 documents contradict each other, resolve the contradiction rather than tuning retrieval to prefer one: a system that relies on ranking to pick the right policy will eventually rank the other one first.
What the guardrail will not catch
It catches assertions, not implications. "I have escalated this to the engineering team" contains no number and no commercial verb, and it still creates an expectation you may not meet. Tone can commit too, and a sufficiently warm draft implies more than its sentences say. Neither of those is reachable by pattern matching, and both are reasons the named human sender stays in the loop rather than being optimised away.
It also will not tell you which policies you are missing until customers ask. The rejection log is the closest thing to that list, which is why it is worth keeping and reading monthly. Building the check, the source-attachment rule and the logging is MVP and product build work in our SaaS and customer support practice, and it sits alongside the rest of drafted replies and agent assist.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
Our AI support reply promised a refund we do not offer. Are we bound by it?
Treat it as though you are, and take advice for anything material. A reply sent by your agent from your helpdesk is a statement your company made, and "the model wrote it" describes your tooling rather than excusing the sentence. Operationally the safer posture is to honour the specific case, correct the source that produced it, and stop it recurring before the same sentence reaches a hundred more customers.
How do we stop a model inventing policies it has no source for?
Require a source for the sentences that can bind you, and enforce it after generation rather than only in instructions. Flag every sentence containing a number, a duration, or a commercial verb such as refund, credit, cancel or guarantee; require an attached reference that the retrieval step returned; and strike the sentence when there is none, leaving the rest of the draft intact.
Is this a hallucination, or is our knowledge base at fault?
One search settles it. If the term appears nowhere in your corpus, the generator inferred it and the fix is engineering; if it appears but is out of date or contradicted by another document, the model reported your corpus faithfully and the fix belongs to whoever owns the policy. Those 2 look identical from the compose box and have nothing else in common.
Should the guardrail block the whole draft or just the sentence?
Just the sentence, every time. Blocking the draft costs the agent everything the model got right and trains them to route around the check, which is how safety features get disabled by the people they were built for. Striking one sentence, marking the gap and letting the agent write that line keeps the review layer credible.
- drafted replies
- grounding
- policy
- guardrails
The work behind this page
Builds from our portfolio that this page draws on.
Read next
- Agents are deleting the same sentence out of every draftA repeated identical deletion is the cheapest diagnostic signal a drafting system produces. It says something is still emitting that sentence — and the prompt is the wrong place to stop it.diagnostic
- An unrendered placeholder shipped in a live reply"Hi {{first_name}}" reaching a customer is not one bug. It is 5, and the first question — did the model write those braces, or did your template engine fail to remove them — decides which.diagnostic
- Draft acceptance rate: three outcomes it has to separateOne acceptance percentage hides the only signal worth having. Sent unchanged, sent after edits and discarded are three different verdicts, and the middle one carries almost all the information.definition
- Internal note: the half of a ticket the customer never readsEvery helpdesk has 2 compose boxes behind one text field. The internal note holds the reasoning, the doubt and the account context — and it is discoverable, which changes what belongs in it.definition
- A mail loop is manufacturing tickets between your system and theirsRunaway ticket volume from a single counterparty is rarely spam. It is two automated systems answering each other, and the fix is a header rule your responder should already have been applying.diagnostic
- Customer replies are opening new tickets instead of threadingOpen the raw source of one orphaned reply. Whether the References chain contains your outbound Message-ID decides whether this is a matching bug, a stripped-header problem, or an identity problem.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