StatsPAI is one import statspai as sp over 1,500+ registered functions for
causal inference and applied econometrics, numerically aligned with Stata / R
reference implementations, with self-describing schemas and result objects that
export to LaTeX / Word / Excel / BibTeX. This skill drives it through the
canonical pipeline of an applied empirical paper, in one of three modes
(default applied econ; epidemiology; ML-causal), and leaves paper-ready
artifacts on disk at every step.
- Source: https://github.com/brycewang-stanford/StatsPAI
- Install:
pip install "statspai[fixest,plotting]"(default pipeline); addneuralfor Dragonnet / TARNet / CEVAE,textfor text-as-treatment. The bare install cannot runsp.feols(anyy ~ x | feregression) or make figures — seereferences/operating-loop.mdfor the extras matrix. - Verified:
validate_api_claims.pychecks this skill against the installed package (statspai skill validate). Everysp.*name resolves, everysp.*(...)call in a code block binds to the real signature (for a function that takes**kwargs, to its agent schema or forwarding target), and the result attributes on the gate's smoke-fit list exist. With--runthe pipeline files are also executed end to end on synthetic data, which is what catches a call that binds but is rejected at run time. There is no version stamp to go stale. - Is this copy current? An installed skill is a plain copy and does not
follow
pip install -U statspai.statspai skill statuscompares it with the skill packaged in the installed version; if it reportsstale, say so and suggeststatspai skill install --forcebefore relying on a call shape written here. - Paper: Wang & Rozelle (2026), Journal of Open Source Software 11(125), 10604, https://doi.org/10.21105/joss.10604.
Operating loop (every request)
- Route the mode first from the user's words — default applied econ,
Mode A epi, Mode B ML-causal, or an export-only path. Do not run the whole
paper pipeline for "make Table 1" or "export this regression". A request
for one estimate, one check or one table takes the short path in
references/quick-path.md. - Freeze the contract before estimating:
y, treatment / exposure, unit / time ids, estimand, design, required artifacts, install extras. Infer a missing field only when the column names make it obvious; otherwise return a short blocking checklist instead of inventing columns. - Pick the estimator with the tables, not from memory:
sp.route('did', design='staggered', timing_random='no', covariates='none')(alsoiv,rd,matching,ml_causal,qte,dynamic_panel) returns the registered call, an example, why, and the assumptions it adds;sp.decision_guide(family)lists the questions.sp.recommend(df, ...)routes from the data itself. - Start from the smallest verified call shape: the skeleton in
references/verified-skeleton.md, then the section snippet. For anything unfamiliar,sp.describe_function(name)/sp.function_schema(name)before writing code;sp.search_functions("weak instrument robust CI")to find the name. - Widen one block at a time: data contract → plan → diagnostic figure →
main estimate → robustness / export. After each block read the result's
violations(),next_steps(),degradationsandmodel_infobefore passing it downstream. - Gate the answer on artifacts: the final message lists the files produced, the identifying assumption, the estimator class, and any failed or skipped gate. Never say "paper-ready" when an export or a required diagnostic did not actually run.
- Turn failures into bounded corrections: a
StatsPAIErrorcarriescode,recovery_hint,diagnosticsandalternative_functions; fix the smallest wrong rule and continue from the last verified artifact.
Pipeline map (default mode)
Paper section Step StatsPAI moves
─────────────────────────── ───── ────────────────────────────────────────────
Pre-analysis plan −1 sp.power(...) + freeze the IdentificationPlan
§1 Data 0 data contract + sample-construction log
§1.1 Table 1 1 sp.sumstats · sp.mean_comparison · sp.balance_table
§2 Empirical strategy 2 equation + assumption + sp.causal_question(...).identify()
(LLM-DAG addendum) 2.5 sp.llm_dag_propose · validate · constrained
§3 Identification graphics 3 event study · first-stage F · McCrary · love plot
§4 Main results (Table 2) 4 progressive controls + FE (sp.regtable / sp.causal)
§5 Heterogeneity (Table 3) 5 sp.subgroup_analysis · sp.continuous_did · CATE
§6 Mechanisms 6 sp.mediation · sp.decompose
§7 Robustness gauntlet 7 placebo · Oster · honest_did · E-value · Conley · spec_curve
§8 Replication package 8 sp.collect / sp.paper_tables · reproducibility stamp
Step-by-step code: references/pipeline-econ.md. Mode A:
references/pipeline-epi.md. Mode B: references/pipeline-ml-causal.md.
Hard rules (read before writing code)
- Estimand first.
sp.causal_question(...).identify()(orsp.route) decides DID vs RD vs IV before any estimate, and the identifying assumption is written down where a referee will read it. y ~ x | fegoes throughsp.feols(pyfixest).sp.regressis OLS only and does not parse|;sp.ivregtakes no| feeither.- Staggered DID: never a static TWFE coefficient.
sp.callaway_santanna(+sp.aggte) orsp.sun_abraham; event-study figures come from those results. A passed pre-trend test is not evidence for parallel trends — reportsp.honest_didandsp.pretrends_power. - Event-study paths get simultaneous bands:
sp.uniform_bands(sup-t) on top ofsp.event_study_vcov; pointwise CIs do not support a claim about the whole path. - One or a few treated units: cluster-robust SEs over-reject; use
sp.did_few_treated(orsp.wild_cluster_bootstrap). - Treatment that feeds back into later states:
sp.dynamic_dml, notsp.dml/sp.dml_panel. - Panel forests (
fe=): test heterogeneity withsp.rate_split, notsp.rateon the forest's own ranking;sp.forest_policy_treeis fe-only. - Covariates do not go in a TWFE / 3WFE regression under conditional
parallel trends:
sp.drdid,sp.callaway_santanna(..., x=[...], estimator='dr'),sp.ddd(..., method='dr'). - IV: report the first-stage / effective F before the 2SLS coefficient
(
sp.iv_diaggives the whole bundle); below 10,sp.anderson_rubin_ci— not a 2SLS t-ratio. - Parity claims are per configuration: quote
sp.validation_scope(result)instead of a blanket "matches Stata / R". - RD:
sp.rddensity(test),sp.rdplotdensity(its figure) andsp.rdplotbefore the effect table; bandwidth sensitivity in robustness. - Matching / weighting: balance (
sp.love_plot,sp.ps_balance) before outcomes; say which estimand (ATT / ATE / ATO). - Export all three formats (
.to_word,.to_excel,.to_latex) from the sameRegtableResult/Collection; never hand-roll LaTeX. - Citations only from
result.cite()/sp.bibtex(keys=[...])— never from memory (paper.bib is the single source of truth). - Plots return
(fig, ax): unpack, thenfig.savefig(...).
Where to read next
| Need | File |
|---|---|
| one estimate, one check or one export: route, describe, fit, inspect, export, and when to stop | references/quick-path.md |
| operating loop in full, acceptance gates by request type, mode table, figure & table inventory | references/operating-loop.md |
| the minimal end-to-end skeleton to copy | references/verified-skeleton.md |
| Steps −1 → 8 with code, one paper section each | references/pipeline-econ.md |
| target-trial / IPTW / g-formula / TMLE / MR / survival pipeline | references/pipeline-epi.md |
| DML / meta-learners / causal forest / policy / conformal / fairness pipeline | references/pipeline-ml-causal.md |
| Word / Excel / LaTeX export, regtable recipes, the 12 standard figures, notebook setup | references/export.md |
| method catalog by family; when to use StatsPAI vs alternatives | references/method-catalog.md |
| robust staggered-DID family, event-study bands, few treated units, IV bundle, GRF forest family, dynamic DML, validation scope | references/modern-methods.md |
| API traps that cost agents real time; agent integration pattern | references/common-mistakes.md |
driving StatsPAI over MCP (statspai-mcp) or the shell (statspai run), data handles, routing, the result contract |
references/mcp-and-cli.md |
Validation
statspai skill validate (or python validate_api_claims.py) runs the gate:
every sp.<name> in this skill exists, the documented argument names bind, and
the documented result attributes hold on a live fit. statspai skill validate --run also executes the quick path, the verified skeleton, the three
pipelines and the export recipes on synthetic frames (several minutes); a
block opened with ```python no-run is a sketch that needs something
the gate does not have (an LLM client, your own second dataset) and is bound
but not executed. EVALS.md-style held-out
checks for editing the skill itself live in the repository under
StatsPAI_full_data_analysis_skill/EVALS.md.