Skip to content

Retrieval and admission

A query becomes an answer in two distinct stages, and keeping them distinct is the difference between a system that isolates tenants and one that merely tries to.

Query + action contextCandidate generationhybrid lexical + denseGraph expansionone hop of typed edgesRankingrelevance · recency ·authority · provenanceADMISSION FILTERtenant · scope · clearance ·statusHitsscored, cited, edge-bearing

Candidates come from hybrid search — lexical and dense together, because each fails differently. Lexical finds the exact identifier (billing/reconcile.py) that an embedding blurs into neighbouring files; dense finds the paraphrase that shares no words with the query.

Then one hop of graph expansion: pull in what the top candidates are connected to, so a lesson arrives with the incident that caused it and the decision that contradicts it.

Then ranking, which is not similarity alone. Recency, authority (a policy above a lesson), provenance strength, and status all contribute. Every hit carries a score_breakdown so you can see why it ranked where it did rather than trusting a single opaque number.

This is a filter, not a ranking signal. It runs at read time, on every request, against the calling principal:

CheckEffect
TenantA token for tenant A never sees tenant B’s memory
ScopeOutside the principal’s scopes, memory is not visible
ClearanceAbove the principal’s clearance, memory is not visible
Statusdeprecated is excluded from current results

Nothing here is a soft penalty. A memory that fails admission is absent from the result, not ranked low.

Ranking first and filtering second means the filter is the last word. Rank-with-a-penalty is the design that leaks: a sufficiently strong relevance score eventually outweighs any finite penalty, and the failure is silent and load-dependent — exactly the kind you find in production, not in testing.

Because admission is a filter, “no results” is legitimate and is not an error. It means: nothing this credential is allowed to see matched.

Two consequences for your code:

  • Do not treat empty as failure. Do not retry it, and do not fall back to an ungoverned source.
  • Do not infer existence from absence. “Nothing you may see” and “nothing exists” are indistinguishable by design — a system that let you tell them apart would leak the existence of restricted memory to anyone who could count results.

Admission runs on every read, against the principal making that request. It is not baked in when the memory is written.

This is what makes revocation work. Narrow a principal’s scope and its next read reflects that immediately — there is no index to rebuild and no cached view still serving the old authority.

as_of asks what the corpus knew at a past instant — bi-temporal, so you can reconstruct what an agent would have been told last Tuesday. That is what makes an incident review tractable: you can distinguish “the agent ignored what it knew” from “the agent was never told”.

Admission still applies at the current principal’s authority. Time travel changes what was known, never who may see it.