JournalHow a property knowledge graph makes an AI agent answerable
Journal · under the hood

Most Real Estate Companies Have Data They Cannot Interrogate

10,207 nodes, 28,563 relations, 133 ontology classes measured 2026-07-27: how a ranked source-of-truth hierarchy makes a property AI agent answerable.

Published 2026-10-259 min readSources verified 2026-09-13

Most real estate companies can query their data. Almost none can interrogate it.

They have tables, dashboards and exports. Ask them which developers completed more than half the projects they launched, in districts where sales volume is rising, and someone opens a ticket. The answer is not missing. It is simply not expressible — it lives in a join nobody has written yet.

That is the difference between storing property records and modelling a property domain. A record system knows that row 4,812 has a developer_id. A domain model knows what a developer is, what a district is, that a sub-district is subsumed by a district, and that a project instantiates a class with inherited properties. One answers the questions you anticipated. The other answers the questions you didn't.

This matters more now than it did three years ago, because the interface has changed. When a human read the dashboard, the missing model was an inconvenience. When an AI agent answers on your behalf, the missing model is the difference between a system that is answerable and a system that is merely fluent.

Facts Belong in Postgres. Meaning Belongs in the Graph.

Formal ontologies split knowledge into two layers, and the split is the entire trick.

The A-Box is assertions about individuals: this project, this unit, this developer, this beach. It is dense, it changes daily, and it belongs in a relational store. In the Reflexion property intelligence platform, which runs this architecture in production, that layer is Postgres. Measured 2026-07-27: 6,660 projects, 83,707 units, 1,522 developers, 249 beaches, 100 transit stations, across 6 provinces, 80 districts and 308 sub-districts. A later product reading on 2026-09-10 counted 6,787 projects and 85,399 units against a stable 1,522 developers.

Two series. Two dates. Never one number without the date attached — see our measurement methodology for why we refuse to interpolate between readings.

The T-Box is the terminology: the classes, the subsumption relations, the semantics. It answers what kind of thing is this and what follows from that. It is small, it changes slowly, and it belongs in a graph. Measured 2026-07-27, that graph holds 10,207 nodes and 28,563 relations, of which 133 are ontology classes.

Table 1 — Graph shape, measured 2026-07-27

LayerElementCount
NodesProject6,660
NodesDeveloper1,522
NodesKBDocument1,128
NodesSubDistrict308
NodesBeach249
NodesOntologyClass133
NodesTransitStation100
NodesDistrict80
NodesProvince6
RelationsINSTANCE_OF10,036
RelationsIN7,048
RelationsDEVELOPED_BY3,644
RelationsNEAR_STATION3,174
RelationsNEAR_BEACH2,826
RelationsSUBCLASS_OF106

Read the two ends of that table together. 10,036 INSTANCE_OF edges against 106 SUBCLASS_OF edges. That ratio is what a working ontology looks like: a thin, deliberate hierarchy of meaning carrying a heavy population of instances. A hierarchy that grows as fast as its instances is not an ontology — it is a taxonomy that has lost discipline.

Note also what the geography relations encode. 3,174 NEAR_STATION and 2,826 NEAR_BEACH edges are not distance columns. They are typed, traversable assertions of proximity, which means an agent can reason about access without anyone having pre-computed the specific query. That is the same structural property that makes our scoring model auditable rather than opaque.

Why Does a Vector Index Never Get to Be a Source?

Because a vector is a lossy projection, and a projection that outranks its origin is a system that lies with confidence.

This is the part most teams skip. They stand up Postgres, a graph and a vector index, and then never declare which one wins when they disagree — and they will disagree, constantly, because they refresh on different cadences. Without a declared order, the winner is whichever store the last engineer happened to query. That is not architecture. That is coincidence.

So the hierarchy is formal, ranked, and dated 2026-07-27.

Table 2 — Source-of-truth hierarchy

RankStoreAuthorityForbidden from being
1Postgres (public)A-Box — the factsA derivative. It rebuilds from nothing
2Neo4jT-Box — classes, subsumption, semanticsA cache
3QdrantDerived index — vectorsA source. Everything in it is rebuildable
4TTL filesDocumentationThe source of the T-Box

Arbitration on divergence runs strictly Postgres → Neo4j → Qdrant → TTL. Never the reverse.

Each prohibition is load-bearing.

Rank 1 cannot be a derivative because it is the only layer with no upstream. If you can regenerate it, it wasn't the truth.

Rank 2 cannot be a cache because caches are, by definition, safe to drop and repopulate. The moment the graph is treated as disposable, the semantics become disposable with it — and as the next section shows, in our case a large fraction of them would not come back.

Rank 3 cannot be a source. Vectors are compressed similarity, not assertion. An index can tell you that two documents are close; it cannot tell you that a project has 240 units, and it will happily return a plausible neighbour when the real answer does not exist. The partitioning of that layer is therefore structural rather than filtered: the public corpus and the internal corpus sit in separate collections — 7,438 points and 1,711 points respectively, measured 2026-07-27 — so a mis-scoped query returns nothing rather than returning something it shouldn't. Filters are a runtime promise. Collections are a boundary. The retrieval layer is designed so that every passage it surfaces carries the store and date it came from, which is the subject of the provenance layer.

Rank 4 is the one people find surprising. The Turtle files — the RDF serialisation of the ontology, the thing that looks most like a formal source — are documentation. They are outranked by the running system.

The governing principle is quotable exactly as written:

"A repo file is not the truth; it is at best a projection of the truth. We verify the living system before touching a file."

                  ┌──────────────────────────────────────────────┐
   QUESTION  ───► │  AGENT — ontology-aware query planner        │
                  └───────────────────┬──────────────────────────┘
                                      │ resolve the CLASS before the FACT
                                      ▼
   RANK 1   ┌────────────────────────────────────────────┐
            │ POSTGRES — A-Box. The facts.               │  authoritative
            │ projects · units · developers · geography  │  rebuilt from: nothing
            └───────────────────┬────────────────────────┘
                                │ instances feed the graph
                                ▼
   RANK 2   ┌────────────────────────────────────────────┐
            │ NEO4J — T-Box. Classes. Subsumption.       │  authoritative
            │ INSTANCE_OF · SUBCLASS_OF · geo relations  │  never a cache
            └───────────────────┬────────────────────────┘
                                │ semantics scope the search
                                ▼
   RANK 3   ┌────────────────────────────────────────────┐
            │ QDRANT — derived index. Vectors.           │  disposable
            │ isolation by COLLECTION, not by filter     │  fully rebuildable
            └───────────────────┬────────────────────────┘
                                │
                                ▼
   RANK 4   ┌────────────────────────────────────────────┐
            │ TTL FILES — documentation only.            │  non-authoritative
            └────────────────────────────────────────────┘

   ARBITRATION ON DIVERGENCE:  Postgres → Neo4j → Qdrant → TTL.  Never the reverse.
   ANSWER ◄── fact (rank 1) + class (rank 2) + passages (rank 3), each stamped with store + date.

A Contract, Not a Diagram

Architecture diagrams are opinions. This one is enforceable.

The hierarchy is a dated, versioned document, and it is referenced from every agent configuration file in the stack. That single detail is what converts a preference into governance. An agent cannot plausibly claim it didn't know the arbitration order, because the order is loaded alongside its instructions. There is no legitimate path around it.

This is also what makes the system auditable by a client rather than merely explainable by us. An auditor does not ask what your architecture is. An auditor asks: where is it written, when was it written, who is bound by it, and what happens when it is violated. A diagram answers none of those. A dated contract answers all four.

What Happens If We Rebuild the Ontology From Scratch?

We lose 58 classes. Here is exactly why, because this is the most useful thing in this article.

Of the 133 ontology classes, only 75 are reproducible.

Table 3 — Provenance of the 133 ontology classes

OriginClassesReproducible
Knowledge-base document types, regenerated on every sync63Yes, automatically
Hardcoded constants in the ingestion script12Yes, but impoverished
One-off load from degraded TTL files58No

The 58 break down by module: property 15, agent 14, financial 8, temporal 6, governance 5, knowledge-graph 4, core 3, geo 3. They were loaded once, from Turtle files that no longer parse cleanly, and nothing in the current pipeline recreates them.

The operational consequence is precise, and it is bounded.

The ingestion script is idempotent under MERGE. Replaying it is safe: it will not duplicate classes, will not corrupt existing ones, and can be run as often as you like. Routine operation carries no risk.

The risk is a single class of operation — anything that empties the class table. A cold rebuild, a "let's clear it and re-import", a migration that drops and recreates. Any of those regresses the T-Box from 133 classes to 75, and the loss is silent: the graph still works, queries still return, and the semantics for property, agent and financial reasoning have simply thinned out underneath. So that operation is not permitted. Not discouraged — forbidden, in writing, in the contract.

And the TTL files? 8 of 23 fail to parse. Which is exactly why they sit at rank 4. If the Turtle files were the source of the T-Box, a third of the ontology would be unloadable on any given day. Demoting them to documentation is not a compromise; it is the correct reading of what they actually are.

We publish this because the alternative is worse. An undocumented fragility is an outage waiting for a new engineer. A documented one is a guardrail. Mature data governance is not the absence of failure modes — it is failure modes that are named, measured, bounded and guarded. Anyone claiming a production knowledge graph with no irreproducible state has either a very young system or a very incurious one.

Five Checks to Run on Your Own Stack This Week

Concrete, and none of them require a vendor.

1. Ask one question that needs a class, not a column. "Which developers have a completion rate above the median in districts where inventory is rising?" If the answer requires new engineering, you have records, not a model.

2. Count the rows in your geography tables. We keep two documented traps in ours: a geo_provinces table with 3 rows and a districts table with 0, neither of which is the source of our 6 provinces and 80 districts. Empty placeholder tables that look authoritative are how agents learn to be confidently wrong.

3. Write down your arbitration order, ranked, with prohibitions. One line per store: what it is authoritative for, and what it is forbidden from being. If two stores tie for rank 1, you don't have a hierarchy — you have a race condition.

4. Attempt a cold rebuild of your semantic layer in a scratch environment and count what survives. Ours goes from 133 to 75. Knowing your number is the whole exercise. Not knowing it is the actual risk.

5. Grep your agent configs for a reference to the contract. If the arbitration order is not loaded into the agents that depend on it, it isn't governance — it's a wiki page, and agents route around wiki pages.

An agent that can cite which store an answer came from, at which rank, measured on which date, is answerable. One that cannot is fluent. Operators are increasingly discovering that those are not the same product — and that only one of them survives a client asking "how do you know?"

The district-level output this architecture produces is published in market intelligence.