Very Simple CAIS Skill
Given a CSV dataset, a dataset description, and a natural-language causal query: select the right causal method, run the appropriate tools, and return a numeric ATE estimate with reasoning.
When to Use
Use this skill when the user provides a tabular dataset (CSV) and a causal question such as "What is the effect of X on Y?" Do not use for pure correlation analysis, prediction tasks, or causal graph discovery.
Tools Available
All tools live at ~/.claude/skills/adaptive_causal_estimate/tools/. Always call them via Bash:
python - <<'PYEOF'
import os, sys, json
sys.path.insert(0, os.path.expanduser("~/.claude/skills/adaptive_causal_estimate"))
from tools.data import analyze_dataset
result = analyze_dataset("/path/to/data.csv")
print(json.dumps(result, default=str))
PYEOF
| Tool |
Function |
When to use |
tools.data |
analyze_dataset(df_path) |
Always call first — reveals column types, time/id cols, panel structure, treatment/outcome candidates |
tools.diagnostics |
check_covariate_balance(df_path, treatment, covariates) |
Before choosing matching/OLS on observational data — check SMD |
tools.diagnostics |
test_parallel_trends(df_path, outcome, treatment_group_col, time_var, treatment_period) |
Before committing to DiD |
tools.diagnostics |
test_instrument_strength(df_path, treatment, instrument, covariates) |
Before committing to IV — check F ≥ 10 |
tools.diagnostics |
check_overlap(df_path, treatment, covariates) |
Before choosing PSM vs IPW |
tools.estimators |
estimate_ols(df_path, treatment, outcome, covariates) |
RCT with covariates, or observational fallback |
tools.estimators |
estimate_diff_in_means(df_path, treatment, outcome) |
Pure RCT without covariates |
tools.estimators |
estimate_did(df_path, treatment_group_col, outcome, time_var, treatment_period, group_var, covariates) |
Panel data with treatment timing |
tools.estimators |
estimate_iv(df_path, treatment, outcome, instrument, covariates) |
Valid instrument exists |
tools.estimators |
estimate_rdd(df_path, outcome, running_var, cutoff, bandwidth, covariates) |
Running variable with threshold |
tools.estimators |
estimate_psm(df_path, treatment, outcome, covariates, n_bootstraps) |
Observational, binary treatment, good overlap |
Rule: always call at least one estimator tool. Do not compute ATE by hand.
Domain Knowledge: Method Selection
Step 1 — RCT check (do this first, before any tool call)
Scan the dataset description and query for: randomized, randomised, RCT, randomized controlled trial, randomized study, randomly assigned, random assignment.
- If any keyword matches →
is_rct = True
- When
is_rct = True: matching, PSM, and IPW are forbidden. Do not run them, do not consider them. OLS with covariates is the correct choice (or difference-in-means if no covariates). Random assignment already balances covariates — applying matching on top is wrong and will produce an incorrect selected_method.
Step 2 — Study design identification
Call analyze_dataset to inspect column structure, then apply this decision logic:
| Signal |
Method |
is_rct = True, no non-compliance instrument |
OLS (covariates available) or Difference-in-Means (no covariates) |
is_rct = True, instrument for non-compliance exists |
IV (encouragement design, LATE) |
| Running variable + threshold in description or data |
RDD |
Panel data (panel_detected=True) + treatment timing |
DiD |
| Instrument column mentioned in description (policy change, lottery, geography) |
IV |
| Observational, binary treatment, covariates available |
Matching or OLS — check overlap first |
| No strong identification strategy |
OLS as fallback |
Step 3 — Observational data: matching vs OLS
This is the most common error source. Use these rules:
- Call
check_covariate_balance first. If max_smd < 0.1 (already well-balanced), prefer OLS — matching adds noise without benefit.
- Call
check_overlap. If overlap_score ≥ 0.8, matching is viable. If overlap_score < 0.5, use IPW or OLS instead.
- Matching is appropriate when: selection bias is strong (high SMD pre-matching), treatment is binary, and overlap is good.
- OLS is appropriate when: confounders are few and well-measured, or when the question asks for ATE (not ATT).
- Never choose matching just because the dataset has covariates. Covariates alone do not justify matching over OLS.
Domain Knowledge: Method Assumptions
OLS
- Assumes no unmeasured confounding given covariates (conditional ignorability)
- Use HC1 robust standard errors (already done by the tool)
- Valid for both RCT (precision gain) and observational (with strong ignorability assumption)
Difference-in-Means
- Only for pure RCTs with no covariate adjustment needed
- Equivalent to OLS without covariates
DiD
- Requires: panel structure (unit × time), binary treatment group indicator, known treatment timing
- Key assumption: parallel trends — treated and control groups would have followed the same trend absent treatment
- Always run
test_parallel_trends if ≥ 3 pre-treatment periods exist
- Treatment timing = first period when treated group received treatment
IV / 2SLS
- Instrument must satisfy: (1) relevance — correlated with treatment (F ≥ 10), (2) exclusion restriction — only affects outcome through treatment, (3) exogeneity — uncorrelated with unmeasured confounders
- Always run
test_instrument_strength — if F < 10, instrument is weak, IV estimate is biased, fall back to OLS
- IV estimates LATE (Local ATE), not ATE — only for compliers
RDD
- Running variable must exist: a continuous variable where crossing a threshold determines treatment
- Estimate is local — valid only near the cutoff
- Units should not be able to precisely manipulate the running variable
- Bandwidth choice matters — try default (10% of range), then check
n_in_bandwidth is adequate (≥ 20)
Matching / PSM
- Estimates ATT (effect on treated), not ATE
- Requires: binary treatment, observed covariates capture all confounding (no unmeasured confounders)
- Check overlap before running: if overlap is poor, PSM matches on poorly supported regions and estimates are unreliable
- Post-matching balance:
max_smd_post < 0.1 is excellent, < 0.25 acceptable
- Forbidden when
is_rct = True
Domain Knowledge: Common Pitfalls
- RCT + matching error: Dataset says "randomized study" → agent incorrectly runs PSM because covariates exist and PSM converges well. Fix:
is_rct = True immediately eliminates matching as a candidate.
- IV over-selection: Wage/education datasets often have a plausible IV (father's education, quarter of birth). This is methodologically reasonable but benchmark labels may use OLS. When both IV and OLS are defensible, prefer the method better supported by the description.
- DiD without panel: DiD requires multiple observations per unit over time. A single cross-section with a "before/after" question is not DiD.
- Matching without overlap check: Running PSM without
check_overlap first risks matching on a region of no common support. Always check overlap before matching.
selected_method field must match the estimator tool actually called: if you called estimate_ols, write "ols"; if you called estimate_psm, write "matching". Never write the method you considered but rejected.
Output Format
Respond with a JSON object:
{
"selected_method": "<ols|matching|iv|did|rdd>",
"ate": <numeric estimate>,
"reasoning": "<method choice rationale + key assumption check result>"
}
selected_method must be one of: ols, matching, iv, did, rdd.
1---2name: adaptive-causal-estimate3description: Very Simple CAIS Skill4---5# Very Simple CAIS Skill67Given a CSV dataset, a dataset description, and a natural-language causal query: select the right causal method, run the appropriate tools, and return a numeric ATE estimate with reasoning.89## When to Use1011Use this skill when the user provides a tabular dataset (CSV) and a causal question such as "What is the effect of X on Y?" Do **not** use for pure correlation analysis, prediction tasks, or causal graph discovery.1213---1415## Tools Available1617All tools live at `~/.claude/skills/adaptive_causal_estimate/tools/`. Always call them via Bash:1819```bash20python - <<'PYEOF'21import os, sys, json22sys.path.insert(0, os.path.expanduser("~/.claude/skills/adaptive_causal_estimate"))23from tools.data import analyze_dataset24result = analyze_dataset("/path/to/data.csv")25print(json.dumps(result, default=str))26PYEOF27```2829| Tool | Function | When to use |30|---|---|---|31| `tools.data` | `analyze_dataset(df_path)` | Always call first — reveals column types, time/id cols, panel structure, treatment/outcome candidates |32| `tools.diagnostics` | `check_covariate_balance(df_path, treatment, covariates)` | Before choosing matching/OLS on observational data — check SMD |33| `tools.diagnostics` | `test_parallel_trends(df_path, outcome, treatment_group_col, time_var, treatment_period)` | Before committing to DiD |34| `tools.diagnostics` | `test_instrument_strength(df_path, treatment, instrument, covariates)` | Before committing to IV — check F ≥ 10 |35| `tools.diagnostics` | `check_overlap(df_path, treatment, covariates)` | Before choosing PSM vs IPW |36| `tools.estimators` | `estimate_ols(df_path, treatment, outcome, covariates)` | RCT with covariates, or observational fallback |37| `tools.estimators` | `estimate_diff_in_means(df_path, treatment, outcome)` | Pure RCT without covariates |38| `tools.estimators` | `estimate_did(df_path, treatment_group_col, outcome, time_var, treatment_period, group_var, covariates)` | Panel data with treatment timing |39| `tools.estimators` | `estimate_iv(df_path, treatment, outcome, instrument, covariates)` | Valid instrument exists |40| `tools.estimators` | `estimate_rdd(df_path, outcome, running_var, cutoff, bandwidth, covariates)` | Running variable with threshold |41| `tools.estimators` | `estimate_psm(df_path, treatment, outcome, covariates, n_bootstraps)` | Observational, binary treatment, good overlap |4243**Rule: always call at least one estimator tool. Do not compute ATE by hand.**4445---4647## Domain Knowledge: Method Selection4849### Step 1 — RCT check (do this first, before any tool call)5051Scan the dataset description and query for: `randomized`, `randomised`, `RCT`, `randomized controlled trial`, `randomized study`, `randomly assigned`, `random assignment`.5253- If any keyword matches → `is_rct = True`54- **When `is_rct = True`: matching, PSM, and IPW are forbidden. Do not run them, do not consider them.** OLS with covariates is the correct choice (or difference-in-means if no covariates). Random assignment already balances covariates — applying matching on top is wrong and will produce an incorrect `selected_method`.5556### Step 2 — Study design identification5758Call `analyze_dataset` to inspect column structure, then apply this decision logic:5960| Signal | Method |61|---|---|62| `is_rct = True`, no non-compliance instrument | **OLS** (covariates available) or **Difference-in-Means** (no covariates) |63| `is_rct = True`, instrument for non-compliance exists | **IV** (encouragement design, LATE) |64| Running variable + threshold in description or data | **RDD** |65| Panel data (`panel_detected=True`) + treatment timing | **DiD** |66| Instrument column mentioned in description (policy change, lottery, geography) | **IV** |67| Observational, binary treatment, covariates available | **Matching** or **OLS** — check overlap first |68| No strong identification strategy | **OLS** as fallback |6970### Step 3 — Observational data: matching vs OLS7172This is the most common error source. Use these rules:7374- Call `check_covariate_balance` first. If `max_smd < 0.1` (already well-balanced), **prefer OLS** — matching adds noise without benefit.75- Call `check_overlap`. If `overlap_score ≥ 0.8`, matching is viable. If `overlap_score < 0.5`, use IPW or OLS instead.76- Matching is appropriate when: selection bias is strong (high SMD pre-matching), treatment is binary, and overlap is good.77- OLS is appropriate when: confounders are few and well-measured, or when the question asks for ATE (not ATT).78- **Never choose matching just because the dataset has covariates.** Covariates alone do not justify matching over OLS.7980---8182## Domain Knowledge: Method Assumptions8384### OLS85- Assumes no unmeasured confounding given covariates (conditional ignorability)86- Use HC1 robust standard errors (already done by the tool)87- Valid for both RCT (precision gain) and observational (with strong ignorability assumption)8889### Difference-in-Means90- Only for pure RCTs with no covariate adjustment needed91- Equivalent to OLS without covariates9293### DiD94- Requires: panel structure (unit × time), binary treatment group indicator, known treatment timing95- Key assumption: parallel trends — treated and control groups would have followed the same trend absent treatment96- Always run `test_parallel_trends` if ≥ 3 pre-treatment periods exist97- Treatment timing = first period when treated group received treatment9899### IV / 2SLS100- Instrument must satisfy: (1) relevance — correlated with treatment (F ≥ 10), (2) exclusion restriction — only affects outcome through treatment, (3) exogeneity — uncorrelated with unmeasured confounders101- Always run `test_instrument_strength` — if F < 10, instrument is weak, IV estimate is biased, fall back to OLS102- IV estimates LATE (Local ATE), not ATE — only for compliers103104### RDD105- Running variable must exist: a continuous variable where crossing a threshold determines treatment106- Estimate is local — valid only near the cutoff107- Units should not be able to precisely manipulate the running variable108- Bandwidth choice matters — try default (10% of range), then check `n_in_bandwidth` is adequate (≥ 20)109110### Matching / PSM111- Estimates ATT (effect on treated), not ATE112- Requires: binary treatment, observed covariates capture all confounding (no unmeasured confounders)113- Check overlap before running: if overlap is poor, PSM matches on poorly supported regions and estimates are unreliable114- Post-matching balance: `max_smd_post < 0.1` is excellent, `< 0.25` acceptable115- **Forbidden when `is_rct = True`**116117---118119## Domain Knowledge: Common Pitfalls120121- **RCT + matching error**: Dataset says "randomized study" → agent incorrectly runs PSM because covariates exist and PSM converges well. Fix: `is_rct = True` immediately eliminates matching as a candidate.122- **IV over-selection**: Wage/education datasets often have a plausible IV (father's education, quarter of birth). This is methodologically reasonable but benchmark labels may use OLS. When both IV and OLS are defensible, prefer the method better supported by the description.123- **DiD without panel**: DiD requires multiple observations per unit over time. A single cross-section with a "before/after" question is not DiD.124- **Matching without overlap check**: Running PSM without `check_overlap` first risks matching on a region of no common support. Always check overlap before matching.125- **`selected_method` field must match the estimator tool actually called**: if you called `estimate_ols`, write `"ols"`; if you called `estimate_psm`, write `"matching"`. Never write the method you considered but rejected.126127---128129## Output Format130131Respond with a JSON object:132133```json134{135 "selected_method": "<ols|matching|iv|did|rdd>",136 "ate": <numeric estimate>,137 "reasoning": "<method choice rationale + key assumption check result>"138}139```140141`selected_method` must be one of: `ols`, `matching`, `iv`, `did`, `rdd`.