Skip to content
AnantCausal
Technical overview

What the engine computes.

Exact arithmetic over a discrete causal model — not estimation from observational data. The distinction is the whole product, so this page states both halves of it.

If what you need is a doubly-robust estimate or a causal forest, this is not that, and the interoperability page explains where to take the model instead.

Computes

What it computes

Nine things, each exact over the stated model. Every one is a route that can be called today.

  • Exact inference

    Marginal, conditional and interventional probabilities by variable elimination over the factorised model. The result is exact given the tables — there is no sampling, no convergence and no seed.

    POST /v1/networks/{id}/query

  • Identification

    Whether a treatment-outcome question is answerable from the structure at all, and by which route: backdoor, front-door, or not identified. Also reports the instrument candidates it considered and rejected.

    infer/identify.py, surfaced on every effect response

  • Adjustment sets

    The full backdoor set and its minimal subset, searched by increasing size over the non-descendants of the treatment. Two callers adjusting for different sets get the same estimate with different variance, which is a real choice and the response makes it visible.

    minimal_adjustment_set, on every effect and handoff response

  • Effects with a named band

    A risk difference and ratio for a stated baseline-contrast pair, with a sensitivity envelope as the band. The band names its own basis in the payload, so a consumer can tell that it is a sensitivity band rather than a confidence interval.

    POST /v1/networks/{id}/effect

  • Refutation

    A battery that tries to break the effect: an unmeasured-confounder stress test, a conditional-association comparison, and a fragility bound. Each check reports pass, fail or inconclusive, and inconclusive is never counted as a pass.

    POST /v1/networks/{id}/refute

  • Heterogeneous effects

    The effect per subgroup of a chosen variable, ranked. This is exact elimination per stratum over a discrete model rather than a learned CATE function, which is why it needs no data and no new dependency.

    POST /v1/networks/{id}/segments

  • Targeting under capacity

    Which subgroups to act on given a stated capacity, which is a ranking and thresholding problem over the per-subgroup effects rather than a separate model.

    POST /v1/networks/{id}/targets

  • Counterfactuals and diagnostics

    What the outcome would have been given what was observed, and the ranking of what would best explain an observed outcome. Both are exact over the tables, including the parts of the table that had no observations and kept the uniform prior.

    POST /v1/networks/{id}/counterfactual, /diagnose

  • Positivity

    Which strata an adjustment set has no data for. This is the check that catches an effect computed in a region where the model has nothing behind it, and it is reported separately rather than folded into the effect.

    GET /v1/datasets/{id}/positivity

Does not compute

What it does not compute

Stated before the capacity limits, because a technical reader will look for these first and the honest place for them is on the page rather than in a footnote.

  • Effects estimated from observational data

    There is no estimator here in the statistical sense. A heterogeneous treatment effect learned from rows carries sampling error and an interval; an exact elimination result carries neither, because it is arithmetic on a stated model. Those are different claims and the product keeps them in different response shapes rather than behind one field.

    deliberate; see /platform/interop for the handoff route

  • Confidence intervals

    The band on an effect is a sensitivity envelope: it says how far the answer moves when each table is shifted by a stated amount. It is not a sampling interval and is never described as one. A reader who needs the latter needs an estimator.

    band.kind and band.basis are on every effect response

  • Native continuous variables

    Variables are discrete. A continuous variable reaches the model through binning, which is lossy and labeled on the row rather than hidden. Where the outcome is genuinely continuous and binning would destroy the question, this is the wrong tool.

    a modeling choice, and a real limitation

  • Structure learning at scale

    Structure is elicited, or recovered from conditional independence tests on a table that fits in the envelope. This is not a structure-learning package for a wide observational dataset, and the graph it builds is an assumption with a source per edge rather than a discovery.

    POST /v1/networks:from-table screens within the cell cap

Envelope

What it computes it over

The envelope is a bound on the model, not a target for one. These are the committed limits, and the capacity page carries the measurements behind them separately.

Variables
≤ 24
a bound on the model, not a target for one
Conditional table
≤ 2,048 cells
per node, across all its parents
Variable arity
any finite
the shipped demos are binary for legibility, not by limitation
Deployment
one process, one database
horizontal scaling has not been measured
The arithmetic

The arithmetic, stated

Three formulas. Each is the thing the product is claiming, so each is on the page rather than implied by the word exact.

  • Interventional probability

    P(y | do(t)) = Σ_z P(y | t, z) · P(z)

    The backdoor adjustment, where z ranges over the adjustment set. The treatment's own mechanism is removed and the confounders keep their observed distribution. When no such z exists, the answer is not identified and the response says so.

  • Why it is exact

    P(all variables) = Π_i P(x_i | parents(x_i))

    The joint is a product of the tables by construction, so any marginal or interventional quantity is arithmetic over the tables rather than a simulation. There is no Monte Carlo step, which is why two calls on one revision are byte-identical.

  • The band

    band = [ minₖ effect(θₖ), maxₖ effect(θₖ) ]

    The same question is recomputed with every row that has a calibrated interval moved to the ends of that interval, and the band is the range of those answers. kind says which perturbations produced it — sensitivity_envelope when tables were shifted, ensemble_envelope when the spread came from independent draws, combined when both contributed — and it never means sampling error, because an elicited model has no sample to draw error from. A row with no interval keeps its probability and contributes no width rather than an invented one; if no row is covered, there is no band and the response says so instead of emitting one that pretends to a range.

Exact over a stated model is a narrower claim than estimated from data, and it is the only one that survives being asked where the number came from.