Skip to main content
Fabric stacks four layers that build on each other. Each is a moat on its own. Together they produce cross-source, time-aware, source-cited answers that no single layer can produce alone.

Layer 1 — The Knowledge Graph

As content syncs from your connectors, an extraction pipeline identifies entities and relationships. Entities become typed nodes. Relationships become typed edges with weights and timestamps.

Edge types extracted today

Why typed edges

A vector store knows "Cole Smith" is near "Project Phoenix" in embedding space. It doesn’t know why. The graph knows Cole attended the Phoenix kickoff, sent_by three emails about the launch, and replied_to the legal review thread on April 7.
Typed edges turn “find similar text” into “reason about who, when, and why.”

Multi-hop traversal

The reasoning loop walks 2–3 hops out from a seed node via recursive CTE:
The graph lives in Postgres. You can SELECT against it, join it to your operational data, and inspect it in any Postgres client.

Layer 2 — Fused Retrieval via Reciprocal Rank Fusion

Every query runs two rankers in parallel over the graph_nodes and observations tables:

BM25 keyword relevance

Postgres full-text search with ts_rank_cd cover-density ranking on tsvector columns. Title weighted A, body weighted B. Parsed via websearch_to_tsquery for safe handling of punctuation.

Vector similarity

pgvector HNSW indexes with cosine distance. Embedding model: OpenAI text-embedding-3-small (1536 dimensions).
Results fuse by rank position via Reciprocal Rank Fusion with k = 60:

Why RRF and not a weighted sum

Cosine similarity is bounded [0, 1] with most matches ~0.3–0.7. ts_rank_cd is unbounded and usually 0.01–0.3. Adding them with fixed weights means vector dominates almost every query — keyword matches on rare terms (names, table identifiers, proper nouns) get crowded out.
RRF sidesteps this entirely. It uses each ranker’s opinion about ordering, not the raw score. Documents that rank well on both lists naturally rise to the top. k = 60 is the standard constant from Cormack, Clarke & Büttcher (2009); it dampens the weight of top ranks slightly so a single ranker’s #1 doesn’t automatically win.
Vespa does it this way. Elasticsearch’s latest hybrid does it this way. We do it this way.

Implementation sketch

Layer 3 — Semantic Memory with Decay

Every user conversation produces observations — typed facts extracted by Claude Haiku from question-answer pairs:

Importance math

1

Initial score: 0.5

Every observation starts at importance 0.5.
2

Strengthened on reference: × 1.1

If the observation is pulled into a later conversation, importance multiplies by 1.1 (capped at 1.0).
3

Decayed when unused: × 0.9

Per conversation it’s not referenced in, importance multiplies by 0.9.
4

Pruned below 0.05

Observations that decay past 0.05 are removed.

Co-occurrence edges

When multiple observations are retrieved together enough times, a weighted edge forms between them. Over time, the memory graph encodes not just what Fabric knows but what knowledge travels together.

Grounded in the knowledge graph

Every observation points back at the source content — the email thread, the meeting transcript, the Slack message where the fact originated. This is the difference between mem0 (floating memories with no provenance) and Fabric (facts with citations).

Layer 4 — Databases as First-Class Citizens

Fabric connects directly to PostgreSQL and MySQL. Not API wrappers — real connections with schema discovery.

Connect

Provide credentials once. Stored encrypted per-tenant with AES-256.

Discover

Fabric introspects the schema: tables, columns, types, primary keys, foreign keys. The schema becomes queryable context for the agent.

Query

Ask a natural-language question. Fabric generates SQL against your actual schema, executes it via asyncpg or aiomysql, and returns results in chat with the query visible for auditing.

Example: cross-source join

Q: Pull the top 10 customers by revenue from public.customers who opened a support ticket in the last 7 days, and show me any Slack #support threads that mention them.
Fabric generates:
Executes against your Postgres. Then searches the graph for #support Slack threads whose content matches any of those customer names. Returns a unified result with both.

Why the layers compound

Graph alone is a CRM with extra steps. Search alone is Elasticsearch. Memory alone is mem0. Database connections alone is Metabase with a chat wrapper. The combination is Fabric.