Hallucination prevention
Hallucination, an answer that sounds right and is not, cannot be turned off. Preventing it takes prompt engineering, context engineering and flow engineering together: tell the model what to do, give it the facts, and shape the path so a guess has nowhere to land. See promptPrompt engineeringEngineering the instruction given to the model.Opens in a new tab, contextContext engineeringDeciding what the model sees on every call, because the window is finite.Opens in a new tab and flowFlow engineeringDesign the task as a flow of steps: a model where judgement is needed, plain code everywhere else.Opens in a new tab engineering.
Habits that cut it down
- Retrieval tool grounding. The answer comes from what a tool returned, not from the model’s memory (see retrieval at query timeRAG at query timeA one-way chain: embed the query, search, stuff the chunks into the prompt, generate.Opens in a new tab).
- No answer from history. A fact that can change, like a status or a balance, is fetched again, not read back from earlier in the chat.
- Never invent IDs or tool config. If the lookup finds nothing, the right output is “not found”, not a plausible ID.
- Low temperature. Sampling is less random. It helps, but a confident wrong answer is still possible.
- Structural guards. Take the choice away from the model, as in the tenant guard below.
- Reflection agents. A second pass critiques the first before it is final (see reflectionReflectionCritique the output before finalizing it: one agent does, another reflects.Opens in a new tab).
Anthropic’s guide adds three prompt-level ones: allow the model to say it does not know, have it quote the source first, and have it retract any claim it cannot back with a quote. It also says plainly that these reduce hallucination and do not eliminate it.
A tenant guard
The model should not pick whose data it reads. Here the tenant comes from the runtime, and a missing order returns a refusal to guess.
from dataclasses import dataclass from langchain.tools import ToolRuntime, tool @dataclassclass Ctx: tenant_id: str ORDERS = {("acme", "A-1001"): "shipped"} @tooldef get_order_status(order_id: str, runtime: ToolRuntime[Ctx]) -> str: """Look up an order's status by its ID.""" status = ORDERS.get((runtime.context.tenant_id, order_id)) return status or "No such order. Do not guess one."The runtime parameter is hidden from the tool schema, so the model sees only order_id and cannot supply a tenant of its own.
Sources
- Reduce hallucinations, Claude Docs · accessed October 5, 2026
- Tools, LangChain Docs · accessed October 5, 2026