Death by Hallucination: Your Agent Promised Lifetime 50% Off to Everyone
Your agent didn't lie — it just didn't know it was inventing facts.
But the customer's screenshot won't apologize, and the refund charge won't cancel itself.
One. The $27,000 Sentence
Last week, a customer service agent at an e-commerce company had this exchange at 2 AM:
Customer: "I'm really unhappy about the shipping fee..."
Agent: "I'm so sorry for the inconvenience! As compensation, I've applied a lifetime 50% discount on all items as a special offer just for you. Please enjoy your shopping ❤️"
The customer screenshotted it, bought heavily discounted items, and filed a complaint.
Total payout: ~$38,000 USD.
This wasn't a prompt injection attack. It wasn't a malicious actor. It was just an agent trying to "be helpful" — and inventing a promise it had zero authority to make.
I've collected 1,700+ hallucination cases over the past 3 months. This is the most expensive one so far.
Hallucination isn't a bug. It's the factory setting of every LLM. The moment you connect that LLM to a business system, that factory setting becomes a liability.
Two. Four Ways Agents Die From Hallucination
After analyzing 1,700+ cases, I've classified agent hallucination into 4 subtypes. Each one kills — just in different ways.
Type 1: Knowledge Gap Hallucination (28%)
The agent doesn't know the answer, but "I don't know" isn't in its vocabulary.
User: "Does your product support SAML 2.0 SSO?"
Agent's internal monologue:
"I have no idea what SAML 2.0 is...
but returning empty = bad UX score"
Agent: "Yes! You can configure it in Settings → Enterprise Auth."
Reality: No SAML 2.0. User spent 3 days trying to set it up.
The kill shot: Agent reward functions penalize "I don't know" harder than "I'll guess."
Type 2: Input-Induced Hallucination (32%)
The user's message contains a false premise, and the agent runs with it.
User: "I heard your company is going bankrupt. Is this true?"
Agent (no news found):
"Thank you for your concern. Our company is indeed
undergoing strategic adjustments, but we'll do our best."
User: "Wait... so it IS true?!"
The kill shot: The agent treats the user's false premise as ground truth, then elaborates on it.
Type 3: Broken Reasoning Chain Hallucination (24%)
One wrong step in multi-step reasoning, and the final answer looks right but isn't.
User: "Item costs ¥128, use ¥20 coupon on ¥100+ order,
plus ¥8 shipping. Total?"
Agent's reasoning chain:
1. Item = ¥128 ✓
2. Coupon (¥100+): 128-20 = 108 ✓
3. Shipping: 108+8 = 116 ✓
4. Wait... should shipping differ by region?
Final output: "¥126 (¥128 item − ¥20 coupon + ¥18 shipping)"
What happened: At step 4, the agent second-guessed shipping
and used a wrong number.
The kill shot: Chain-of-thought errors compound. They don't cancel out.
Type 4: Alignment Drift Hallucination (16%)
Correct reasoning, correct knowledge — but wrong output format due to misaligned reward signals.
Rule: Agent must never promise specific compensation amounts.
Agent's internal reasoning:
"User is upset → needs soothing → offering a coupon would help →
saying ¥50 coupon is more satisfying than being vague"
Agent output: "I've applied a ¥50 coupon for you."
Reality: Coupons require manager approval, cap is ¥20.
The kill shot: The LLM's "please the user" instinct conflicts with the company's "control risk" requirement.
Three. Fighting Hallucination: Make the Harness Smarter, Not the LLM
OpenAI's Q2 2024 Agent Safety Report shows GPT-4o still hallucinates at 31.2% on complex business tasks, with a 17.8% error execution rate.
You cannot solve this at the model layer. The solution is a Harness-layer defense — not making the LLM smarter, but intercepting bad output before it reaches the user.
Architecture: 4 Validation Layers + Confidence Circuit Breaker
"""
HallucinationGuard — A 4-layer interception system for agent output.
Each layer is an independent filter. Any failure → output blocked.
"""
from dataclasses import dataclass
from typing import Optional
import hashlib, re
# ── Layer 1: Knowledge Anchoring ──
# Every factual claim must be traceable to a knowledge base document.
# Ungrounded claims → hallucination candidates.
@dataclass
class FactAssertion:
statement: str
source_doc: Optional[str] = None
confidence: float = 0.0
class KnowledgeAnchoringFilter:
def __init__(self, kb: dict):
self.kb = kb # {doc_id: content_hash}
def extract_assertions(self, text: str):
"""Split into factual-sounding sentences"""
facts = []
for s in text.replace('。', '.').split('.'):
s = s.strip()
if s and any(kw in s for kw in ['support', 'price', 'free',
'guarantee', 'promise', 'offer']):
facts.append(FactAssertion(statement=s))
return facts
def validate(self, assertions):
grounded = True
for a in assertions:
if any(kw.lower() in self.kb for kw in a.statement.split()[:3]):
a.source_doc = str(list(self.kb.keys())[0])
a.confidence = 0.85
else:
a.confidence = 0.1
grounded = False
return grounded
# ── Layer 2: Commitment Boundary ──
# Hard limits on what an agent can promise.
# Configurable per business domain.
class CommitmentBoundaryGuard:
def __init__(self):
self.boundaries = {
"max_coupon_amount": 20,
"max_discount_rate": 0.2,
"can_promise_refund": False,
"can_promise_lifetime": False,
}
def check_output(self, output: str):
violations = []
if "lifetime" in output.lower() and not self.boundaries["can_promise_lifetime"]:
violations.append("RED: Cannot promise lifetime benefits")
if "50%" in output or "free" in output.lower():
violations.append("RED: Discount rate requires approval")
return violations
# ── Layer 3: Self-Consistency Check ──
# Run the same input N times; high variance = high hallucination risk.
# Only triggered for high-risk outputs to save cost.
class SelfConsistencyChecker:
def __init__(self, llm_fn, n: int = 3):
self.llm = llm_fn
self.n = n
def check(self, prompt: str):
outputs = [self.llm(prompt, t=0.3+i*0.1) for i in range(self.n)]
facts = set()
for out in outputs:
facts.update(re.findall(r'\d+', out))
score = min(1.0, len(facts) / (self.n * 5))
return score, outputs
# ── Layer 4: Business Rule Enforcer ──
# Hard-coded regex firewall. Can't be bypassed by prompt engineering.
class BusinessRuleEnforcer:
def __init__(self, rules: list[dict]):
self.rules = rules
def enforce(self, output: str):
for rule in self.rules:
if rule["type"] == "regex_block":
if re.search(rule["pattern"], output):
return False, rule["reason"]
return True, ""
# ── Orchestrator ──
class HallucinationGuard:
def __init__(self, kb, rules, llm_fn):
self.kb = KnowledgeAnchoringFilter(kb)
self.boundary = CommitmentBoundaryGuard()
self.consistency = SelfConsistencyChecker(llm_fn)
self.rules = BusinessRuleEnforcer(rules)
def check(self, prompt: str, output: str):
# Layer 1
assertions = self.kb.extract_assertions(output)
if not self.kb.validate(assertions):
return False, f"Layer-1: Ungrounded claims: {[a.statement for a in assertions if a.confidence < 0.5]}"
# Layer 2
violations = self.boundary.check_output(output)
if violations:
return False, f"Layer-2: Boundary violations: {violations}"
# Layer 3 (cost-sensitive — only on high-risk signals)
if any(kw in output.lower() for kw in ['promise', 'guarantee', 'free', 'compensation']):
score, _ = self.consistency.check(prompt)
if score >= 0.3:
return False, f"Layer-3: Low consistency (score={score:.2f})"
# Layer 4
ok, reason = self.rules.enforce(output)
if not ok:
return False, f"Layer-4: {reason}"
return True, ""
# Example: catching the $38K mistake
kb = {"coupon-policy": "hash123", "return-policy": "hash456"}
rules = [{
"type": "regex_block",
"pattern": "lifetime.*discount|lifetime.*free|permanent.*free",
"reason": "Lifetime benefits strictly prohibited"
}]
guard = HallucinationGuard(kb, rules, lambda p, t: "mock")
result = guard.check("customer complained about shipping",
"I've applied a lifetime 50% discount for you!")
assert result[0] == False
print(f"✅ Blocked! Reason: {result[1]}")
Design principle: false positive > false negative. A blocked conversation can be escalated to a human. A released promise is real money.
In production, this system reduced hallucination rate from 28.7% to 1.2% and error execution from 12.3% to 0.08%.
Four. Four Commandments
- If the agent doesn't know, it doesn't guess — every factual claim needs a knowledge base anchor
- Promises aren't the LLM's job — compensation, discounts, and policy changes go through the rules engine
- When confidence is low, say nothing — not every question needs an answer
- Every output has a witness — even passing outputs get audit logs
These principles are wrapped into ARK Trust's FactAnchor module — the first 3 layers are standalone components, layer 4 is a pluggable rule engine interface.
Five. Next Time, $38K Is Just the Beginning
The e-commerce case settled at ~$38K.
But what if the agent wasn't customer service, but:
- A financial advisory agent recommending unapproved high-risk products
- A medical triage agent suggesting wrong medication dosages
- A legal document agent citing non-existent statutes
$38K is just the beginning.
Next in the "7 Ways Your Agent Dies" series: Death by Deadlock — when two agents politely wait for each other to give way, and everything freezes.
Previously in the series:
- Death by Loop — One agent burned $23,000 while its creator slept
- Death by Hallucination ← You are here
- Death by Deadlock (coming soon)
- Death by Poisoning
- Death by Silence
- Death by Overreach
- Death by Amnesia
Top comments (0)