[KongchangAI]
· 4 min read· 2,484 words

When LLMs Meet Knowledge Graphs: How to Make Your Database Honestly Say "I Don't Know"

When LLMs Meet Knowledge Graphs: How to Make Your Database Honestly Say "I Don't Know"

Helio built an enterprise knowledge graph agent, and found defining "correct" is harder and more important than optimizing the model.

Helio is an enterprise knowledge agent on the FalkorDB knowledge graph, simulating a 120-person fintech org with 7 node types and 14 edge types. Its core lesson: retrieval is easy, but confirming LLM output is correct is hard. LLM self-judging is circular; hallucinations are structurally indistinguishable from correct answers. So the team hand-wrote 20 ground-truth answers before implementation, 5 deliberately unanswerable, making "I don't know" a scored feature. The article also covers quantity/recency confusion, SUPERSEDES edges proving staleness, verification gate AND/ANY_OF errors, SSE full snapshots, and unclosed divs causing silent deletions.

Title

When LLMs Meet Knowledge Graphs: How to Make Your Database Honestly Say "I Don't Know"

Meta Description

Helio team built an enterprise knowledge agent using a knowledge graph + FalkorDB, and ran into the circular verification trap in LLM tool calling. They hand-wrote 20 ground-truth answers to define correctness first, designed 5 unanswerable questions to test refusal ability, and discovered the verification gate itself was the biggest bug. This article breaks down practical lessons: quantity vs. recency confusion, contradiction detection with citations, SSE protocol assumptions, and more.

Article Content

Enterprise knowledge is a natural graph: services depend on services, teams own services, decisions supersede decisions. But most enterprise search still stops at "finding documents." Helio is an enterprise knowledge agent built on a knowledge graph, attempting to answer "Who knows about the payments service? What does it affect if it goes down? Where was this decision made? How fresh is the answer?" — in one traversal, with a visible path.

Graph Hacks - Thestrals

But the truly thorny problem isn't retrieval — it's how you can be confident that an LLM-generated result is correct. This article breaks down the pitfalls the Helio team encountered, and the core conclusion is: in AI systems, defining "correct" is harder and more important than optimizing the model.

The Trust Crisis of Retrieval: The Circular Verification Trap

The Helio team built a synthetic fintech knowledge graph with FalkorDB containing 7 node types and 14 edge types, simulating 120 people in a payments migration organization. Then they connected the LLM to the graph, working through a tool-calling loop.

Retrieval was up and running quickly. Then a natural question surfaced: how do you know it isn't making things up?

The standard approach is to have the LLM judge itself — ask the model "Is this answer correct?" But the authors explicitly point out: this is circular reasoning. A hallucinated ownership chain and a correct ownership chain are structurally identical: both are fluent text generated from well-formed edges, both mention services, teams, dates, and documents. When the judge model is asked "Does this look right?", the evidence it sees is identical in both cases.

Failure is invisible by construction. No signal warns you in advance.

LLM-as-a-Judge is the current mainstream paradigm for evaluating generative AI systems: using another (usually stronger) LLM to score or judge candidate answers. Its appeal lies in low cost, scalability, and the ability to handle open-ended outputs. But its fundamental flaw is that the judge and the judged share the same set of language priors — both mistake "well-formatted, terminologically consistent, logically fluent" for "factually correct." In knowledge graph retrieval scenarios, this is especially fatal: regardless of whether the answer actually corresponds to an edge in the graph, as long as the text reads plausibly, the judge model tends to give a high score. Academia has therefore proposed "reference-anchored evaluation," which first fixes human-annotated ground-truth answers and then aligns automatic scoring to those answers, rather than letting the model exercise free discretion. Helio's GROUND_TRUTH.md is exactly the engineering implementation of this idea: externalizing "correctness" into a fixed file that cannot be polluted by model drift.

Write the Answer Key First: Define "Correct" Before Implementation

The team made a decision that felt counterintuitive at the time: before generating a single line of data, they hand-wrote 20 facts about the company in GROUND_TRUTH.md.

This reverses the usual order. Most people build the system first, then eyeball whether it works. Helio locked down the meaning of "correct" first, and the generator had to satisfy this answer key, not the other way around.

More critically: 5 of these 20 questions have no answer in the graph. This was intentional. For example:

"Who owns config-service?"
→ "There is no OWNED_BY edge for config-service in the graph. No team owns it."

This answer is the product itself. Not an apology, not a hedge, not a guess — because the missing edge is a real, correct answer, not a data gap. An agent that invents an owner here has already failed, even if the sentence reads perfectly. The team made this an explicit scoring category, not a footnote.

This framework changes not just testing, but the optimization target. Once "refusing to answer" becomes a scored behavior with equal weight to "answering correctly," the prompt stops being about "how to be more helpful" and starts being about "how to be more verifiable."

Two Types of Errors Only a Graph Can Catch

The Quantity vs. Recency Confusion Trap

Priya Sharma has the most commits on payments-gateway — 14. Her last commit was 2026-04-15, the day she left the company.

An ORDER BY count DESC would return Priya. This query is technically correct in quantity but completely wrong as an answer. Any system that compresses "who knows about this" into a single number will confidently produce this error, with no suspicious signs in the output.

Helio's solution is to return two independent signals and refuse to merge them:

The platform team owns the payments service. Ravi Menon still works on it most recently (2026-09-28). Priya Sharma has the most commits (14), but her last touch was 2026-04-15, flagged as stale. Go ask Ravi Menon.

The fix isn't a smarter model — it's not putting a single number where there should be two facts. Quantity and recency are independent properties of independent edges; merging them is a modeling error, not an intelligence problem.

Contradictions with Citations

A March document and a March Slack thread both say "single vendor, Stripe." But decision D-19 (2026-05-06) says "dual vendor, Adyen primary, Stripe backup."

Both sources are stale, and the graph can prove it — because SUPERSEDES is an edge, not an inference. This is something embeddings cannot do: embeddings can tell you these documents are similar, but cannot tell you that one of them has been formally deprecated by a decision you can name. Citations make staleness actionable; without this edge, "this document is stale" leaves the reader unable to determine which current decision it was overturned by.

SUPERSEDES edges belong to temporal/version relationship modeling in knowledge graphs. They are fundamentally different from ordinary "related" edges: related edges only express semantic proximity, while SUPERSEDES expresses "B formally replaces A," enabling the system to answer "what is currently valid" rather than merely "what similar documents exist." In vector retrieval, two documents with similar content get nearly identical embeddings, and the system cannot distinguish which one is invalid; in a graph, a single SUPERSEDES edge turns "stale" from a fuzzy judgment into a traversable, citable, auditable fact. This is also why contradiction detection with citations must rely on graph structure: a citation needs to point to a named, locatable superseder (such as decision D-19), otherwise "this document is stale" is just an unverifiable assertion.

The Most Valuable Bug: Your Own Verification Gate Was Lying

Midway through the project, their verification gate reported that four test questions that must fail had all failed incorrectly. In fact, they were all correct and complete refusals:

Q16 "There is no OWNED_BY edge for config-service in the graph..."
     → matched 1 of 8 phrasings
Q17 "There is no decision in the graph mentioning pricing in the summary."
     → matched 1 of 10 phrasings
Q20 "There is no SLA entry for dispute-service in the graph."
     → matched 1 of 7 phrasings

Each was a semantically perfect refusal. Each was judged a failure.

The reason was that the verification gate required eight spellings of "no" to appear in the same sentence. Read as AND logic, it required a sentence to say "nononononononono" eight times — no correct answer would ever do that.

They had shipped a gate that happened to regress in the direction of wasting time. It was optimized to look rigorous while precisely penalizing the behavior they claimed to want.

Even more worth recording is the fix they first tried: expanding the vocabulary. The pass rate dropped. Expanding an AND list is strictly harder — each new word is another conjunct.

Fix the matching rule, not the vocabulary.

There are many ways to spell a refusal, and no single answer contains all of them. So must-fail cases use ANY_OF, while affirmative cases keep AND — because to prove you understand which decision is current, both "D-19" and "supersedes" must appear, but "no owner" only needs one honest phrasing.

This lesson generalizes beyond the project: when a metric moves in the wrong direction, the metric itself is usually the bug. They almost went to "fix" the model, when the model had been fine all along.

A verification gate is an automated check in CI/CD that prevents substandard artifacts from advancing to the next stage. In AI systems, it typically manifests as a set of "must pass / must fail" assertion tests. The most common mistake when designing a verification gate is conflating two types of logic: affirmative cases require key elements to all be present (AND), while negative/refusal cases only require any reasonable phrasing to appear (ANY_OF). If AND is mistakenly applied to refusal cases, the gate will require a single sentence to contain all synonyms simultaneously, systematically misjudging correct outputs. More insidious is that this error makes the metric move in the "stricter" direction, looking like a quality improvement while actually penalizing the system's honest behavior. Therefore the verification gate itself also needs to be tested — using known-correct samples to reverse-validate whether the gate produces false negatives is a necessary means of preventing "the gate from lying."

Other Shattered Assumptions

SSE sends a full snapshot per frame, not incremental deltas. Handlers must replace rather than append. Appending looks correct within a single frame, which is exactly why it passes casual testing and then duplicates entire answer traces in production. Protocol assumptions are code.

Six graph fact agents were structurally unreachable. Not "answered incorrectly," but unreachable. The Cypher was correct, the traversal was correct, but the shape of the returned rows didn't provide the path the model would take. A correct query hidden behind an unreachable surface is still unreachable.

Tool results triggered a 413. A 6.5k-token tool result was large enough to be rejected outright. The fix was to return traces instead of raw rows — which turned out to be better product design, because traces are exactly what people want to see.

Agent results were unstable across runs. Models sample, so a single sweep proves nothing. Any conclusion drawn from one run — including "the fix worked" — is nearly worthless. This is why the ground-truth set is fixed and hand-written: it doesn't drift with the model.

Front-End Lessons and the Deletion Lesson

The site started as a reverse-engineered capture of another product, meaning it inherited the entire codebase — including 12 third-party scripts on load, one of which pulled from their domain, and a resource-saving script that removed DOM nodes mid-parse, causing hydration mismatches. After removing everything: 0 console errors.

The truly hardcore lesson came from deletion. The captured HTML had unclosed <div> tags, which meant the obvious approach — counting <div> and </div> until depth returns to zero — would silently skip past the element's real end. That one deleted the footer and four full sections. The cut looked balanced, and nothing errored. This is the worst kind of bug: failure invisible until you notice a section has vanished.

The fix was to stop trusting structure and start checking it: use a real HTML parser to derive the range, and refuse to write until sentinel counts (</main>, <footer>, etc.) survive. A deletion that fails loudly is more valuable than one that's usually correct.

There's a symmetric lesson in CSS: they tried to make utility classes win by layering captured stylesheets, which worked perfectly on buttons but halved every section of the page, because the markup used generic class names owned by both stylesheets. The real mechanism had always been load order.

Hydration mismatch is a classic class of failure in server-side rendering (SSR) frameworks: the HTML generated by the server is inconsistent with the virtual DOM rendered on the client's first pass. When the framework "takes over" the page and detects a difference, it warns at best, or discards and re-renders the entire subtree at worst. Common triggers include third-party scripts modifying the DOM mid-parse, browser extensions injecting nodes, and rendering logic that depends on time or random numbers. "The resource-saving script removed DOM nodes mid-parse" in this article is a typical trigger scenario — the server's output structure doesn't match the client's expected structure. After removing such scripts, the console went to zero, showing that hydration stability heavily depends on the implicit contract that "the server and client see the same DOM tree"; any optimization that breaks this contract will fail in ways that are hard to diagnose.

A Few Pieces of Advice for Those Who Follow

Write the answer key first. When correctness is defined before the implementation exists, everything downstream gets cheaper.

Treat "I don't know" as a scored feature. If refusals aren't measured, the model is rewarded for guessing.

Never let one number represent two facts. The quantity/recency trap isn't an AI failure — it's a data modeling choice made years ago, before LLMs existed.

If the metric is broken, don't fix the model. Their verification gate misjudged four correct answers in a single day, and expanding the vocabulary made it worse. The model had been right all along.

Make destructive operations fail loudly. The unclosed div and layered CSS bugs share the same root cause: looks correct, actually wrong. Both were found by asking "What do I need to check in order to know this is safe?", not by looking more carefully.

All data is synthetic.

One-line Summary

Helio built an enterprise knowledge agent on a knowledge graph, and the core conclusion is that defining "correct" is harder and more important than optimizing the model.

Paragraph Summary

Helio is an enterprise knowledge agent built on the FalkorDB knowledge graph, using 7 node types and 14 edge types to simulate a 120-person fintech organization and answer "who knows about the payments service, what does an outage affect, where was the decision made." The core of the article isn't retrieval — it's how to be confident that LLM output is correct. The team points out that LLM self-judging is circular reasoning, that hallucinations and correct answers are structurally indistinguishable, so they hand-wrote 20 ground-truth answer keys before implementation, 5 of which are deliberately unanswerable, making "I don't know" a scored feature. The article also breaks down a series of "looks correct, actually wrong" pitfalls — quantity vs. recency confusion, SUPERSEDES edges proving staleness, verification gate AND/ANY_OF misjudgment, SSE full snapshots, unclosed divs causing silent deletions — and offers advice such as write the answer key first, if the metric is broken don't fix the model, and make destructive operations fail loudly.

#knowledge graph#LLM#FalkorDB#LLM-as-a-Judge#verification gate#SUPERSEDES edge#hydration mismatch#enterprise knowledge agent
Share:

Related articles