Healthcare

For Both Executive and Technical Readers

Which exposure caused this patient’s outcome, separated from the confounders that made it look more or less likely, answered per patient, not on the average.

The Healthcare plug-in, vocabulary, structure, and the questions your leaders ask, already mapped. Nothing here starts from a blank page.

Executive Summary · Healthcare

The QuestionDid this exposure cause this patient's outcome, or just correlate with it?

The MethodA structural causal model with explicit confounders, computing the probability of necessity per patient.

The AnswerA per-patient causal attribution, not a population average standing in for an individual case.

PHARMACOEPIDEMIOLOGY has a well-developed Rung 2 toolkit. Cohort studies, case-control studies, self-controlled case series, target-trial emulation, these all answer the population-level question: across many patients, how does drug exposure shift the distribution of an adverse outcome? That is sufficient for regulatory approval and for population-level risk-benefit analysis.

It is not sufficient for the individual question that drug-injury cases, M&M conferences, and causality-assessment frameworks (WHO-UMC, Naranjo, RUCAM) ask: in this specific patient, with this specific exposure, did the drug cause the injury? That is a Rung 3 counterfactual claim, and answering it requires structural commitments that go beyond what a Bayesian network can offer on its own.

The structural problem

A standard Bayesian network can compute P(AKI | NSAID, covariates) at Rung 1 and P(AKI | do(NSAID), covariates) at Rung 2. It cannot, by itself, compute P(AKI = No | do(NSAID = No), this patient’s observed factual outcome and covariates), the probability of necessity, the formal version of “but-for cause.” That computation requires committing to a structural-equation interpretation of the graph, with explicit exogenous variables that absorb the residual variation. Those exogenous variables, the U-nodes, are abducted from the factual observation, the intervention is applied, and the counterfactual outcome is read.

The model is a Structural Causal Model in the strict sense: every endogenous variable has its structural parents AND a corresponding exogenous U-node. The U-nodes are not optional cosmetic additions, they are what makes the counterfactual computation tractable.

Node States Role
BaselineRenalFunctionNormal · CKD_stage_2_3 · CKD_stage_4_plusPre-existing risk
SurgeryTypeMinor · Major · NoneAcute insult
PeriOpDehydrationLow · Moderate · HighModulator
ConcomitantNephrotoxinNone · Vancomycin · IV_Contrast · MultipleCo-cause
NSAID_ExposureYes · NoExposure of interest
IntraopHemodynamicsStable · HypotensiveMediating variable
AKI_outcomeYes · NoAdverse event of interest

Each observable also has a U-node, U_NSAID, U_AKI, etc., modeled as a 2-state exogenous variable with a 50/50 prior. These U-nodes are the residual variation that structural parents do not explain. Edges: BaselineRenalFunction, SurgeryType, PeriOpDehydrationIntraopHemodynamics. IntraopHemodynamics, NSAID_Exposure, ConcomitantNephrotoxin, BaselineRenalFunctionAKI_outcome. Optionally: BaselineRenalFunctionNSAID_Exposure (CKD reduces NSAID prescribing, confounding by indication in the protective direction).

The solution was to model the relationships between the variables that determine adverse event risk, and to be explicit about which variables cause which. We recognised, for example, that NSAID exposure does not operate independently of baseline renal function, the same exposure produces very different risks depending on what was already true about the patient, which means observing an adverse outcome tells you something about both the exposure and the pre-existing conditions that modulated it. Surgery type, perioperative dehydration, and concomitant nephrotoxins all contribute to the outcome, but through different mechanisms that a regression coefficient cannot separate. When you observe a variable in this model, you are effectively filtering the data to cases where that variable takes a particular value, and that filter ripples through the model, shifting related variables up and down accordingly. When you intervene on a variable, forcing it to a value regardless of what caused it, you break that ripple effect and get a cleaner answer: not what patients who look like this tend to experience, but what would have happened if this specific exposure had been absent When you abduct, you extract a particular case from the averages, locking in its idiosyncratic circumstances before asking what would have happened if one or more things had been different.

Identifiability

Rung 2 is identifiable under standard back-door adjustment. Rung 3, the probability of necessity, is identifiable given the SCM structural assumptions: that U-nodes are independent across observables, that structural equations are deterministic given (parents, U), and that the parameterization is correct. Rung 3 always requires assumptions that go beyond what data alone can support, and naming those assumptions is a precondition for using the inference responsibly in a regulatory or legal context.

Rung 1: Association: confounding by indication

Among patients with this covariate profile who took the NSAID, what fraction developed AKI? Clinicians prescribe NSAID_Exposure less in patients with CKD, precisely because they fear AKI. The covariate is informative about both the outcome AND the prescribing decision. The conditional cannot tell you which is which.

This patient profile shows a 56% AKI rate after NSAID exposure. That number is misleading because clinicians already steer NSAID use away from CKD patients, so the apparent association mixes drug effect with patient selection.

Rung 2: Population Effect: the causal effect of the NSAID

If we forced NSAID exposure on a random patient, without conditioning on the prescribing rule, what would the AKI rate be? The do-operator severs the BaselineRenalFunction → NSAID_Exposure edge, breaking the back-door from CKD into the prescribing rule. This is the standard regulatory question, sufficient for label warnings and prescribing guidelines.

The actual causal effect of NSAID exposure across the population is +9.3 percentage points in AKI risk. That’s real, and it justifies the label warning, but it does not tell us whether the NSAID caused this specific patient’s AKI.

Rung 3: Individual Counterfactual: the central question

This patient took the NSAID and developed AKI. Would the AKI have occurred if they had not taken the NSAID? Three operations on the same graph: (1) set the patient’s full evidence, U_AKI’s posterior shifts away from 50/50, encoding this patient’s idiosyncratic AKI susceptibility. (2) Carry the abducted U_AKI forward as soft evidence. (3) Apply do(NSAID_Exposure = No) and read the counterfactual outcome.

For this specific patient, the model estimates a 50% chance the AKI would have occurred even without the NSAID: given their CKD, major surgery, and intraoperative hypotension. So the probability of necessity, the strength of the claim that the NSAID caused this AKI, is 50%. That’s a defensible patient-specific attribution.

A language model can speak fluently about any domain. It cannot know one. The .bayes file is the knowledge the LLM is missing: a causal map of the domain, auditable, versioned, and wrong in specific correctable ways.

Optionally open PharmacovigilanceAttribution.bayes in Bayes Server or any equivalent tool. The model is the thing; the software that runs it is a commodity.

A black checkmark = observed evidence. A red checkmark = do() intervention (severs incoming links; parents stay at prior).

Rung 1, Association: confounding by indication

Prior, no evidence set
Prior, no evidence set

Population baseline before any patient data is entered. AKI, NSAID exposure, and covariates all sit at their marginal priors.

Rung 2, Population effect: do() vs obs() on NSAID

Prior, no intervention applied
Prior, no intervention

Population baseline. NSAID is at its prior, some patients exposed, most not, driven by the natural prescribing rule that depends on renal status.

Rung 3, Individual counterfactual: did the drug cause this patient’s injury?

Prior, no evidence set
Prior, no evidence set

Population baseline before any patient data is entered. All nodes at their marginal priors.

The model is a file. Any capable LLM can load its XML and answer pharmacovigilance questions in plain English, keeping association, population effect, and individual counterfactual apart.

We have a patient with CKD stage 2-3 who developed acute kidney injury three days after starting an NSAID post major surgery. Our safety team wants to know if the NSAID caused the injury.
AnyChatRung 1 · association
Before we get to attribution, I need to flag a confounding problem. Clinicians prescribe NSAIDs less in CKD patients precisely because they fear AKI, so if I just read the chart-review rate for this profile, I get 56% AKI after NSAID exposure. But that mixes the drug’s effect with the selection process. CKD is upstream of both prescribing and outcome. The observational number isn’t the causal effect.
What is the actual causal effect of the NSAID on AKI in this patient population?
AnyChatRung 2 · do(NSAID = Yes)
Running do(NSAID = Yes) severs the prescribing rule, BaselineRenalFunction stays at its population prior rather than updating toward CKD. The unconfounded causal effect is +9.3 percentage points in AKI risk. That’s the number that justifies the label warning. But it’s a population average, not an answer about this specific patient.
But did the NSAID cause the injury in this patient specifically? That’s what the M&M committee needs.
AnyChatRung 3 · abduct → counterfactual
That’s the probability of necessity, the formal version of “but-for cause.” Step one: abduction. I enter the full factual record: CKD stage 2-3, major surgery, moderate dehydration, NSAID = Yes, AKI = Yes. U_AKI’s posterior shifts away from 50/50, encoding this patient’s idiosyncratic susceptibility. Step two: do(NSAID = No) on that same anchored world. AKI_outcome reads 50% Yes: meaning there’s a 50% chance the AKI would have occurred even without the NSAID, given their CKD, major surgery, and intraoperative hypotension. Probability of necessity: 50%. That’s the defensible patient-specific attribution for the M&M committee.
How do you know all this?
AnyChatRung 1 · provenance
I don’t know it, the model does. The CPTs were built from clinical literature on NSAID nephrotoxicity, CKD risk stratification, and perioperative AKI. Every number I gave you comes from PharmacovigilanceAttribution.bayes. Open the file, inspect every node and CPT, change any parameter your clinical team disagrees with. The model is auditable. I’m just the interface.
Our pharmacovigilance team already runs adverse event reporting. Isn’t that sufficient?
AnyChatRung 3 · but-for causation
Adverse event reporting captures association: the NSAID was on board when the AKI occurred. It cannot answer whether the NSAID caused the injury in this patient, because it does not account for CKD stage 2–3 as a baseline risk, the surgical stress as a competing cause, or the specific pharmacodynamic mechanism. The but-for query requires abducting this patient’s background from the factual evidence, then intervening to remove the NSAID and reading the counterfactual AKI probability. That is a Rung 3 computation. Pharmacovigilance gives you signal. The causal model gives you the answer the M&M committee needs.

Same model, three rungs, driven in conversation. The audit trail is the .bayes file, not a black box.

Is that all this simple model can answer?
AnyChat
A more sophisticated model can answer more complex questions. Still, even this intentionally simple model can answer more, like these:
  • Cohort-level policy. Would restricting this exposure hospital-wide reduce adverse events?
  • Dosing threshold. At what exposure level does the causal risk cross an actionable threshold?
  • Confounder audit. Which currently unmeasured factor would most change the attribution if added?
  • Comparative attribution. How does this patient's causal risk compare to a matched cohort?
  • Regulatory reporting. What is the population-attributable fraction for this exposure this quarter?
Same file, same audit trail, different questions asked.

Encode your clinical team’s pharmacovigilance reasoning into an SCM: which risk factors interact, which are legally material in your jurisdiction, and which are noise. The resulting model applies that reasoning consistently at scale, and produces defensible, patient-specific attributions your M&M committee and legal team can work with.

PharmacovigilanceAttribution.bayes

Structural Causal Model with explicit U-nodes for each observable. The U-nodes are essential, they are what makes counterfactual abduction possible: from the factual observation (this patient, this exposure, this outcome) the U-values are inferred, then a do-intervention is applied, and the counterfactual outcome is read. The probability of necessity, the formal version of ‘but-for cause’, is what the model computes.

PharmacovigilanceAttribution.bayes

This case study is a composite drawn from published pharmacoepidemiology, the study of how drugs affect populations, literature and pharmacovigilance causality assessment frameworks. Specific figures are representative. No individual patient or engagement is described. The Bayes Server models are working files: download, set evidence, and run inference.

The Deeper Trade

The model does not replace the expert who built it. It frees her from being the bottleneck for every routine version of this question, so she can spend her judgment on the cases that actually need it, and keep making the model better.

Tools I Work In
Modeling environments: Bayes Server, AgenaRisk, GeNIe/SMILE
Probabilistic programming & inference: Stan, PyMC, pgmpy
Discovery & graph tooling: DAGitty, plus R/Robyn for marketing-mix work

Tool-agnostic by design, the model is the asset; the environment follows the engagement.