Most AI agents hallucinate confidence. When asked for the cheapest way to fly from SFO to Tokyo in business class using credit card points, they spit out a number without checking if the underlying data actually agrees. Lewisaweβs new agent, Safari, submitted for the Sanity Challenge, does the opposite: it refuses to price anything when sources contradict each other. Instead of offering a caveat-laden estimate, it returns NOT_COMPUTED until the conflict is resolved against an authoritative source.
The Fail-Closed Architecture
Safari operates on a strict fail-closed design principle, meaning every price displayed on screen is generated by a deterministic TypeScript solver, not the LLM. The agent walks a typed graph in Sanity, moving from points currency to transfer partner to loyalty program to award chart entry. If the printed ANA chart says 85,000 points but a devaluation notice says 90,000 effective September 25, 2026, Safari blocks the entire request. It does not average the numbers. It does not pick the newer one arbitrarily. It waits for a human or a higher-authority rule to resolve the contradiction, then writes that decision back to Sanity so the next run carries it forward.
Sanity Context and Knowledge Bases
The build leverages Sanity Context in two distinct modes: GROQ mode for structured traversal and Knowledge Base mode for prose-based evidence. The developer deliberately excluded contradiction documents from the Knowledge Base, letting the system identify conflicts by reading source excerpts. This resulted in the Knowledge Base independently flagging the SFO-NRT price disagreement as a 'Critical' conflict, matching the agentβs own gate. This dual verification ensures that the evidence cited in the UI is consistent with the structured data, even if the LLM narration is unreliable.
Hardening Against LLM Hallucinations
Lewisawe learned the hard way that models like Amazon Nova Pro will invent inputs if allowed. Early versions let the model pass traversal rows to the solver, resulting in fabricated data. The fix was structural: runSolver now takes only trip parameters and re-runs the traversal on the server, removing the modelβs ability to feed itself fake data. Additionally, stream transforms strip
Key Takeaways
- Safari prioritizes correctness over availability, returning NOT_COMPUTED when data sources disagree.
- The solver is deterministic and TypeScript-based, ensuring the LLM never performs arithmetic.
- Sanity Context is used to independently verify conflicts found by the structured graph traversal.
- Input validation is strict: the model cannot inject fake routing data into the solver.
The Bottom Line
This is how agents should work: boring, verifiable, and stubbornly honest about what they don't know. If your agent guesses, itβs lying. Safariβs refusal to price a flight until it resolves a 5,000-point discrepancy is a masterclass in building trustworthy autonomous systems.