> ## Documentation Index
> Fetch the complete documentation index at: https://honeydew.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Semantic Compiler

> How Honeydew compiles a semantic query into deterministic, warehouse-native SQL.

Honeydew is built around a deterministic **semantic compiler**. It takes a *semantic query*, a
structured request expressed in terms of your model (entities, metrics, attributes, filters,
groupings), and generates warehouse-native SQL that your data warehouse executes. That query is
produced by the client that issues it: a BI tool, the
[SQL interface](/docs/integration/sql-interface), or an AI agent. It is never raw text. The same
semantic query always compiles to the same SQL, and therefore returns the same numbers.

## What compilation resolves

Given a semantic query and your model, the compiler determines the SQL that answers it. It draws
on four things from the model:

* **Relationships (the ERD).** [Entities](/docs/modeling/entities) and the
  [relations](/docs/modeling/relations) between them define the join paths. The compiler selects the
  path needed to connect the requested fields and builds the joins.
* **Definitions and their lineage.** [Metrics](/docs/calculations/metrics) and
  [calculated attributes](/docs/calculations/attributes) are expressions that often depend on other
  metrics and attributes. The compiler expands each definition and resolves those dependencies in
  the correct [order of computation](/docs/advanced-modeling/order-of-computation).
* **Grain and correctness.** Combining facts at different grains is where hand-written SQL
  silently double-counts. The compiler handles fan-out and chasm traps when
  [mixing granularities](/docs/advanced-modeling/mixing-granularities), across
  [shared dimensions](/docs/advanced-modeling/shared-dimensions) and
  [multi-grain tables](/docs/advanced-modeling/multi-grain-tables).
* **Efficiency.** The compiler rewrites the query to use
  [aggregate awareness](/docs/performance/aggregate-awareness) and the warehouse result cache, so a
  request reads pre-aggregated data instead of scanning raw rows when an aggregate is available.

Take the semantic query *"revenue by customer segment, this year"*. The compiler resolves the
customer-to-order relation, expands the `revenue` metric into its aggregation, deduplicates the
fan-out from customers to orders, applies the time filter, and emits a single SQL statement. Your
warehouse runs it; Honeydew does not process or store the data. The compiler generates SQL for
whichever warehouse you run, whether Snowflake, Databricks, or BigQuery.

<Tip>
  This is **not text-to-SQL**. A text-to-SQL tool has an LLM write SQL directly from a question, so
  the same question can produce different SQL, and different numbers, on different runs, and can
  reference joins or columns that don't match your model. A compiler generates the SQL itself from
  the model, so the result is deterministic.
</Tip>

## The determinism guarantee

Because the SQL is generated by the compiler from the model:

* **The same semantic query always compiles to the same SQL.** A metric, for a given filter and
  grouping, is computed one way every time.
* **Numbers reconcile across tools.** The same metric returns the same value in Power BI, Tableau,
  Excel, and an AI agent, because all of them compile through the same engine.
* **Only modeled objects can appear.** The compiler can use only the entities, relations, and
  metrics you have modeled. It cannot invent a join or a definition.

A definition can still be *wrong* if the model is wrong, but it is wrong the same way every time,
which makes it easy to find and fix rather than varying run to run.

## Serving an AI analysis

The compiler answers one semantic query. An AI analysis is many *correlated* semantic queries: the
steps are not independent, because a later step references the entities and results of an earlier
one. The compiler wires those references together, resolving the join paths that connect them so
each step stays correct against the model. Each step still compiles the same deterministic way:
the AI decides what to ask and which step builds on which, and the compiler decides how each is
answered and how they join.

<Info>
  For example, one step might isolate an underperforming segment and the next analyze its orders
  over time. The compiler resolves how customers connect to orders, so the second step is scoped to
  the first.
</Info>

When a question arrives from an AI surface such as Claude, Codex, Cortex Code, or a Slack bot,
Honeydew opens an [analysis session](/docs/integration/context-layer/deep-analysis) and answers it in
steps. Take *"what are our key profit opportunities?"*:

<Steps>
  <Step title="Interpret">
    The agent maps the question to managed objects, using the
    [context layer](/docs/integration/context-layer/overview) (instructions, skills, synonyms) to resolve
    what the terms mean in your model.
  </Step>

  <Step title="Plan">
    It builds an analysis plan, a sequence of semantic queries, often a dozen or more, each building
    on the last. One step might be *"profit and revenue by menu item."*
  </Step>

  <Step title="Compile and execute">
    Each semantic query compiles to SQL and runs, exactly as any semantic query does. The agent reads
    the results and decides the next query.
  </Step>
</Steps>

The AI only expresses each step as a semantic query; it never writes the SQL. The agent references
a `revenue` object without knowing whether it compiles to one table or a several-hundred-join
query. What the AI can get wrong is **interpretation**: mapping an ambiguous question to the wrong
objects. Two mechanisms contain this:

* **Semantic tests between steps.** Each step is validated against the model. If the agent requests
  a metric at a grain where it isn't defined, the step fails, the agent receives the error, and it
  self-corrects rather than returning a wrong number.
* **The context layer.** Real ambiguity, such as several candidate customer-id columns with nothing
  to distinguish them, is resolved with the [context layer](/docs/integration/context-layer/overview)
  and [AI metadata](/docs/integration/context-layer/ai-metadata). This is the part you tune, and the
  only probabilistic part of the system.

<Tip>
  Because the LLM never writes SQL, a whole class of hallucinations cannot happen: it cannot invent a
  join, a metric definition, or a column. Only interpretation can be wrong. An analysis also uses
  fewer tokens than a text-to-SQL system doing the same work, because the AI emits compact semantic
  queries rather than full SQL.
</Tip>

<Note>
  Every session is recorded in [question history](/docs/monitoring/question-history): the question, the
  plan, each semantic query, and the generated SQL, so a data team can audit exactly how any answer
  was produced.
</Note>

## Do I still need verified queries?

Teams coming from text-to-SQL systems, including Snowflake Cortex Analyst's *verified queries*,
often ask whether they need to pin or verify individual questions in advance. With a compiler this
is unnecessary: correctness is guaranteed for any in-scope question, not just a curated list. Where
you invest instead is the [context layer](/docs/integration/context-layer/overview), with instructions
and skills that guide *how* the AI interprets a question and which metrics it should prefer.

## Related

<CardGroup cols={2}>
  <Card title="Architecture" href="/docs/architecture" icon="diagram-project">
    Where the compiler sits between the warehouse and your tools.
  </Card>

  <Card title="Mixing granularities" href="/docs/advanced-modeling/mixing-granularities" icon="layer-group">
    How fan-out and chasm traps are handled across grains.
  </Card>

  <Card title="Aggregate awareness" href="/docs/performance/aggregate-awareness" icon="gauge-high">
    How the compiler rewrites queries to read pre-aggregated data.
  </Card>

  <Card title="Deep Analysis" href="/docs/integration/context-layer/deep-analysis" icon="route">
    How an investigative question becomes a multi-step answer.
  </Card>
</CardGroup>
