> From https://dialect-engineering.ai/sections/9-grammar, the companion site to the paper "SaaS architecture when code is cheap". Draft, September 2026.

# SaaS architecture when code is cheap

## 9. A grammar above the graph

A knowledge graph records that a given primitive exists and what it relates to. A grammar records what a valid instance of that primitive looks like, which of its parts may vary, what values each part admits, and which combinations are legal.

Take a product whose configuration primitive is a screen bound to a set of fields and a rule set. The graph holds the primitive as a node with its relationships. The grammar states that this primitive admits these parameters, that one parameter takes one of four values, that another is required when a third is present, and that a given combination is invalid. An agent given the grammar writes in the product's own vocabulary rather than in Angular or React, and the text it produces can be parsed, validated and tested before anything reaches the product.

What the grammar provides:

- **Parsing and validation.** A malformed document is rejected at the boundary with a location and a reason.
- **Editor support.** Syntax highlighting, completion and inline errors come from the language workbench through the Language Server Protocol, with no bespoke tooling. The same protocol that gives a developer these affordances in an editor gives them to an agent.
- **A test target.** Functional tests can be written against the language and run by the agent, so semantic errors that the tests cover are caught without a person reading the document.
- **Worked examples.** Every converted screen becomes a reference for the next one.
- **A smaller output.** The agent writes the domain construct rather than its implementation, so there is less text to get wrong.
- **A bounded reach.** An agent writing in the language cannot add an API, a table or a code path. Its reach ends at what the language can express, so the shared layers below the line are outside what it can change.

The last property matters specifically for a multi-tenant platform. The layers below the line are the ones every tenant shares, and an agent confined to the language has no route into them.

The tooling for this is two decades old. Fowler's 2005 article called language workbenches the killer application for domain-specific languages, and his 2010 book *Domain-Specific Languages* is the standard treatment of both external and embedded forms. The category has been continuously maintained since: MPS, Xtext, Spoofax, Rascal, and more recently Langium. Grammar, parser, editor support and validation are standard output from any of them.

Adoption fell short of that 2005 expectation: the assessment from inside the field is that these workbenches see real use and none reached the traction anticipated ([Are language workbenches dead?](https://medium.com/@dslmeinte/are-language-workbenches-dead-4b05d1698d3c)). One reason was that domain experts did not author in the language. The same pattern repeated with low-code platforms, where the people operating the platform turned out to be developers, who reasonably asked why they should use it when they already knew how to write the underlying code. The adoption literature adds scarcity of compiler competence, absence of established vendors, fear of lock-in, and prior bad experience with 4GL and rapid-application-development tools ([Reflections on the Lack of Adoption of DSLs](http://grammarware.net/text/2020/dsl-adoption.pdf), 2020).

```mermaid
flowchart LR
    A["Domain expert states intent<br/>in natural language"] --> B["Agent authors the document<br/>in the domain grammar"]
    B --> C{"Parser and validator"}
    C -->|"invalid"| B
    C -->|"valid"| D["Functional tests"]
    D -->|"fail"| B
    D -->|"pass"| E["Compiler"]
    E --> F["Product configuration,<br/>interface, API calls"]
    F --> G["Result shown back<br/>to the domain expert"]
    G --> A
```

What changed is the second step, where the agent rather than the expert authors the document. The expert no longer learns the notation, and the definition of the language and its compiler stay with the product company. The grammar can also stay small, because the model brings general world knowledge to the translation. A language with a generic `room` primitive needs no `bedroom` keyword, since the model maps the word to the primitive. That mapping previously needed hand-written pattern matching.

Two disciplines divide this work at the multi-tenancy line. Semantic engineering governs what sits below it: the knowledge graph that records the domain invariants every customer shares, and the process by which those invariants change ([Semantic Engineering](https://semantic-engineering.ai)). Dialect engineering governs what sits above it: a domain language defined over those invariants, in which each customer's business rules are written as that customer's own dialect, and in which people, agents and applications exchange requests and results, each exchange checked by the grammar and the functional tests before it takes effect.

### 9.1 What the grammar does and does not guarantee

A grammar bounds what can be expressed. A request the language has no construction for produces no valid document, so it is refused at the boundary with a reason, rather than being silently reinterpreted as the nearest thing the language can say. The gain is in the failure mode.

The clearest measurement of that trade comes from constrained generation. When PICARD checked each step of a model's SQL output with a parser, for T5-3B on Spider's development set, 12% of generated queries caused an execution error without it; with it, 2% were unusable, all cases where no valid query was found, so they surfaced as explicit non-answers ([Scholak et al., PICARD](https://arxiv.org/abs/2109.05093), EMNLP 2021).

Analytics shows the same behaviour one level down. dbt compared free-form text-to-SQL against queries through a semantic layer: on a properly modelled project one model went from 84.1% to 100.0% and another from 90.0% to 98.2%, and beyond the semantic layer's coverage accuracy was 0.0%, against 70.0% for free-form SQL ([Semantic Layer vs. Text-to-SQL](https://docs.getdbt.com/blog/semantic-layer-vs-text-to-sql-2026), vendor benchmark with public dataset and method). A semantic layer is a governed catalogue of concepts, closer to the knowledge graph of section 8 than to a grammar, and it shows the same behaviour at its boundary. A formal layer stops at its boundary rather than degrading, and that is the trade being made.

Semantic errors inside the language remain entirely possible. Across 21 models the Structured Output Benchmark found JSON pass rates of 84.5% to 99.97% against value accuracy of 69.3% to 83.0%, so near-perfect structure routinely contains wrong values ([The Structured Output Benchmark](https://arxiv.org/html/2604.25359v1), arXiv preprint, 2026). At small model sizes and under hard constraints the gap widens: across 15,000 generations on models from 0.5B to 3B, schema validity rose from 61.5% to 100.0% while answer accuracy fell from 19.7% to 11.0%, and the share of outputs that were wrong while remaining schema-valid rose from 49.5% to 88.9% ([The Constraint Tax](https://arxiv.org/html/2605.26128v1), arXiv preprint, 2026).

Our own implementation supplies the same lesson without a benchmark. In the house-design language described in section 13.1, a mistyped reference resolved silently to zero and produced a valid document that rendered a plausible, wrong building. The validator as built did not catch it. What catches that class of error is executing the document against adjudicated cases, which is why functional tests are load-bearing rather than optional.

The claim, then, is that a grammar, a validator and an executable test corpus together produce a system that refuses what it cannot express and catches the errors its test corpus covers, while an agent writing inside the language remains capable of error.

---

---

Previous: [8. The knowledge graph as the starting inventory](https://dialect-engineering.ai/sections/8-knowledge-graph.md) · Next: [10. Configuration schema and grammar](https://dialect-engineering.ai/sections/10-schema-and-grammar.md)
