bimtex
For agents

For agents

A building language a model can write, drawings it can look at, and a judgement loop it cannot flatter — the three moves that make an agent produce buildings instead of pictures of buildings.

An agent that draws buildings fails in one of three places: it does arithmetic it should not be trusted with, it never looks at what it made, or it grades its own work. bimtex is designed against all three, and the design is three moves.

Move one — declare, never draft

The model's job is to declare intent. The compiler's job is arithmetic. The validator's job is to return repairable contradictions.

NDJSON entities → compile → solids → derive plans · elevations · sections · 3D
                   └──────→ validate → diagnostics, addressed to the writer

A wall is a side of a footprint, not four coordinates; a roof is a form and a pitch, not a mesh. Every drawing is derived from one model, so the drawings cannot disagree with each other — and coordinates, ridge heights, areas and travel distances leave the model's working memory entirely. Bind the wire format as a tool schema (bimtex/ai exports the definitions) rather than describing it in prose: in the benchmark, one response spelled t as type on every line, and that single spelling produced 96 findings.

One consequence agents get wrong constantly: diagnostics come in two populations, and only one is work. blocking means the drawings contradict each other — geometry that cannot be built — and fails ok. Everything else (advisory, numeric thresholds, presentation lint) is an indicator: the model is unusual, not impossible, and an agent that spends repair turns on indicators loops forever on a model that was already releasable.

Move two — look at the drawing

Text diagnostics cannot say "the roof reads as a lid" or "half the frame is tarmac". The second half of the design is that the same inspect() that compiles and validates will also print the drawings:

import { inspect } from 'bimtex/ai';

const report = inspect(source, { review: true, split: true });
// report.diagnostics — the checker's findings, as text
// report.review.sheets — labelled SVGs, one per view, ready to rasterise

bimtex supplies the compiler, the diagnostics and the labelled sheet; the agent harness supplies the eyes — rasterise the SVG, hand the pixels to a vision model, and treat what it sees as findings the same way checker output is findings. A model that writes without looking ships buildings that pass every rule and read as nothing.

Move three — judge with different eyes than drew

The most expensive failure mode is self-assessment: measured on this repository's own artifacts, nineteen consecutive self-scores came back as compliments, and the same rubric given to a judge that had not drawn the model came back honest. So judgement is structurally separated from authorship:

  • the drafter must state a scheme before writing — what the building is, its organising idea, what each view must show — and is later held to it;
  • evaluate refuses a verdict on a drawing the drafter has not looked at since its last change, and cannot overrule the checker;
  • an independent crit — a second model call with no drafting history — reviews a fixed sheet set the drafter does not get to curate, and grades likeness against the scheme's own rubric;
  • the pass bar is never told to the model. A model that knows the bar clears it by writing a bigger number.

Two ways in

bimtex/ai — the primitives. getSyntax(), getVocabulary(), validateNdjson(), inspect(), the tool schemas. Build your own loop; this is the layer everything else stands on.

bimtex/drafter — the shipped loop. The full harness the studio runs: session, seven tools with their refusal gates, drawing rounds, the independent crit and the likeness score. It is host-agnostic — a browser tab and a server run the same code and differ only in the services they inject. Requires the optional peer dependencies ai, zod and @openrouter/ai-sdk-provider.