Causal Reasoning

advanced20 mincausal-reasoning.ts

Churn went up after a redesign. You want to predict the effect of rolling it back and see the likely root causes.

What it shows

  • Model causes, outcomes and confounders with CausalGraphBuilder
  • Hand the graph to CausalReasoner through its graph store
  • Predict effects, explain an outcome, generate hypotheses

The code

causal-reasoning.ts
import {
  CausalGraphBuilder,
  CausalReasoner,
  InMemoryCausalGraphStore,
  createLLMBackend,
} from '@cogitator-ai/core';

const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) throw new Error('Set GOOGLE_API_KEY');

const graph = CausalGraphBuilder.create('user-retention')
  .treatment('redesign', 'UI Redesign')
  .causes('ux-complexity', { strength: 0.8, confidence: 0.9, mechanism: 'new navigation patterns' })
  .causes('page-load-time', { strength: 0.6, confidence: 0.7, mechanism: 'heavier assets' })
  .variable('ux-complexity', 'UX Complexity')
  .causes('user-frustration', { strength: 0.7, confidence: 0.85 })
  .variable('page-load-time', 'Page Load Time')
  .causes('bounce-rate', { strength: 0.8, confidence: 0.9 })
  .variable('user-frustration', 'User Frustration')
  .causes('churn', { strength: 0.9, confidence: 0.95 })
  .variable('bounce-rate', 'Bounce Rate')
  .causes('churn', { strength: 0.5, confidence: 0.8 })
  .outcome('churn', 'User Churn')
  .confounder('seasonality', 'Seasonality')
  .confounds('churn', { strength: 0.3, confidence: 0.5 })
  .build();

for (const node of graph.getNodes()) {
  const children = graph.getChildren(node.id).map((child) => child.id);
  console.log(`[${node.variableType}] ${node.name}${children.length ? ` -> ${children.join(', ')}` : ''}`);
}

const agentId = 'product-analytics';
const graphStore = new InMemoryCausalGraphStore();
await graphStore.save({ ...graph.toData(), metadata: { agentId } });

const reasoner = new CausalReasoner({
  llmBackend: createLLMBackend('google', { providers: { google: { apiKey } } }),
  model: 'gemini-3.8-flash',
  graphStore,
  config: { enableLLMDiscovery: true, enableSafetyChecks: true },
});
await reasoner.loadGraph(agentId);

const prediction = await reasoner.predictEffect('Roll back the UI redesign', agentId, {
  observedVariables: { churn: 0.15, 'bounce-rate': 0.35 },
});
console.log(`Prediction (${prediction.confidence.toFixed(2)}): ${prediction.reasoning}`);
for (const effect of prediction.effects) {
  console.log(`  ${effect.variable}: ${effect.expectedValue} — ${effect.mechanism}`);
}

const explanation = await reasoner.explainCause('churn', 0.15, agentId, {
  observedVariables: { 'ux-complexity': 0.8, 'page-load-time': 3.2, 'bounce-rate': 0.35 },
});
console.log(explanation.summary);
for (const cause of explanation.rootCauses) {
  console.log(`  root cause ${cause.variable} (${cause.contribution.toFixed(2)}): ${cause.suggestedIntervention ?? ''}`);
}
for (const counterfactual of explanation.counterfactuals) {
  console.log(`  if "${counterfactual.change}" — would prevent: ${counterfactual.wouldPrevent}`);
}

const hypotheses = await reasoner.generateHypotheses(agentId, 'reduce user churn');
for (const hypothesis of hypotheses.slice(0, 3)) {
  console.log(`  hypothesis: ${hypothesis.cause} -> ${hypothesis.effect} (${hypothesis.relationType})`);
}

Run it

install · bash
pnpm add @cogitator-ai/core
EnvironmentGOOGLE_API_KEY
run · bash
GOOGLE_API_KEY=your-key npx tsx causal-reasoning.ts

Or run the full example from a clone of the repository (keys in .env):

repository · bash
npx tsx examples/core/12-causal-reasoning.ts

Learn more