All posts
Research13 Oct 202640 min readVersion 1.0 draft

The Company Second Brain

How Doram builds, tests and serves a semantic context graph that every AI system in a company can read from and trust.

Written for data, platform and security teams

Key findings

91.2%Spider 1.0, academic databases
73.0%BIRD, public databases
21.3%Spider 2.0, real enterprise databases
10.8%BEAVER, real company warehouses

Execution accuracy of leading AI models. It falls as the questions move from public data to real company data.

Section 1

Abstract

AI models can now write valid SQL. They still give confidently wrong answers to most real business questions.

On Spider 1.0, an academic benchmark, a leading code agent solves 91.2% of tasks. On Spider 2.0, built from real enterprise databases, the same agent solves 21.3%.[1] On BEAVER, built from real company data warehouses and query logs, the best agent setup tested reaches 10.8%.[2] The model is the same in each case. What changed is that the questions became real, and real questions depend on knowledge the database does not hold: what a term means at this company, which of several tables is the right one, how each number is counted, and what happened that changed the data.

Doram gives AI systems that knowledge through a company second brain: a semantic context graph that holds what the company knows about its data. It has three layers. The ontology layer says what things are. The context layer says how they connect and why. The semantic layer says how each number is counted. Every AI system the company runs, starting with Doram's own AI analyst, reads from this one graph, so every answer uses the same approved definitions.

The brain is not written by hand, and nobody has to keep it up to date by hand. It is built from the systems the company already runs: database schemas and query history, dbt models and BI dashboards, documents in tools such as Confluence and Notion, and events from tools such as Jira and Slack. Owners add the business context that no system holds. The work is split by what each part does best. Code settles everything the data can answer on its own. An LLM drafts only what code cannot, such as names and candidate definitions. People approve what neither can settle, such as a choice between two valid definitions.

After the first day, the brain is self-maintaining. Agents watch every source for changes, learn from how people use the analyst, and update the brain on their own. Small, safe updates go live automatically. Anything that would change an approved number waits for its owner.

At question time, one retriever walks the graph within fixed limits and applies access rules at every step. A semantic compiler turns the approved definitions into a single SQL query that runs in the customer's own warehouse. When the brain cannot decide between two meanings, or lacks a fact, it refuses and says what is missing instead of guessing.

What Doram guarantees

  1. Evidence & ownershipEach node and edge links to the query, model, document, tool record or person it came from, and carries a trust level: discovered, validated, approved or certified.
  2. Validation before releaseA metric definition is approved only after it compiles, runs on real data and matches a known result, such as an existing dashboard, within 0.5%.
  3. Reproducible answersThe same graph version and the same user scope always return the same facts, so any answer can be replayed and traced to the definitions behind it.
  4. Access control at every stepRole, row and column rules are enforced during the graph walk and in the compiled SQL, never filtered out afterwards.
  5. Data stays in placeNo rows of company data are copied into the graph. Doram runs as SaaS or inside the customer's own cloud.

We evaluate Doram on Spider 2.0, BIRD[3] and BEAVER, and on an enterprise test set with messy schemas, conflicting definitions and restricted data. We compare it with three common approaches: an LLM given only the schema, an LLM with document search, and an LLM with a hand-built semantic layer. On the enterprise set, Doram reaches x23% execution accuracy, against x20% to x22% for these approaches. It is confidently wrong on x31% of questions, returns the same answer on x27% of repeated and reworded questions, and returned restricted data in 0 of x47 access tests.

This paper describes the architecture in full: the data model, how the graph is built and kept current, how it is read and compiled, how it is secured and deployed, and how it performs.

Draft noteFigures marked x are placeholders. They match the tables in Section 12 and will be filled in when the benchmark runs are complete.

Section 2

The Problem: Why AI Gets Company Questions Wrong

Most teams that try an AI analyst see the same thing. The SQL runs, the chart looks right, and the answer is confidently wrong.

This section shows where that gap comes from, what research says about its size, and why the usual fixes do not close it.

The gap between data and meaning

Take a question from a Monday leadership meeting:

“Why did revenue drop last quarter?”

Give an LLM the warehouse and it returns a confident answer in seconds: revenue fell 14%, mainly because of fewer new deals. The SQL is valid and the numbers are real, but the answer is wrong. The real drop was 9%, because Finance does not count one-time setup fees as recurring revenue. Upgrades were filed as new business instead of expansion. And the cause was paused customers, not new deals.

None of these is a SQL error. Each comes from something the company knows and the database does not say:

What an analyst knows Where the evidence lives
Setup fees are not recurring revenue. A Finance decision from March 2024, in meeting notes.
An upgrade is expansion, not new business. Every revenue dashboard.
Status P means paused, not cancelled. Paused accounts have open contracts but no invoices.
accounts_v2 is the real customer table. Query history: joined about 400 times, the old table almost never.

Table 1What an experienced analyst knows, and where each fact leaves a trace.

Every one of these facts has a trace somewhere in the company. None of them is in the schema. This is the gap between data and meaning, and it is why an AI can sound certain and still be wrong.

What research shows

When the databases and questions come from real companies, accuracy falls sharply.

Spider 1.0Academic databases
91.2%
o1-preview code agent. Source: Spider 2.0 paper [1]
BIRDPublic databases
73.0%
Same o1-preview code agent. Source: Spider 2.0 paper [1]
Spider 2.0Real enterprise databases
21.3%
Same o1-preview code agent, 632 enterprise tasks [1]
BEAVERReal company warehouses
10.8%
Best agent frameworks using GPT-5.2 [2]

Figure 1Execution accuracy of leading AI agents. Spider 1.0, BIRD and Spider 2.0 use the same o1-preview code agent[1]. BEAVER uses the best agent frameworks tested, running GPT-5.2[2].

The same agent that solves 91.2% of Spider 1.0 solves only 21.3% of Spider 2.0, whose databases often have more than 1,000 columns.[1] On BEAVER, built from real company query logs, the best GPT-5.2 agents reach 10.8%, and only 30.1% even with expert hints.[2]

Context is what moves the number. On an insurance company's database, GPT-4 answered 16% of business questions correctly from the SQL tables alone, and 54% when given a knowledge graph of the business.[4]

Why the usual fixes fall short

Teams usually try one of four fixes. Each helps, but none closes the gap.

Fix Why it falls short
More data The meaning of the data is not in the data. More tables only mean more wrong choices.
A bigger model No model can know a decision Finance made in a meeting. BEAVER's 10.8% comes from GPT-5.2.
Document search It finds pages, but cannot tell which definition is approved or turn it into SQL that gives the same answer every time.
A hand-written semantic layer There is too much to write, and it goes stale. It holds metrics, but not events or decisions.

Table 2The four common fixes, and why each one leaves the gap open.

What is missing is a layer that holds the company's meaning: built from the evidence the company already has, validated against real data, and approved by its own people. Section 3 describes that layer.

Section 3

The Company Second Brain

The company second brain is a versioned, evidence-backed semantic context graph, built from the company's own systems and read by every AI system through one interface.

DISCOVERED, VALIDATED ONE READ PATH Databases schema, queries, dbt, BI Business context entered by owners Company knowledge Confluence, Notion, Drive Third-party tools Jira, Slack, CRM, billing Company second brain semantic context graph Ontology layer what things are Context layer how things connect, and why Semantic layer how things are counted AI analyst business users ask here Semantic compiler definitions to SQL API other AI tools, by role Data and business owners APPROVE

Figure 2Four sources, one graph, one read path.

For each workspace, Doram keeps one graph, versioned on every change, and every consumer reads it through one function:

Gk = (V, E)        the graph at version k
layer(x)  ∈ {ontology, context, semantic}      x: any node or edge
trust(x)  ∈ {discovered, validated, approved, certified}
trust(x) ≥ validated ⇒ evidence(x) ≠ ∅
trust(x) ≥ approved  ⇒ owner(x) defined
R(Gk, u, q) → context pack   the only read path, for user u and question q

No consumer reads a source system directly.

The three layers

Each layer depends on the one before it.

Ontology layer: what things are. It holds the company's model of its business: entities, their columns, and the words people use for them.

entity   = ⟨ name, tables, key, grain, synonyms ⟩
column   = ⟨ table, type, role, profile ⟩
role     ∈ { identifier, measure, dimension, time, foreign key, personal }
profile  = ⟨ distinct values, null rate, range, masked samples ⟩
           masked samples: a few example values, personal values masked
term     = ⟨ word, synonyms, target node, persona ⟩
cardinality(A → B) ∈ { 1:1, N:1 }        from keys and observed joins
                                          N:M only through a bridge entity

An entity can span several tables and sources. A column's role decides how the compiler may use it: measures are aggregated, dimensions split, personal columns are masked. The ontology answers "what is this, and where does it live?"

Context layer: how things connect, and why. It holds every edge between nodes, and the knowledge around the data that no schema records.

edge     = ⟨ from, to, type, weight, valid from, valid to, trust, evidence ⟩
rule     = ⟨ predicate, applies to, persona ⟩
policy   = ⟨ kind ∈ { RBAC, ABAC, column }, predicate or mask, subjects ⟩
event    = ⟨ name, time window, affects, source record ⟩
fact     = ⟨ statement, decided by, date, applies to ⟩

Join edges carry their keys and a weight from how often they are used. Because every edge has a validity window, the graph can be read as of any past date. The context layer answers "which join, which filter, who may see it, what happened, and what was decided?"

Semantic layer: how things are counted. It holds one approved definition for each metric, as a fixed tuple:

metric = ⟨ entity, measure, aggregation, grain, rules, dimensions, additivity ⟩
additivity ∈ { additive, semi-additive, non-additive }
additive: sums across any dimension (revenue)
semi-additive: sums across all but time (account balance)
non-additive: must be recomputed (ratios, distinct counts)

Dimensions point to columns or terms and set how a metric may be split. Because the definition is fixed, the same metric, split and filters always compile to the same SQL. The semantic layer answers "how exactly is this number computed?"

The four sources

All four are read with read-only access:

  • Databases: schema, column profiles, query history, and definitions already in dbt and BI tools. They yield entities, columns, joins, metrics and rules.
  • Business context: entered by owners in Doram's studio, because no system holds it. It yields terms, facts, goals and calendar rules.
  • Company knowledge: document sections that mention something the graph already knows, from spaces an admin chose. It yields rules, terms, facts and goals.
  • Third-party tools: events and reference lists from tools such as Jira, Slack, the CRM and billing. Single records are read live and never stored. They yield events, terms and rules.

The build pipeline

Every fact enters the graph through three gated stages:

  1. Discover. Code extracts candidates from the sources, and the LLM drafts each fact from evidence only. A draft without evidence goes no further.
  2. Validate. Code checks each draft. Data-backed facts, such as metrics and joins, are run on real data, and a metric must replay within 0.5% of a known result. Knowledge facts, such as decisions and policies, are checked for evidence, references and conflicts.
  3. Approve. Low-risk changes go live automatically. Medium-risk changes go live, and 1 in 10 is spot-checked. High-risk changes wait for the owner. Certification is always a person's decision.

The LLM never writes SQL and never sets a trust level.

Consumers

Three consumers read the graph through R. The AI analyst calls it as a tool, engineers' own agents call it through the API, and the semantic compiler compiles the context pack that R returns. Consumers can propose changes, but a proposal becomes a fact only through the build pipeline. Data owners approve definitions, business owners enter business context, engineers integrate, and business users only ask questions.

Section 4

Trust by Design

An answer can be trusted only if it can be checked, today and later. These properties make every Doram answer checkable.

Evidence on every fact

Every node and edge links to the sources it came from:

evidence(x) = { (kind, reference, excerpt, captured_at) }
kind ∈ { query, model, dashboard, document, tool record, person }
readers(x) = ∩ readers(e)  for e ∈ evidence(x)     until the owner widens it

Doram keeps a reference and a short excerpt, never the whole source. A fact with no evidence stays a draft. When a source changes, the facts built on it are checked again. When a fact's only source is deleted, the fact returns to discovered. A fact taken from a restricted document can be read only by people who can read that document.

Trust levels

  • Discovered: found by the crawler agent, with evidence, not yet checked.
  • Validated: a data-backed fact that ran on real data and matched a known result.
  • Approved: accepted by its owner, or approved automatically because the change is low risk.
  • Certified: signed off by its owner as the company's official definition, with the reviewer, time and test score recorded.

A fact moves between levels only along these transitions, and every move writes a new version:

discovered → validated     data-backed fact passes all tests
discovered → approved      knowledge fact accepted by its owner
validated  → approved      low or medium risk, or owner accepts
approved   → certified     owner signs off
any        → discovered    its only evidence is deleted
default read set:  trust(x) ∈ { approved, certified }

Drafts are returned only when a user asks for them, and are marked. The semantic compiler never reads a draft, so a draft can never reach a SQL query.

Continuous verification

Trust is re-earned every day. Every approved and certified metric is replayed daily and after any source change:

|m_today − m_ref| / |m_ref| ≤ ε   ⇒  stays live            ε = 0.005
otherwise                        ⇒  new draft; users keep the
                                    last approved version
last approved fails to compile   ⇒  refuse for that metric

Same question, same answer

change(x)    → version + 1, with (author, time, reason, test result)
rollback     = a new version that copies an older one
same (k, u, q)  ⇒  same facts and same SQL
                   ranking model frozen with k; LLM slots stored in the record
read record  = (k, u, q, slots, a*, f),   f = hash(sort(facts returned))
               a*: the chosen resolution (Section 7)
replay(r)    passes ⇔ fingerprint of R(G_k, u, q) = f

Any past answer can be replayed on the version that produced it and traced to its definition. No separate audit system is needed.

Refusal instead of guessing

Doram refuses when:

  • a term still has more than one valid definition after the persona order;
  • a question needs a fact that has no approved definition;
  • an approved metric no longer compiles after a source changed;
  • an answer would need data the user may not see.

A refusal names the missing fact and shows the evidence on each side, so the owner can settle it once.

When things go wrong

  • An owner approves a wrong definition: any change that moves an approved number is high risk, and the reviewer sees its test results and everything that depends on it.
  • A document contains injected instructions: the LLM only drafts. It cannot approve, write SQL or change a policy.
  • The LLM misreads a question: slot checks and clarifying questions catch it before any SQL runs.
  • A source changes: drift detection creates a new draft, and users keep the last approved version.

Section 12 measures trust directly: the confidently wrong rate, and the daily replay match rate of certified metrics.

Section 5

System Architecture

Architecture thesis

Company meaning must be discovered, validated and approved before a question is asked. At question time, the system only looks it up.

Most AI analysts decide what "revenue" means while they answer, from the schema and whatever text they retrieve. Doram moves that decision out of the answer. The write path establishes meaning with evidence, tests and owners. The read path can use only what the write path has approved. The rest of the architecture follows from this:

  1. Two paths, one meeting point. The write path builds the graph and the read path reads it. Nothing on the read path can write to the graph, and nothing on the write path can answer a question.
  2. Code decides, the LLM proposes. The LLM drafts from evidence and reads questions. Code tests, resolves and writes SQL. People approve what code cannot settle.
  3. Proof before use. A data-backed fact reaches a SQL query only after it reproduces a known number.
  4. One store, one read path. Every fact lives in one transactional graph, and every consumer reads it through R, under the same rules.
  5. Pinned reads. Every read uses one graph version, so the same question gets the same answer and can be replayed.
  6. No guessing at runtime. If meaning is missing or ambiguous at question time, Doram refuses. It never fills the gap by inference.
  7. Meaning, not data. The graph stores definitions, relationships, profiles and evidence. It holds no rows of company data, only masked samples inside column profiles. The data stays in the company's warehouse.

Architecture at a glance

WRITE PATH READ PATH Company systems Warehouse, DBs dbt and BI tools Documents Jira, Slack, CRM read-only access Connectors Crawler agent drafts from evidence Validation code runs the tests Approval by risk, or by owner Monitoring and feedback agents watch sources, usage UPDATES Semantic context graph one Postgres store: nodes, edges, evidence, versions APPROVED Semantic compiler definitions to SQL, access filters added Retriever scope, walk, resolve or refuse AI analyst plans and explains API engineers' AI tools APPROVED FACTS SQL RUNS HERE uses an LLM

Figure 3Write path (top) and read path (bottom). Shaded boxes use an LLM.

Separation of concerns

The system is split into two paths and seven layers.

Write path: creates meaning. Discover → Validate → Approve, as described in Section 3.

Read path: uses meaning.

  • Understand: the LLM turns the question into slots.
  • Resolve: the retriever maps the slots to approved facts and builds the context pack.
  • Compile: the compiler checks joins, grain and filters, adds policies and writes SQL.
  • Execute: the warehouse runs the SQL under a cost guard, and the analyst explains the rows.

Meaning is created only on the write path and used only on the read path. Up to Resolve, the read path works only with business names. Physical tables and columns appear only from Compile onward.

Components

Each component has one job. Only two use an LLM.

  • Connectors read the sources, with read-only access, and build evidence bundles.
  • The crawler agent turns an evidence bundle into a draft, using an LLM.
  • Validation tests each draft. It is code.
  • Approval turns a tested draft into a new graph version, by risk rules or by the owner.
  • The monitoring agent turns source changes into new drafts.
  • The feedback agent turns usage signals into new drafts.
  • The retriever turns slots into a context pack. It is code.
  • The semantic compiler turns a context pack into SQL. It is code.
  • The AI analyst reads the question and explains the answer, using an LLM.

The retriever, compiler and analyst are stateless and scale horizontally. All state lives in two places: the graph in Postgres, and the company's data in its own warehouse. Each fact is written in one transaction, and after the first run, connectors read only what changed. Section 6 details the write path. Sections 7 and 8 detail the retriever and the compiler.

Section 6

Building and Maintaining the Graph

The write path in depth: discovery, validation, storage and maintenance.

Discovery

Query history is the primary signal. Each query is parsed, normalized and fingerprinted. Candidates are extracted per shape and weighted by frequency, user spread and recency:

shape(q) = hash(canon(AST(q)))       literals stripped, identifiers canonicalized
C(s)     = joins ∪ predicates ∪ group keys ∪ aggregates of shape s
w(c)     = log(1 + n_c) · log(1 + u_c) · e^(−λ·Δt_c)
           n: runs, u: distinct users, Δt: age; λ = ln 2 / 90 days
keep c   ⇔  n_c ≥ 3  ∧  c not only in system or failed queries

Equivalent candidates are clustered. For each cluster, the LLM receives one evidence bundle (column profiles, masked samples, query shapes and declared dbt or BI definitions, each with an evidence ID) and emits a typed draft. Declared definitions enter as high-weight priors. Documents are segmented by heading and entity-linked against existing nodes, and only linked segments are drafted from. Tools contribute events and reference lists. Individual records are resolved live and never persisted. Business context is entered by owners and recorded with the owner as evidence.

The same entity in several sources is linked by key containment:

overlap(A.k, B.k) = |V(A.k) ∩ V(B.k)| / min(|V(A.k)|, |V(B.k)|)
propose same_as(A, B)  ⇔  overlap ≥ 0.9          V: distinct key values

Validation

Data-backed facts are executed against the warehouse. A metric passes five sequential gates: static type and grain check, compilation, dry-run cost bound, sample execution against column profiles, and replay.

replay  ⇔  |m − m_ref| / |m_ref| ≤ ε                         ε = 0.005
join    ⇔  uniq(k₁) = 1  ∧  match(k) ≥ 0.95  ∧  |A ⋈ B| / |A| ≤ 1
           uniq: distinct keys / rows on the one side
rule    ⇔  compiles  ∧  |Δrows − Δrows_hist| / Δrows_hist ≤ 0.05

Knowledge facts are checked for provenance, referential integrity and in-scope contradiction, then routed to their owner. Approval follows the risk classes in Section 3.

Storage

The graph is persisted in Postgres as four relations. Nodes carry type, layer, fields, trust, version and owner. Edges carry type, source, target, weight, validity window, trust and version. Evidence rows carry kind, reference, excerpt and capture time. Version rows carry the diff, author, timestamp and reason. A node, its edges, its evidence and its version row commit in one ACID transaction.

Node and edge types form a closed set that the crawler agent cannot extend. Traversal is a bounded recursive query (depth ≤ 3, edge types restricted per request, at most 2,000 visited nodes) over indexes on (workspace, type), (src, type) and (dst, type), so read cost is independent of graph size. The design point is 10⁶ nodes and 5 × 10⁶ edges per workspace. Beyond it, relations are partitioned by workspace and reads are served from replicas.

Maintenance

Four detectors run continuously. A schema change is flagged when the schema fingerprint differs from the last run. A data change is flagged when a column's population stability index (PSI) against its last profile exceeds 0.2, or a new categorical value appears. A usage change is flagged when a join path's share of queries moves by more than 20 points. A provenance change is flagged when the source behind a fact's evidence is edited or deleted.

Each detection triggers impact analysis over the reversed dependency graph:

for y ∈ reach(x, depends_on⁻¹):
    ¬compiles(y)           →  break     →  redraft
    replay(y) drifts > ε   →  semantic  →  redraft
    otherwise              →  refresh evidence

Until a redraft is approved, consumers fall back as described in Section 4. Usage feedback is aggregated per node and acts only at 3 or more distinct users, or one owner. No agent can approve its own output, mutate an approved version, arbitrate between conflicting definitions, modify a policy or persona, or emit SQL.

Section 7

Context Retrieval

The retriever implements R(Gk, u, q) → context pack. It is a controlled agentic retriever. The AI analyst's LLM plans the request once. The retriever itself is code, and performs every search, ranking, resolution and check, deterministically on version k.

Slot extraction

The AI analyst's LLM maps the question to a typed request. It fills slots with the user's words and never names a node:

slots(q) = ⟨ metrics, dimensions, filters, time, task ⟩
task     ∈ { lookup, compare, trend, explain }

Filters keep their literal values, such as "EMEA". Code, not the LLM, resolves time phrases against the fiscal calendar. A follow-up inherits the previous turn's slots. The slot output is stored in the read record, so a replay never calls the LLM again.

Scope

Scope is computed before any search, so a node the user may not see is never a candidate, whether by name, synonym or path:

G_u = { x ∈ G_k : allowed(u, x) ∧ trust(x) ∈ T_u }
T_u = { approved, certified }                  drafts only on explicit request

Candidate generation

Each slot is searched inside G_u, in four indexes held in the same Postgres database as the graph. A BM25 index covers names, synonyms, descriptions and example questions. A pgvector index covers the same text, for loose wording. A value index covers the distinct values of small, non-personal columns and reference lists, with trigram matching for typos. A question memory holds approved question-to-resolution pairs, matched on the masked question and on the plan skeleton[6].

Search runs from metrics and from columns, and the two results are merged[8]. Values in large or personal columns are never indexed. They are resolved by a live, policy-filtered lookup[7].

The ranked lists are fused with reciprocal rank fusion[5]:

RRF(c) = Σ_i 1 / (k_rrf + rank_i(c))            k_rrf = 60; top K = 20 per slot

Ranking

Candidates are re-ranked by a linear scorer over fixed features:

s(c) = wᵀ · φ(c)
φ(c) = [ RRF(c), match type, usage weight, trust, persona fit, confirmations ]

The weights are learned offline with learning-to-rank on labelled resolutions, then frozen and versioned with the graph. Ties are broken by node identifier. The same question on version k always ranks the same way.

Joint resolution

Slots are resolved together, not one by one. The retriever selects the highest-scoring assignment that satisfies every structural constraint, using beam search over the top candidates of each slot:

a* = argmax  Σ s(a_i)    over a ∈ top_K(slot_1) × … × top_K(slot_n)
     subject to
       metrics and dimensions joinable on approved edges, depth ≤ 3
       grain(dimension) ≥ grain(metric)
       every filter column reachable from the metric's entity
       additivity(metric) compatible with the requested aggregation
                                                    beam width B = 10

If a question in memory matches with similarity at least 0.9 and its resolution satisfies the constraints, that resolution is reused. Where a term has several definitions in scope, a fixed precedence decides:

def(t, u) = first non-empty of
            D_user(t, u), D_team(t, u), D_source(t, u), D_company(t)

Decision rule

margin = S(a*) − S(a₂)                          normalized scores; δ = 0.1
margin ≥ δ                  ⇒  proceed
margin < δ                  ⇒  ask the user to choose among the top options
no feasible assignment      ⇒  LLM restates the slots once, then retry
still none, or |def| > 1    ⇒  refuse, naming the unresolved slot

Context pack

The pack contains the chosen definitions, the join path, the rules and policies that apply, and the events and decisions linked to the metric whose time window overlaps the question's. Every item carries its evidence, and the pack is held within a fixed size budget. Consumers see business names only. Physical tables and columns are passed only to the compiler, and a column hidden by policy is passed to no one.

Learning across versions

Clarifications and corrections become candidate synonyms, value aliases and question-memory entries, and enter the graph through the feedback agent and the build pipeline. Ranking weights are retrained offline and shipped only as a new graph version. Retrieval improves from one version to the next, while each version stays deterministic.

Together these components cover exact names, synonyms and typos, loose wording, literal filter values, relative and fiscal time, team-specific meanings, ambiguous questions, incompatible slots, comparisons and ratios, "why" questions, follow-ups and repeated questions. Section 12 measures the retriever on its own.

Section 8

Semantic Compilation and Execution

The semantic compiler implements C(pack, k) → SQL. It is code, not an LLM, and a pure function: the same pack on version k always yields the same SQL, byte for byte.

Semantic compiler code, no LLM · same pack, same SQL Context pack from the retriever Lower pack → Q typed query Plan Q → P per-fact γ Rewrite P → P_u policies Emit P_u → SQL dialect AST Verify re-parse, invariants Cost guard dry-run estimate Warehouse read-only ROWS AI analyst this user only Refuse, and name the reason type, grain or hidden column Stop, log as a defect nothing runs Ask for a narrower question estimate over budget

Figure 4Six passes turn a context pack into SQL. Every failure stops before the warehouse.

Semantic query

The pack is lowered into a typed intermediate form. Each metric carries its expression, aggregation class and grain:

Q      = ⟨ M, D, F, T ⟩
m ∈ M  = ⟨ expr, class, entity, grain, time column ⟩
class  ∈ { additive, semi-additive, distinct, ratio }
         additivity of Section 3; non-additive splits into distinct and ratio
d ∈ D  = ⟨ column, entity, key ⟩
T      = [t₀, t₁)                          closed-open, on the fiscal calendar

The compiler does not trust the pack. It re-checks every node and edge against version k and re-applies the constraints of Section 7. Any failure stops compilation.

Aggregation planning

Every approved join is N:1 in one direction (Sections 3 and 6), so the direction of traversal gives each edge's cardinality. The planner uses it to decide where rows could repeat:

dimension path   N:1 or 1:1 edges only, by grain(d) ≥ grain(m)
filter over 1:N  semi-join R ⋉ σ_F(S), as EXISTS, never an inner join
several facts    aggregate each, then join on D

Metrics are grouped by fact entity. Each group is aggregated at the grain of D, and the groups are joined on the dimension keys:

Sᵢ = γ_{D ; aggᵢ} ( σ_{F ∧ T} ( Rᵢ ⋈ path(D) ) )
P  = S₁ ⟗ S₂ ⟗ … ⟗ Sₙ   on the keys of D
     ⟗: full outer join

A row is counted once per metric, whatever the join shape, so fan-out and chasm traps cannot occur. Each class compiles differently:

additive        Σ at grain D
ratio a / b     Σa / NULLIF(Σb, 0), after aggregation, never averaged
distinct        recomputed from base rows at grain D, never summed
semi-additive   last value over time, Σ over other dimensions
compare         P(T) ⋈_D P(T − Δ)
trend           P by time grain, joined to a date spine

Policy rewrite

Policies rewrite the plan. They do not filter the result. Every base relation is replaced by its filtered form before any join or aggregation:

R  →  σ_{p(u, R)} (R)            every base relation in P
c  →  mask(c)                    every masked column in the output
hidden(c) ∧ c ∈ D ∪ F  ⇒  refuse

The predicate p(u, R) comes from ABAC (Section 9). It sits below every aggregate, so no total can include a row the user may not see.

SQL generation

The rewritten plan P_u is canonicalized, emitted as a syntax tree in the warehouse's dialect, and serialized:

SQL   = serialize( emit_dialect( canon(P_u) ) )
canon : sorted predicates, deterministic aliases, fixed CTE order

Date functions, quoting and the fiscal calendar are handled per dialect, and T is pushed down as the partition filter on partitioned tables. Filter values from the question are bound as parameters, never written into the SQL text, so a question cannot inject SQL. Every syntax-tree node keeps the ID of the graph node it came from, and this lineage is shown with the answer.

Verification

The emitted SQL is parsed again and checked, independently of the passes that produced it:

verify(SQL)  ⇔  one read-only SELECT
             ∧  every table and column ∈ pack
             ∧  every base scan carries p(u, R)
             ∧  every partitioned scan carries a partition filter
             ∧  every value from the question is a bound parameter

A failure here is a compiler defect, not a user error. Nothing runs, and the case is logged.

Cost guard and execution

Before running, the compiler requests the warehouse's own estimate by dry run or EXPLAIN:

run  ⇔  bytes(SQL) ≤ B_max  ∧  rows(SQL) ≤ N_max        limits set per workspace

Otherwise, the analyst asks for a narrower question, such as a shorter time range. The query runs in the customer's warehouse through a read-only account with a statement timeout. Rows go to the analyst for this user only, and are never written to the graph.

Section 9

Security and Governance

One invariant governs access: no user learns through Doram what they could not see in the source.

Access control

Three policy kinds, each enforced at one point on the read path:

RBAC     facts    allowed(u, x), applied by the retriever before search
ABAC     rows     p(u, R), added by the compiler below every aggregate
column   values   mask(c) or hide(c), applied by the compiler
policy(u, x) = warehouse grants ∩ admin rules      the stricter wins

Warehouse grants are imported at every schema read, so a revoke in the source reaches Doram at the next read. Only admins write policy nodes, and no agent can create or change one. Every connector uses a read-only account. Credentials are encrypted, kept outside the graph, and never sent to the LLM.

What the LLM sees

While building the graph, the LLM sees names, profiles, value-free query shapes, masked samples and document excerpts. While answering, it sees the question, business names and the asking user's own results. It never sees credentials, hidden or personal values, raw rows at build time, or another user's results. The customer chooses the LLM, and its data never trains a model.

Data boundary

In SaaS, only the graph is stored outside the customer, and an agent inside the customer's network connects out to Doram. On-premise, nothing is stored outside, and only calls to the chosen LLM leave the network. No inbound port is opened in either model. Rows are never stored, and are sent only to the user who asked. The graph holds only masked samples inside column profiles.

Audit and retention

The audit trail is the version log and the read records of Section 4, so an auditor can see who changed a definition, why, and who saw which number. Read records hold facts and fingerprints, not rows. Both are kept for two years. Erasing a person removes their values from evidence, samples and stored slots in every version.

Section 10

One Question, End to End

This is what happens, step by step, when someone asks Doram the question from Section 2.

“Why did revenue drop last quarter?”

What Doram does

  1. Reads the question. The AI analyst works out what is being asked: a number (revenue), a time (last quarter) and a task (explain why it changed). This is the only step where the LLM reads the question.
  2. Checks who is asking. The user works in Finance, so Doram looks only at facts Finance is allowed to see, and only at approved ones.
  3. Picks the right meaning. "Revenue" means different things to different teams. Finance means net revenue. Sales means gross revenue, which includes setup fees. A Finance user is asking, so Doram uses Finance's meaning. "Last quarter" becomes 1 April to 30 June 2026, compared with 1 January to 31 March.
  4. Gathers what an expert would know. Trial and internal accounts do not count. Setup fees are not recurring revenue, a Finance decision from March 2024. Status "P" means paused, not cancelled. The last big drop was caused by a billing outage.
  5. Writes the query. The compiler turns all of this into one SQL query, adds Finance's access rules, checks that the query is safe, and checks that it will not cost too much.
  6. Runs it. The query runs in the company's own warehouse, with read-only access. The results go only to the person who asked.

What the numbers show

Revenue                  4,000,000 → 3,640,000    down 360,000 (9%)
Paused customers          −445,000
Customers who left        −110,000
Customers who downgraded   −40,000
Customers who upgraded     +95,000
New customers             +140,000

The answer

Revenue fell 9%, not 14%. The 14% included one-time setup fees, which Finance does not count as recurring revenue.

There was no billing outage this quarter, so this is not a repeat of the last drop. The real cause is paused customers. They took away 445,000, more than the whole drop, and without them revenue would have grown about 2%. Upgrades are counted as upgrades, not as new customers.

Where the numbers could not explain something, the analyst checked the CRM. Most paused customers are schools and colleges that pause every summer. Fourteen have no restart date, so the analyst lists them for the account team instead of guessing.

Why it can be trusted

The answer comes with the definitions it used, the SQL it ran and the source behind each fact. Doram also keeps a record of the question, the user, the graph version (1482) and the facts it used. Anyone can replay that record later and get the same facts and the same SQL.

Section 11

Deployment, Scale and Cost

Doram runs as SaaS or on-premise from the same build. In both, computation on company data runs in the customer's warehouse, and Doram's own load on it is bounded by a budget.

Deployment

The system has two planes. The control plane holds the graph store, the indexes, the agents, the retriever, the compiler and the analyst. The data plane is the customer's warehouse and sources, reached only through connectors.

In SaaS, the control plane runs in Doram's cloud, and the connectors run in an agent inside the customer's network. On-premise, both planes run in the customer's cloud account. Doram operates it through access the customer grants and can revoke, and upgrades ship in an agreed window. A workspace moves between the two modes by exporting and importing its graph versions, without a rebuild.

Each customer is one workspace. Every relation, index and version log is keyed by workspace, and every read is scoped to a single workspace. A workspace is created in the region the customer picks, and its graph, evidence, backups and LLM calls stay in that region.

Scaling

The retriever, compiler and analyst are stateless and scale horizontally. Read cost is bounded by the traversal limits of Section 6, so it depends on the question, not the size of the graph. Above the design point of Section 6, a workspace gets its own database and read replicas. Background jobs are incremental: after the first run, they process only what changed.

Cost

Background jobs read metadata and log tables, profile from samples rather than full scans, and replay approved metrics on a recent window. The customer sets a monthly compute budget and a run window, and can assign a dedicated warehouse or resource group. For production databases, connectors read from a read replica, never the primary, so Doram's jobs and questions cannot slow down production. Jobs run by priority within the budget. When it is exhausted, the lowest-priority jobs pause first, and the replay of approved metrics stops last.

A question costs one bounded graph read, one slot extraction by the LLM, one warehouse query that has passed the cost guard of Section 8, and the LLM tokens used to explain the answer. Section 12 reports the average tokens and warehouse compute per question.

Section 12

Benchmarks

Doram is evaluated on public benchmarks, for comparison with published results, and on an enterprise set that tests what public benchmarks do not: conflicting definitions, restricted data and questions that should not be answered.

Draft noteEvery figure marked x1, x2 and so on is a placeholder until the benchmark runs are complete.

Method

The public sets are Spider 2.0[1], BIRD[3] and the public release of BEAVER[2] (7,978 of its 9,128 questions; the rest is held out by its authors). For these, the graph is built automatically from what each benchmark provides, with no human review.

The Doram enterprise set has x1 questions across x2 company workspaces, taken from real query history and dashboards. It includes conflicting definitions, team-specific terms, hidden rules, fiscal calendars, events, restricted data, and questions that are ambiguous or unanswerable. Every expected answer is approved by a domain expert. Test questions and their SQL are removed from the query history used to build each graph, so no expected answer can reach the graph or question memory.

Doram is compared with an LLM given only the schema, an LLM with search over the company's documents, an LLM with a semantic layer written by an expert (enterprise set only), and the best published result on each public set. Every system uses the same LLM, x3, at temperature zero, with the same time limit per question. Each question is run five times, and results are reported as the mean with a 95% confidence interval. Doram's graph version is fixed for each run, so any result can be replayed.

The measures:

EX(q)         = 1 ⇔ rows(q) = rows_ref(q)    multisets, any column order
consistent(q) = 1 ⇔ all 25 results agree     5 rephrasings × 5 runs
CW            = P( wrong ∧ no refusal, clarification or warning )
leak          = access tests returning a restricted row or value

Confidently wrong (CW) is the measure that matters most. It is reported with the over-refusal rate, so a system cannot lower it by refusing everything.

Public benchmarks

Benchmark LLM + schema LLM + document search Best published Doram
Spider 2.0subset: x4 x5% x6% x7% x8%
BIRDdev set x9% x10% x11% x12%
BEAVER x13% x14% 10.8%[2] x15%

Table 3Execution accuracy on public benchmarks. Every system uses the same LLM, except the best published result, which may use a different split or model.

To show that the model is the replaceable part, the enterprise set is also run with x16 and x17, from other providers. Doram's accuracy changes by x18 points across models, against x19 points for an LLM given only the schema.

Enterprise results

Measure LLM + schema LLM + document search LLM + hand-built semantic layer Doram
Execution accuracy x20% x21% x22% x23%
Consistent across runs and rephrasings x24% x25% x26% x27%
Confidently wrong x28% x29% x30% x31%
Correct refusal on unanswerable questions x32% x33% x34% x35%
Clarifying question on ambiguous questions x36% x37% x38% x39%
Refused or asked when it should have answered x40% x41% x42% x43%
Restricted data returned x44 x45 x46 0 of x47

Table 4Results on the Doram enterprise set.

Ablations

One component is removed or replaced at a time, on the enterprise set:

Configuration Execution accuracy Confidently wrong
Full Doram x48% x49%
LLM writes SQL from the context pack, no compiler x50% x51%
Without the context layer x52% x53%
Without query-history discovery x54% x55%
Drafts used without validation or approval x56% x57%
Without the value index x58% x59%
Without question memory x60% x61%
Slots resolved one by one, not jointly x62% x63%

Table 5What each component adds, on the Doram enterprise set.

Retriever

Measure Result
Slot extraction accuracy x64%
Candidate recall at K = 20 x65%
Top-1 accuracy after ranking x66%
Joint resolution accuracy (a* matches the reference) x67%
Context-pack recall against the reference SQL x68%

Table 6The retriever, measured on its own.

Build and maintenance

Measure Result
Drafts approved automatically x69%
Drafts rejected by reviewers x70%
Auto-approved facts later reverted x71%
Reviewer hours in the first week x72
Reviewer hours per week by the second month x73
Time from connection to first answer x74
Certified metrics matching on daily replay x75%
Injected source changes detected x76%

Table 7Discovery, review effort and drift detection, averaged across workspaces.

Latency and cost

Stage p50 p95 p99
Retrieval x77 ms x78 ms x79 ms
Compilation x80 ms x81 ms x82 ms
End to end, excluding warehouse time x83 s x84 s x85 s

Table 8Latency at the design point of Section 6.

An average question uses x86 LLM tokens and x87 of warehouse compute.

Section 13

How Doram Compares

Four kinds of product give AI systems part of a company's knowledge. Each does some things well. The table compares them on what a trusted answer needs.

Capability Doram Data catalogs Semantic layers Platform AI analysts Text-to-SQL tools
Answers business questions with numbers ✓ — — ✓ ✓
Builds itself from your existing systems ✓ ◐ — ◐ ◐
Knows how each number is counted ✓ — ✓ ◐ —
Knows the rules, events and decisions behind the data ✓ ◐ ◐ ◐ —
Checks each number against a trusted report before use ✓ — ◐ ◐ —
Shows where every fact comes from ✓ ✓ ◐ ◐ ◐
Gives the same answer every time ✓ — ✓ ◐ —
Says "I don't know" instead of guessing ✓ — — ◐ —
Works with any AI tool ✓ ✓ ✓ — ◐

Table 9✓ yes · ◐ partly · — no. Examples: data catalogs (Atlan, Alation, Collibra, data.world), semantic layers (dbt Semantic Layer, Cube, AtScale, LookML, Timbr), platform AI analysts (Snowflake Cortex Analyst, Databricks Genie, Power BI Copilot, ThoughtSpot, Tableau Next, Omni), text-to-SQL tools (Wren AI, Vanna, TextQL). As of September 2026; products within a category vary, and many are adding features quickly.

Section 14

Limits and Conclusion

Limits

  • Cold start. Discovery is weighted by query history. A workspace with little history yields fewer candidates, so more definitions start as questions for their owners.
  • Knowledge facts are not testable. Decisions, policies and events are checked for evidence and conflicts, not against data. Their correctness rests on the owner who approves them.
  • Onboarding needs review. The first build produces a review queue. Low-risk facts go live automatically, but high-risk ones wait for their owners.
  • Bounded reach. Reads stop at a depth of three edges. A question that needs a longer join path is refused.
  • Explanation, not causation. An explain answer breaks a change into its parts and links the events in its time window. It does not prove cause, and Doram does not forecast.
  • Slot extraction can fail. The LLM can misread a question. Constraint checks, the decision margin and clarifying questions catch most misreadings, but not all.

Conclusion

AI models already know how to write SQL. What they lack is the company's meaning: what its words refer to, which data is real, how it counts, and what happened. That knowledge has always lived in a few people's heads and in traces spread across the company's systems.

Doram turns it into a company second brain: a semantic context graph built from the company's own systems, validated against its data, approved by its own people, and kept current on its own. Every AI system reads from it, so every answer uses the same approved definitions, can be traced to its evidence, and can be repeated.

The model is the part a company can replace. Its context graph is the part no one else can copy, because it is built from its own data, decisions and history, and it gets more valuable with every question answered.

The analyst knew the business. The AI knew the data. With a second brain, the AI knows both.

Back matter

Frequently Asked Questions

Does Doram copy our data?
No. The graph stores definitions, relationships, column profiles, small samples and evidence. Query results are shown to the user who asked and are never stored.
Which LLM does Doram use?
The one you choose, including your own model endpoint. Your data is never used to train a model.
What happens when Doram does not know?
It refuses, names the missing piece, and asks the owner. It asks the user a short question when a question is ambiguous.
How soon can we ask questions?
As soon as the first facts are approved. Low-risk facts that pass validation go live automatically, so the first answers do not wait for a review. Answers get better as owners approve more drafts. Section 12 reports the time from connection to first answer.
How much work is it for our data team?
Onboarding creates a review queue, sorted so the most-used definitions come first. After that, the target is fewer than ten reviews per owner per week.
Do we need a data warehouse or a data team?
No. Doram also works on read replicas of production databases. It then relies more on the schema and asks your engineers more questions.
We already have a semantic layer. Do we still need Doram?
Doram imports definitions from dbt, LookML and BI tools as strong drafts, then adds the context around them: events, decisions, evidence, trust levels and access rules, for every AI tool.
What happens when a definition changes?
It becomes a new version. New answers use it, and old answers can still be replayed on the version that produced them.
Can our own AI tools use the brain?
Yes, through the API, with the same access rules. They can propose changes, which go through the same review.
Can Doram run in our own cloud?
Yes. On-premise, the whole product runs in your cloud account, and nothing leaves except calls to the LLM you chose.

Back matter

Glossary

AI analyst
The agent business users ask questions. It reads facts only through the retriever and SQL only from the semantic compiler.
Approved
A trust level. The fact is accepted by its owner, or approved automatically because the change is low risk.
Certified
The highest trust level. The owner has signed the fact off as the company's official definition.
Company second brain
Doram's name for the company's semantic context graph and the agents that keep it current.
Context layer
The layer that holds how things connect, and why: joins, rules, policies, goals, events and decisions.
Context pack
What the retriever returns: definitions, join path, rules, policies, events and decisions, each with evidence.
Crawler agent
The only agent that creates drafts. It reads the company's systems and drafts facts from evidence.
Data-backed fact
A fact built on the database, such as a metric or a join, which can be tested against real data.
Discovered
The lowest trust level. Found by the crawler agent, with evidence, but not checked yet.
Evidence
The source behind a fact: a query, a model, a document, a tool record or a person.
Feedback agent
The agent that learns from how people use the analyst, and turns repeated signals into drafts.
Grain
The level a metric is counted at, such as one invoice line or one customer per month.
Knowledge fact
A fact that cannot be tested against data, such as a decision, a policy or an event.
Monitoring agent
The agent that watches the sources for change and checks what each change affects.
Ontology layer
The layer that holds what things are: entities, columns and the words people use for them.
Persona
A group of users with its own scope, such as Finance or Sales.
Question memory
Approved questions and how each was resolved, used to answer similar questions.
Retriever
The only way to read the graph. It finds, ranks and resolves what a question needs.
Semantic compiler
The code that turns a context pack into one SQL query, with access rules added.
Semantic context graph
The graph of nodes and edges that holds what the company knows about its data.
Semantic layer
The layer that holds how things are counted: metrics and the ways to split them.
Slot
One part of a question: the metric, a split, a filter, the time range or the task.
Trust level
Discovered, validated, approved or certified. It decides whether a fact can be used in answers.
Validated
A trust level. A data-backed fact that ran on real data and matched a known number.
Value index
An index of column values, such as region names, used to turn words into filters.
Workspace
One customer's own graph, evidence and settings, in the region it chose.

Back matter

References

  1. Lei, F. et al. Spider 2.0: Evaluating Language Models on Real-World Enterprise Text-to-SQL Workflows. ICLR 2025. arXiv:2411.07763
  2. Chen, P. B. et al. BEAVER: An Enterprise Benchmark for Text-to-SQL. Version 3, May 2026. arXiv:2409.02038
  3. Li, J. et al. Can LLM Already Serve as a Database Interface? A Big Bench for Large-Scale Database Grounded Text-to-SQLs (BIRD). NeurIPS 2023. arXiv:2305.03111
  4. Sequeda, J., Allemang, D. and Jacob, B. A Benchmark to Understand the Role of Knowledge Graphs on Large Language Model's Accuracy for Question Answering on Enterprise SQL Databases. GRADES-NDA 2024. arXiv:2311.07509
  5. Cormack, G. V., Clarke, C. L. A. and Büttcher, S. Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods. SIGIR 2009.
  6. Gao, D. et al. Text-to-SQL Empowered by Large Language Models: A Benchmark Evaluation (DAIL-SQL). VLDB 2024. arXiv:2308.15363
  7. Talaei, S. et al. CHESS: Contextual Harnessing for Efficient SQL Synthesis. 2024. arXiv:2405.16755
  8. Rethinking Schema Linking: A Context-Aware Bidirectional Retrieval Approach for Text-to-SQL. 2025. arXiv:2510.14296