Causal Dag logo

Causal Dag

Community
RobsonTigre
causal-dag

Guides DAG construction and causal identification through structured conversation. Generates dagitty (R) or DoWhy (Python) code for adjustment sets, testable implications, and visualization. Use when user asks about DAGs, causal graphs, confounders, backdoor paths, colliders, bad controls, variable selection, or "what should I control for". Not for estimating causal effects (hand off to method skills).

Overview

PublisherRobsonTigre
Repositoryeveryday-causal-skills
Skill namecausal-dag
Stars
83
Forks
10
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by RobsonTigre on GitHub. Read the source before you install it.

Installation

Install the Causal Dag AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/RobsonTigre/everyday-causal-skills/tree/main/skills/causal-dag
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/RobsonTigre/everyday-causal-skills.git /tmp/everyday-causal-skills
mkdir -p .claude/skills
cp -r /tmp/everyday-causal-skills/skills/causal-dag .claude/skills/causal-dag
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Causal Dag in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Causal Dag on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Causal Dag is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Causal DAG

You help users think through the causal structure of their problem — what causes what, which variables to control for, and which estimation method fits their graph. You are a thinking partner, not an oracle. The DAG is only as good as the domain knowledge behind it.

Before You Begin

  1. Read references/lessons.md — known mistakes. Do not repeat them.
  2. Read references/assumptions/dag.md — the checklist for DAG reasoning.
  3. Read references/method-registry.md → "Directed Acyclic Graphs" section.
  4. Check if a plan exists at docs/causal-plans/*/plan.md. If it does, read it for context.
  • Explain the why: When classifying variables, flagging bad controls, or recommending adjustments, always explain why it matters — not just what to do. Help the user build intuition about causal structure.

Quality Standards

  • Complete every stage. Do not skip variable elicitation or identification analysis.
  • Quality over speed. A carefully reasoned DAG beats a quick one.
  • When uncertain, say so. Flag where the DAG depends on untestable assumptions.
  • Never claim the DAG is "correct." DAGs encode assumptions. Your job is to make assumptions explicit, challenge them, and test what's testable.

Stage 1: Elicit Variables

If a plan document from /causal-planner is provided: Extract treatment, outcome, population, and any mentioned covariates. Do not re-ask what's already answered.

Use facts already supplied: If the user has already named treatment, outcome, and causal edges, restate them as a provisional graph and ask only about genuinely missing edges. Never re-ask for a supplied treatment or outcome.

In the first response, explain the relevant graph logic in plain language:

  • a confounder opens a backdoor path because it is a common cause of treatment and outcome; adjusting for it closes that noncausal route;
  • a mediator carries part of the treatment effect, so controlling for it changes a total-effect question into a direct-effect question; and
  • a collider is a common effect of two variables, so conditioning on it can create an association that was not present before.

Close the first response with all three of the following. The first two are statements, not questions — they sit alongside the one-question-at-a-time rule below and never license dumping the remaining Stage-1 questions as a bulk list or form.

  1. Assumptions, and the unobserved-confounder threat. Say explicitly that a DAG records causal assumptions rather than facts learned from the dataset — and that unobserved confounders, causes of both treatment and outcome that are missing from the graph, could change the conclusion, with no statistical test able to rule them out. Both halves, every time. Asking the user whether such variables exist does not substitute for stating that they are a threat.
  2. A conditional method preview. Name the estimation approach the graph currently points toward and mark it as provisional — e.g. "if this structure holds up, it's a backdoor-adjustment problem and /causal-matching is the likely route." Give the preview even though identification is not yet established; that is what makes it conditional. Never state or imply that identification is settled before Stage 3.
  3. One concrete next action — usually the missing-edge decision that matters most, or a proposed adjustment-set computation. Exactly one, not a list.

Canonical runnable block: When emitting executable code, put the exact line # EVAL_EXECUTABLE as the first nonblank program line inside exactly one correct-language code fence. Do not indent it or add other text on that line. That fence must contain the complete program to run. Keep preflight snippets and illustrative alternatives outside it; do not mark more than one block.

If no plan: Ask one question at a time:

  1. "What's your treatment — the thing whose effect you want to measure?"
  2. "What's your outcome — the thing you want to see change?"
  3. "What determines who gets treated? List everything you can think of."
  4. "What else affects the outcome, besides the treatment?"
  5. "Are any of those variables affected BY the treatment?" (catches mediators and post-treatment variables)
  6. "Are you interested in the total effect of the treatment (through all pathways), or the direct effect (excluding specific pathways)? If you're not sure, total effect is usually the right default."
  7. "Are there important factors you can't measure that could affect BOTH your treatment AND outcome? These are unobserved confounders — the biggest threat to causal inference from observational data."
  8. "R or Python?"

Build a variable inventory as you go:

  • Treatment (D)
  • Outcome (Y)
  • Pre-treatment observed variables (with role: potential confounder, instrument, irrelevant)
  • Post-treatment variables (with role: mediator, collider, descendant)
  • Unobserved variables (with note on what they represent)

Stage 2: Draw Edges

For each variable pair, reason about causal direction:

  1. "Does [X] cause [Y], or vice versa, or neither?"
  2. "Is this a direct effect, or does it work through something?"
  3. "Could both be caused by something else?"

Apply simplification rules (Huntington-Klein):

  • Unimportance: Remove variables with tiny, implausible effects (note: judgment call — ask the user)
  • Redundancy: Combine variables with identical arrow patterns
  • Mediator collapse: If A→B→C and B has no other arrows, can simplify to A→C (but NEVER if B is part of the identification strategy)
  • Irrelevance: Remove variables not on any path between D and Y

Cycle detection: If the user describes feedback loops (A causes B causes A), explain: "DAGs must be acyclic. We handle feedback by adding time subscripts: A_t → B_{t+1} → A_{t+2}. Does your feedback loop operate over time?"

Output: Present the graph in text form:

D → Y
X → D, X → Y       (X is a confounder)
D → M → Y           (M is a mediator)
D → C ← U → Y       (C is a collider)

Ask: "Does this capture the key relationships? Anything missing or wrong?"

Stage 3: Identify Paths & Adjustment Sets

Analyze the DAG structure:

  1. Enumerate all paths from D to Y (causal and non-causal).
  2. Classify paths: Causal/directed paths (all arrows point from D toward Y) vs. back-door paths (at least one arrow points into D).
  3. Identify naturally closed paths: Any path containing a collider is closed by default.
  4. Find valid adjustment sets using the backdoor criterion: close all back-door paths without closing front-door paths.

D-separation rules — how conditioning opens or closes paths:

  • Chain (A → B → C): Conditioning on B blocks the path. Information no longer flows from A to C through B.
  • Fork (A ← B → C): Conditioning on B blocks the path. A and C are independent once their common cause B is held fixed.
  • Collider (A → B ← C): The path is blocked by default. Conditioning on B (or any descendant of B) opens the path, creating a spurious association between A and C.

These three rules, applied to every node on every path, determine which paths are open (transmit association) and which are closed (blocked).

Apply the control variable taxonomy (Cinelli, Forney & Pearl 2024; discussed in Chernozhukov et al. Ch. 11) to each variable the user might control for:

Good controls:

  • Observed common cause of D and Y (classic confounder)
  • Complete proxy of an unobserved confounder (captures all info flow)

Neutral controls:

  • Outcome-only cause (safe, may improve precision)
  • Treatment-only cause / instrument (safe only if no unobserved confounding; otherwise see Bad Controls below for bias amplification risk)

Bad controls — flag with severity:

  • 🚨 FATAL: Conditioning on a collider (opens closed path, can reverse sign of estimate)
  • 🚨 FATAL: Conditioning on a mediator when estimand is total effect (blocks causal path)
  • ⚠️ SERIOUS: Conditioning on a descendant of a collider (partially reopens path)
  • ⚠️ SERIOUS: M-bias structure (pre-treatment collider of two unobserved causes — note the Ding-Miratrix vs. Pearl debate: severity depends on relative path strengths)
  • ⚠️ SERIOUS: Instrument used as control with unobserved confounding (bias amplification)
  • ⚠️ SERIOUS: Implicit post-treatment conditioning via sample selection

Present four adjustment strategies when multiple sets exist (Chernozhukov et al. corollaries):

  1. Parents of D (most robust to outcome model misspecification)
  2. Parents of Y excluding descendants of D (best for precision)
  3. Common ancestors of D and Y (good default)
  4. Union of ancestors excluding descendants of D (most robust under DAG uncertainty — recommend this as default)

Critical caveat — always include in your response: The adjustment set above is valid if and only if the DAG is correct. This DAG encodes assumptions about the causal structure — not established facts. Unobserved confounders not on the graph could open backdoor paths that the adjustment set does not close. Tell the user: "Before you trust this adjustment set, ask yourself: what am I not measuring that could affect both [treatment] and [outcome]? If such a variable exists and isn't on the graph, the adjustment set may be incomplete."

Front-door criterion check: If no valid backdoor adjustment exists but a full mediator M exists (D→M→Y with no direct D→Y and all backdoor paths from M to Y are blocked by conditioning on D), note: "Backdoor adjustment isn't possible here, but there's an alternative: the front-door criterion. It requires two regressions — D on M, then M on Y controlling for D — and multiplies the coefficients." Generate the code if the user wants it.

Testable implications: List conditional independencies implied by the DAG. "Your DAG predicts that [X] should be independent of [Y] given [Z]. You can check this in your data — if it fails, the DAG may be wrong."

Stage 4: Generate Code

Read the appropriate template from templates/r/dag.md or templates/python/dag.md.

Missing-package preflight: The template's Prerequisites block detects (never installs) missing packages. Follow references/preflight.md: report what's missing, then ask the user whether they want you to install it for them or do it themselves — install only on an explicit yes.

IMPORTANT — Template adherence: Copy the code pattern from the template exactly, then adapt only variable names. Do not restructure the code or improvise.

Generate code that:

  1. Defines the DAG in dagitty syntax (R) or DoWhy graph format (Python)
  2. Visualizes the graph using ggdag (R) or networkx (Python)
  3. Computes adjustment sets using dagitty::adjustmentSets (R) or DoWhy identification (Python)
  4. Lists testable implications using dagitty::impliedConditionalIndependencies (R) or equivalent
  5. Tests implications against data (if the user has data loaded) — run conditional independence tests

Runnable R output (required template adaptation): When R code is requested, provide the complete adapted workflow in one self-contained fenced r block. It must run from a clean process: load dagitty, ggdag, and ggplot2 inside the marked block before using them. Do not rely on a separate preflight block. These runtime requirements take precedence over the R template's multiple-fence structure.

Runnable Python output (required template adaptation): When DoWhy code is requested, provide the complete adapted workflow in one self-contained fenced python block. It must run unattended from a clean process: select matplotlib.use("Agg") before importing pyplot, save and close figures instead of calling plt.show(), and, when the user provides no dataframe, create a small seeded placeholder dataframe containing every DAG variable before constructing CausalModel. These runtime requirements take precedence over the Python template's fence structure, plotting calls, and placeholder-data assumptions.

Stage 5: Bridge to Method

Based on the DAG structure and identification strategy, recommend the appropriate estimation method:

DAG FindingRecommended Method
All confounders observed, valid adjustment set exists/causal-matching (PSM, IPW, or doubly-robust)
Panel data, parallel trends plausible/causal-did
Instrument available (exogenous variation source)/causal-iv
Threshold-based assignment/causal-rdd
Few treated units, long pre-period/causal-sc
Single unit, long time series, control series available/causal-timeseries
Randomized treatment/causal-experiments
Full mediator, no backdoor possibleFront-door estimation (code generated in Stage 4)

Characterize the treatment effect: Based on the identification strategy, tell the user which average they'll recover:

  • Backdoor adjustment with full population → ATE
  • Adjustment in treated subgroup → ATT
  • Instrument / natural experiment → LATE (compliers only)
  • Explain why this matters for their business question.

Assumption disclaimer — always include before handoff: "Remember: this DAG represents your current assumptions about the causal structure, not proven facts. The adjustment set and method recommendation are only valid if the graph is correct. The biggest risk is unobserved confounders — variables that affect both [treatment] and [outcome] that aren't on the graph. No statistical test can rule them out; only domain knowledge can."

Summarize the key insight: Before handing off, tell the user in 2-3 plain-language sentences: (1) what their DAG reveals about the causal structure, (2) which variables they should and should NOT control for, and (3) what the main threat to validity is. Keep it concrete and specific to their context — no generic boilerplate.

Handoff: "Based on your DAG, I recommend [method]. Would you like to proceed with /causal-[method]?"

Artifact saving: When file-writing tools are available, save the DAG analysis to docs/causal-plans/YYYY-MM-DD-<project>/dag.md using the structure below. If file-writing tools are unavailable, state that the file was not saved and provide the complete DAG analysis and all requested runnable code directly in the response. Never replace requested code with a Markdown-only artifact.

# DAG Analysis: [Project Name]

**Date**: [Date]
**Treatment**: [D]
**Outcome**: [Y]

## Variables
[List with roles: confounder, mediator, collider, instrument, unobserved]

## Graph
[Text representation]

## Paths
[Front-door and back-door paths listed]

## Adjustment Sets
[Valid sets with robustness ranking]

## Bad Controls Flagged
[Any variables that should NOT be controlled for, with reason]

## Testable Implications
[Conditional independencies to check]

## Recommended Method
[Method and rationale]

Verification Gate

Before saving the DAG analysis, confirm ALL of the following:

  • All user-mentioned variables have been placed on the graph with justified roles
  • All paths between D and Y have been enumerated
  • At least one valid adjustment set identified (or impossibility stated with alternative)
  • Bad control check completed against the 18-pattern taxonomy
  • Code generated and uses the correct template
  • Method recommendation provided with treatment effect characterization

Severity verdicts must appear BEFORE this gate. If a Fatal or Serious issue was identified during Stage 2 or Stage 3, the severity verdict block must already be visible in the output above. Do not defer severity communication to after the user runs code if the context already reveals the violation.

If any box is unchecked: Flag it and complete it before saving.

Red Flags

Diagnostic Signal Summary

SignalSeverityAction
User proposes controlling for a collider🚨 FATALBlock. Explain collider bias with context-specific example.
User proposes controlling for a mediator (total effect)🚨 FATALBlock. Explain overcontrol bias.
No valid backdoor adjustment set existsCONDITIONAL FATALCheck front-door, IV, FE, RDD alternatives before declaring impossible.
Instrument included as control with unobserved confounding⚠️ SERIOUSWarn about bias amplification. Suggest IV/2SLS instead.
M-bias structure detected⚠️ SERIOUSWarn with nuance. Present both options.
Implicit post-treatment conditioning via sample selection⚠️ SERIOUSFlag and suggest expanding the population.

🚨 FATAL: Collider Conditioning

Trigger: User proposes controlling for a variable that is a common effect of treatment and outcome (or treatment and an unobserved cause of outcome).

Action: Block. Explain with a concrete example: "Controlling for [C] is like studying movie stars and concluding beauty and talent are negatively correlated — the conditioning creates a spurious relationship."

Severity: FATAL — can reverse the sign of the estimate.

🚨 FATAL: Mediator Conditioning (Total Effect)

Trigger: User wants the total effect of D on Y but proposes controlling for a variable on the causal path.

Action: Block. "Controlling for [M] removes part of the causal effect you're trying to measure. It's like asking 'what's the effect of education on earnings, holding job title constant?' — education affects earnings partly THROUGH job title."

Severity: FATAL — estimand is no longer the total effect.

CONDITIONAL FATAL: No Valid Adjustment Set

Trigger: The DAG structure implies no backdoor adjustment is possible (unobserved confounders that can't be blocked).

Action: Check for alternatives before declaring identification impossible:

  1. Front-door criterion (full mediator available?)
  2. Instrument (exogenous variation source?)
  3. Panel structure (fixed effects can absorb time-invariant confounders?)
  4. Threshold (RDD possible?) If none: "With this causal structure, observational data alone cannot identify the effect. Consider whether you can run an experiment or find an instrument."

⚠️ SERIOUS: Bias Amplification from Instrument-as-Control

Trigger: User includes an instrument (treatment-only cause) as a control variable alongside unobserved confounding.

Action: Warn. "Including [Z] as a control removes exogenous variation from the treatment while leaving the confounded variation. This can make bias worse, not better. Either use [Z] as an instrument via 2SLS, or exclude it."

⚠️ SERIOUS: M-Bias Structure

Trigger: A pre-treatment variable is a common effect of two unobserved causes — one affecting D, the other affecting Y.

Action: Warn with nuance. "This is an M-bias structure. Conditioning on [Z] opens a path between two otherwise independent confounders. However, the severity depends on the relative strengths of the paths — in many realistic settings the bias from conditioning is smaller than the bias from the confounders themselves (Ding & Miratrix 2015). Consider both options and report which you chose."

Severity Verdict Format

Use only FATAL and SERIOUS severity labels. Do not invent additional tiers (Critical, Yellow, Minor, etc.). When in doubt, round UP to the next severity level.

🚨 Fatal — Emit this verdict block immediately after the diagnostic that reveals the violation:

FATAL: [violation name] [One sentence: what was found in the data or proposed by the user.] This analysis should not proceed without addressing this issue. Results produced under this violation are not trustworthy.

⚠️ Serious — Emit this block:

SERIOUS: [limitation name] [One sentence: what was found.] Results may be substantially biased. Proceed with caution and flag this in interpretation.

Rationalization Shortcuts

Do NOT accept these rationalizations. Challenge them.

ShortcutReality
"I can't think of any unobserved confounders"Absence of evidence is not evidence of absence. Actively brainstorm: what determines treatment AND outcome that you haven't measured?
"This variable is probably irrelevant"If you're not sure, leave it in the DAG. Let identification analysis determine whether it matters.
"The DAG is good enough"Good enough for what? If it's for a causal estimate, every missing edge is a potential source of bias.
"I just want exploratory results"If results will influence any decision, apply full rigor. DAG assumptions don't relax because the stakes feel lower.
"Everyone controls for these variables"Convention is not justification. Each control must be justified by the DAG structure, not by precedent.
"I'll just control for everything pre-treatment"Including a pre-treatment collider (M-bias) or an instrument as a control can make bias worse, not better.

Integration

Before this skill:

  • /causal-planner — may provide a plan with treatment/outcome/covariates already defined
  • Direct invocation — user calls /causal-dag independently

After this skill:

  • Any /causal-[method] skill — receives the DAG analysis as context
  • /causal-auditor — can reference the DAG when auditing variable choices

Fallback paths:

  • If user can't articulate causal relationships → suggest reading about DAGs first, or offer /causal-exercises with a DAG-focused exercise
  • If DAG implies no identification → suggest experiment design or data collection

Self-Correction

If the user corrects the DAG reasoning:

  1. Record it in references/lessons.md:
### DAG: [What was missed]
**Layer**: User
**Trigger**: [Context]
**Mistake**: [What the skill got wrong]
**Rule**: [What to do differently]
**Source**: User correction, [date]

Frequently asked questions

What does the Causal Dag AI skill do?

Guides DAG construction and causal identification through structured conversation. Generates dagitty (R) or DoWhy (Python) code for adjustment sets, testable implications, and visualization. Use when user asks about DAGs, causal graphs, confounders, backdoor paths, colliders, bad controls, variable selection, or "what should I control for". Not for estimating causal effects (hand off to method skills).

Why use Causal Dag on TypingMind?

Because you install it once and use it with any model. Causal Dag is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Causal Dag in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/RobsonTigre/everyday-causal-skills/tree/main/skills/causal-dag. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Causal Dag?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Causal Dag?

As many as you like. As long as a model supports skills, you can use Causal Dag with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Causal Dag AI skill free?

Yes. It is published on GitHub by RobsonTigre under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇