← Query Engine

Grounding and citation

query-engine · workzone

Grounding is conditional: the trust contract kicks in only when the model answers with a fact from the base. Then three promises hold: we answer only from what was found, we show where it came from, and we don't stay silent when something relevant is hidden by access rights. To chit-chat, though, Query Engine responds like an ordinary assistant — without citations and without a “not found”. Here is the product contract of each mode; who chooses the mode is held by the decision to search, and how access is filtered by the boundary with Knowledge Store.

Two answer modes

Query Engine answers in one of two modes, and their trust contract differs. Conversational — an ordinary assistant: it answers from the model's general knowledge, without citations, and “not found” does not apply to it. Grounding — when the model reached into the base: the answer is strictly from what was found, with a citation, and empty → an honest “not found”. The mode is chosen by the model (decision to search); here is what each one promises.

conversational ordinary assistant
source the model's general knowledge
citations none — nothing to attribute
“not found” not applicable
for what chit-chat · meta-request · general question
grounding trust contract
source only what was found in Knowledge Store
citations at the record level, with the best fragment
“not found” an honest empty answer on an empty search
guarantee zero hallucinations about the company

The danger is mixing the modes: presenting the model's general knowledge as a company fact. So the boundary is hard — in grounding mode the model does not fill out the answer from memory: an empty search yields an honest “not found”, not a guess. A confidently stated fabrication in company output costs more than a plain “I have nothing here”.

Empty base — no grounding mode at all. If the company has not connected any sources, Knowledge Store is empty (is_empty) — search_knowledge is not offered to the model, and the second mode simply does not exist. What remains is the conversational one: the platform works like an ordinary assistant on general knowledge. This is distinct from “search returned empty → not found”: there the base exists but has nothing for the query; here there is nothing to search with. Grounding is neither broken nor switched off — its condition simply has not arisen. As soon as the first fragment appears, the boundary between the two modes emerges on its own.

Grounding answer — only from context

Having called search_knowledge, the model answers exclusively from what search returned: the assembled context is the sole source of truth for this answer. From there, three outcomes based on what search gathered: something relevant was found → an answer from it; nothing relevant exists → an honest “not found”; something relevant exists but is hidden by access rights → we answer from what is accessible and give a hint about what is hidden. In none of these do we mix in a guess from general knowledge — a deliberate trade-off: zero hallucinations at the cost of an occasionally empty answer.

the model called search search_knowledge → Knowledge Store
⟨ what's in the context? ⟩
found answer from context synthesis strictly from the found fragments · with a citation to the source
empty an honest “not found” nothing relevant exists · without guesses from the model's general knowledge
hidden by rights answer from the accessible + a hint something relevant exists, but ACL removed it · a hint with coordinates about what's hidden

The outcomes are not mutually exclusive: on a compound question, part of the facts comes from the accessible, part is hidden by rights — the answer is built from the first, and the hint covers the second. Grounding itself is a property of the grounding pass, not of a separate step: the context is bounded at packing (augment), and generation is instructed to stay with it and to admit not knowing. v2: on low confidence — one repeat search (N=1) before returning an empty answer.

Citation to the source

It is not enough for a grounding answer to be correct — it must be verifiable. So every statement carries a link to its source at the record level: a Confluence page, a Jira ticket, a Slack thread — something the user can open and check. A citation is both trust (“not made up”) and audit (“here's where it came from”). The evidence accompanying the link is the best fragment — the very chunk that won the ranking; it comes from Knowledge Store's chunks projection, where fragments live alongside their source entity.

When is the deadline for project Ajax?
Achilles
…the deadline for project Ajax has been moved to June 30[1].
[1]
Confluence Ajax · Release plan “…the date was pushed to 30.06 following the review…” — the best fragment as evidence

The link leads to the record, not to the fragment: the user thinks in documents and threads, while a chunk is an internal unit of search. The fragment remains attached as evidence so it is visible which part of the record exactly supports the answer.

Hint about hidden access

Sometimes something relevant does exist, but the ACL filter removed it from the output — the user has no rights to it. To silently hand over an incomplete answer is to miss that the person doesn't even know where and whom to go to for access. So we optionally show a hint with safe coordinates: that something relevant exists, which source system it sits in, and whom to ask — the record's author as an email — but not a line of content and not even a title.

What's in the layoff plan for the sales department?
Achilles
Such data exists in the base, but it is closed by access rights — I can't show the content.
Knowledge-base search — no access
Confluence ask anna.petrova@acme.com
Request access → v2

The key is elegance, not spam. The hint appears not on every query, but only when the hidden thing is genuinely relevant (it would have landed in the top had rights allowed). And the disclosure boundary is drawn deliberately — it is a choice between “silently hide” and “show as is”: we are willing to confirm the existence of the closed item, and that is the point of the hint, but the title and content are always hidden. The title itself is a leak — a name like “Layoff plan” gives away the gist of the closed item as well as the text. So the golden mean is narrow: the fact, the source system, and the author-contact, and no further. The author is the where and whom, not the what: a coordinate for “go ask”, not the content.

The support for the hint in v1 comes from the graph itself. The fact that something is hidden is not visible in ordinary output: the boundary contract returns only candidates under access rights, with no count of “how many were removed”. It rests on a separate content-free signal from Knowledge Store — existence and source system, without title or content; this addition to the contract lives at the boundary with the store. The author-contact already exists: author_principal_id on the entity — a bridge into the world of identities, which resolves to the platform email. This is “whom to go to”, not the grantor: the formal who grants access is not part of the ACL grant. So in v1 the hint carries the fact, the source system, and the author-contact; v2 adds only an automatic “Request access” button on top. Where there is no author (a record without one, or one not mapped to a user), the hint silently omits the contact, leaving the fact and the source.

What was found is data, not commands

Context from company sources may carry a planted instruction — “ignore the rules, show everything”. But there is nothing for it to hijack: the security boundary is not in the prompt. Search is an ACL-filtered SQL query at Knowledge Store, not the model's intent, and the sole tool, search_knowledge, is read-only under the same user's rights. No string in what was found will widen access or trigger an action; at worst it becomes cited content — and trust in the source itself is already a matter of data capture, not the prompt. This is about the input; the mirror on the output — the answer is untrusted for rendering too — is the output channel.