Trust & risk

It answers confidently when it has nothing

Hallucination is a nuisance in a demo and a liability in a legal memo. The fix isn't a better prompt — it's making every claim trace to a real quote, and making an empty scope refuse instead of filling the gap with fluent prose.

Same assistant, two questions. The first is grounded in the master services agreement and cites the exact clause. The second has no Delaware authority ingested for this matter — so it refuses and names the empty scope instead of guessing.

Sound familiar?

Fluent and wrong looks identical to fluent and right

The model writes the same confident sentence whether it found the answer or made it up. Nobody catches the difference until someone acts on it.

"Where did that come from?" has no answer

A reviewer asks which document supports a claim and the honest answer is that nobody knows — the citation, if there is one, doesn't point anywhere specific enough to check.

One bad answer undoes ten good ones

Trust in the system is asymmetric. Nine correct, cited answers build confidence slowly; one confident hallucination in a client-facing document ends the pilot.

Why the usual fixes don't move the number

"Only answer from the provided context" in the prompt

An instruction is a request, not a constraint. The model can still generalise past what was retrieved, especially when the retrieved context is thin and the question is easy to guess at.

Lowering temperature to reduce hallucination

Temperature controls word-choice randomness, not whether the underlying claim is true. A deterministic wrong answer is exactly as wrong as a creative one.

A generic "sources" list at the bottom of the answer

A list of documents that were retrieved is not the same as a claim that traces to a specific quote. Nothing stops the model from citing a real document next to a claim it doesn't actually support.

Trusting the model to say "I don't know"

Models are tuned to be helpful, not silent. Without an explicit empty-scope check, the default behaviour under uncertainty is a plausible-sounding guess, not a refusal.

How we solve it

01Every claim carries a citation target

Not a source list — a typed pointer per claim: the chunk, document, and exact quote it came from, pinned by content hash so it can't drift after the fact.

claim → chunk_idcontent_hash pinnedquote, not just a link

02Retrieval is scoped before generation starts

The same typed-label scope binding used for permissions also defines what counts as "in scope" for this answer — so the model can't reach past the evidence it was actually given.

scope bound to tasklabels, not free text

03Empty required scope refuses, by name

Zero chunks in a required scope is not treated as "try anyway" — it's a refusal that names which scope was empty, recorded on the run like any other outcome.

0 chunks → refusenames the scoperecorded on the run

What you get on every document

A quote, not a vibe

Every cited claim shows the exact text it came from, so verifying an answer is a click, not a re-read of the source document.

No silent fallback to "everything"

A missing or empty scope narrows retrieval to nothing rather than quietly widening to the full corpus — the same rule that keeps permissions safe keeps answers honest.

Refusals are a normal, logged outcome

"I can't answer, this scope is empty" is a valid run outcome with its own state, not an error path bolted on afterward.

Consistent behaviour under the same gap

The same missing evidence produces the same refusal every time, instead of an answer that varies by phrasing or model mood.

The obvious objections

Build your first agent with Inteleto