All posts

The determinism boundary: why an AI agent must not do the arithmetic

A language model cannot guarantee that a number is right. In the architecture we propose for structural engineering, the agent interprets and proposes, and every number comes from a verified solver.

Decades of commercial software have made the purely numerical part of structural analysis fast. Assembling a stiffness matrix and solving a linear system is a well-understood problem, and a cheap one to compute. The engineer’s time goes elsewhere: building the model, rebuilding it every time the architecture changes, defining loads and combinations, checking each element against the design code, and producing the calculation report and the drawings.

The bottleneck is that manual work around the calculation. Building, changing, checking and documenting the model is where an AI agent can help, on one condition: it must never touch the calculation itself.

What a language model cannot guarantee

A language model generates text probabilistically. It has no knowledge of physics or of how real systems behave, and it can hallucinate: produce answers that sound plausible and make no sense. In structural analysis the risk is concrete. Modelling requires spatial reasoning and topological consistency, and when a model is built over several steps, errors compound.

The strongest constraint, though, comes from professional practice. Every structural result is signed, with the authorship and legal liability that come with a signature. The number that sizes a column is a commitment by the licensed engineer who signs off on it. An agent that hands over unchecked results leaves the professional carrying the risk of signing a calculation nobody verified.

Correctness has to be a property of the solver, not of the language.

The determinism boundary

The architecture separates reasoning in natural language from numerical computation. The agent proposes designs and scenarios, but a result only counts once it has come out of a program the agent cannot modify, one that encodes the physics of the problem. The model chooses which deterministic tool to call and with which parameters, and works with whatever the tool returns. It never produces a number of its own and never makes up geometry.

In practice this takes three layers. The intent layer is the agent: it interprets natural language, asks clarifying questions and emits typed actions. The deterministic computation layer holds everything that produces engineering data: the solver, the CIRSOC modules that run the design-code checks, and the generators that expand a structural typology into a complete model. The documentation layer produces reports, drawings and quantity take-offs from results that have already been computed.

This is not a new pattern. It dominates the recent literature on engineering agents and shows up in neighbouring fields: coding agents work because a compiler and a test suite tell them whether the code builds and passes, and AlphaProof proves theorems because a formal verifier lets no error through. We adopt it deliberately as a design principle.

What the boundary guarantees, and what falls outside it

It helps to be specific about what this boundary guarantees and what it leaves out. What it guarantees:

  • Every number the agent states can be traced to a specific solver result: combination, station, element.
  • Every AI output is validated against the model schema before it is imported, and rejected if it is malformed or contains unknown fields.
  • If the AI service is down, the solver, the editor and the design-code checks keep working.

What it does not guarantee: that the idealised model is the right one for the real problem (that is an engineering decision), that the design is optimal, that the loads and assumptions are complete, or that the reading of the code needs no review.

A case where the model has to be solved again

The engineer describes a reinforced concrete portal frame with a 6 m span and a height of 4 m, fixed bases and a distributed load on the beam. The agent asks for what is missing: steel or concrete? Fixed or pinned bases? Any lateral load? It then emits the action that creates the frame. The backend expands it deterministically into a model with 4 nodes, 3 elements and 6 free degrees of freedom. The design uses H-21 concrete, a 25×40 cm beam to start with, 30×30 cm columns and 30 kN/m on the beam.

Once the model is solved, each column carries a vertical reaction of 90 kN and global equilibrium holds exactly: ΣRz = 180 kN = q·L. The governing beam moment is Mu = 80.8 kN·m at midspan. The CIRSOC 201 flexural check of the 25×40 beam with 3Ø16 gives a capacity of φMn = 73.3 kN·m, so the beam fails the check.

StateSectionReinforcementMu [kN·m]φMn [kN·m]D/CPasses
Initial25×40 cm3Ø1680.873.31.10No
Corrected30×55 cm3Ø16105.6108.60.97Yes
Flexural check of the frame beam, before and after the correction.

Look at the Mu column. Enlarging the beam from 25×40 to 30×55 raises the demand from 80.8 to 105.6 kN·m. In a statically indeterminate frame, statics fixes the sum of the end moment and the midspan moment; stiffness only changes how that sum is split. A beam that is stiffer relative to its columns gets less end restraint from them and behaves more like a simply supported beam, so its midspan moment, which governs here, goes up.

An agent that estimated the effect without re-solving would get it wrong, and would sound just as convincing while doing so.

The example shows why the model has to be solved again, on top of recomputing the capacity of the new section. In an indeterminate structure, enlarging a section changes how internal forces are distributed, and the demand can rise in exactly the member you meant to relieve.

Removing a column from a building that has already been designed

The second case starts from a frame with four 5 m bays and three 3 m storeys, fixed bases, 25×50 cm beams (4Φ16), 35×35 cm columns and 25 kN/m on every beam: 20 nodes, 27 elements and 45 free degrees of freedom. Once solved and checked, every beam passes comfortably.

An architectural change removes an interior ground-floor column. The edit action deletes it with a structural-integrity validation, and the model is solved again; global equilibrium holds before and after (ΣRz = 1500 kN). The beams that were supported by that column now span 10 m and, together with the beams aligned above them, pick up the lost support. Six beams exceed D/C = 1.

StateSectionMu [kN·m]φMn [kN·m]D/CPasses
Intact25×50 (4Φ16)54.2125.30.43Yes
Column removed25×50 (4Φ16)203.9125.31.63No
Resized30×65 (5Φ20)189.8313.70.61Yes
The governing beam of the building in its three states.

The governing beam’s moment nearly quadruples. With 30×65 cm and 5Φ20 in the affected beams and a new solve, every beam passes again. The case also shows that a change which, by hand, means re-modelling, re-analysing, re-checking and re-detailing many members can be handled in a short conversation, with every number traceable to the solver and subject to the engineer’s approval.

Four design decisions behind the boundary

  1. Typed actions instead of free-form code generation. In several earlier systems, the model writes Python scripts that are then run against an external solver. Here the agent’s output is limited to a closed set of calls with explicit input and output contracts, each validated against a schema before it runs. That boundary is narrower than arbitrary code and easier to audit.
  2. Our own solver, rather than a layer on top of someone else’s. The engine is written from scratch in Rust, with no external linear-algebra dependencies, and has its own verification suite against analytical solutions and reference benchmarks: around 6,800 passing tests, plus comparisons with a commercial program on the same models, with differences below 0.1%.
  3. Native design-code compliance. Checks to CIRSOC 201 and 301, which we have not found implemented natively in any open-source software. The concrete module is implemented and tested; the steel module still lives only in the frontend and has no dedicated test suite. We say so to avoid overstating how mature it is.
  4. Runs in the browser. The engine compiles to WebAssembly and runs locally on the user’s machine, with no compute server and nothing to install.

From a tested solver to a proven one

The boundary guarantees that every claim the agent makes can be traced to a solver output. That guarantee inherits a limit: the solver is trustworthy because it is extensively tested, but its correctness has not been formally proven. A test suite, however thorough, only covers the cases its authors thought of.

This matters even more in this context. An agent builds models, modifies them over several steps and reads the results to propose new actions; along the way the solver receives inputs that no engineer reviewed before they reached the engine. If the engine misbehaves on an edge case (a nearly singular stiffness matrix, degenerate geometry, an extreme load combination), the agent may quote that result without any warning.

Two techniques can narrow that gap. Property-based fuzzing generates thousands of valid random models and checks invariants that must hold for any input:

  • Global equilibrium: ΣR = P, regardless of geometry, materials or supports.
  • Stiffness-matrix symmetry: K = Kᵀ by construction.
  • Positive definiteness of K for any structure without mechanisms.
  • Invariance under rigid-body transformations: translating or rotating a model does not change the internal forces.

Formal verification approaches the same gap from the other side: write a mathematical specification of those properties and prove, with a proof assistant such as Lean 4, that the implementation satisfies it. Testing can find errors; formal verification can show they are absent within the specified domain. The two complement each other: when the fuzzer finds an input that breaks a property, that property becomes a candidate for a proof.

Where this stands today

To close, what is available and what is not. The solver, the editor, the CIRSOC checks, the education mode and report and drawing generation run today in the browser at stabileo.com, with nothing to install and no account needed. The agent layer is under active development: its routes run in development and testing against our own backend, on the same solver and the same numbers as everything else, but that backend is not yet part of the public site.

The closed solver-in-the-loop cycle, in which the agent proposes, solves, evaluates and modifies without human intervention, is on the roadmap and has not been implemented. Native design-code coverage is limited to CIRSOC 201 and 301; the rest is future work.

CAD took over the mechanical part of drafting and the spreadsheet took over repetitive arithmetic, while engineering judgement stayed with the engineer. The agent is the next step along that line: it takes on building and modifying the model, entering loads, running the checks and preparing the documentation. None of this transfers responsibility: the signed number is still the engineer’s.

All posts
|

View

Draw

Properties

Conditions

Analyze

Results

Pan
Start by creating nodes (N)
Pos: (0.00, 0.00) m
Zoom: 50 px/m
Model: empty
Selection: —
Grid: 1.00 m