Skip to main content
Glama
vikranthviki

Causal Decision Agent

by vikranthviki

did_imputation

Read-only

Fits a two-way model on untreated observations, imputes counterfactual Y(0) for treated units, and averages residuals to estimate the ATT in staggered DiD. Needs never-treated or not-yet-treated units.

Instructions

Borusyak-Jaravel-Spiess (2024) imputation DiD. Fits a TWFE model on untreated observations only, imputes counterfactual Y(0) for treated obs, and averages the imputation residuals. Efficient under no-anticipation + parallel trends; analytical SE via bjs_inference. Validation: certified evidence with scoped limitations. Known limitations: R/Stata parity is for the documented untreated-only TWFE and simple ATT aggregation convention only; event-study and SE rows are backend-specific diagnostics. Do NOT use when: there is no never-treated (or not-yet-treated) group to fit the untreated-potential-outcome model on -- imputation has no estimation sample; the design is a simple 2x2 -- sp.did(method='2x2') is the same estimand and far cheaper; pre-trends are visibly non-parallel -- BJS imputes Y(0) from a two-way model that assumes them away, so violations are absorbed silently rather than surfaced. Cost: Fits the untreated two-way model once, then imputes; cheap in memory. vce='bootstrap' multiplies total runtime by n_boot -- budget accordingly before raising n_boot. Assumptions: Parallel trends in absolute levels; No anticipation (no pre-treatment reaction); SUTVA. Pre-conditions: panel...

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yYesOutcome variable column name or outcome array.
feNoFixed effects in the Y(0) model, replacing the default unit+time. Stata's fe(): entries are column names or 'a#b' interacted cells; [] means no fixed effects.
vceNoStandard-error mode for the overall ATT. 'analytic' is fast but anti-conservative (~0.87 coverage); 'bootstrap' resamples clusters.analytic
timeYesTime period column
alphaNoSignificance level for confidence intervals and tests.
groupYesUnit identifier
hetbyNoReport heterogeneous ATTs by a time-invariant unit-level variable (Stata: hetby())
min_nNoDrop event-study horizons with fewer treated observations (Stata: minn())
detailNoPayload depth: 'minimal' (~150 tokens) for sub-step calls where only the point estimate is needed; 'standard' (~1K tokens) for diagnostics + coefficient table; 'agent' (~2K tokens, default) adds violations / next_steps / suggested_functions so the LLM can plan its next call without another round-trip.agent
n_bootNoCluster-bootstrap replications when vce='bootstrap'.
clusterNoCluster identifier column for clustered standard errors.
horizonNoRelative-time leads / lags (default: all available)
projectNoRegress the imputed treatment effects on these covariates and report constant plus slopes. Stata's project(); mutually exclusive with hetby.
balancedNoKeep only eventually-treated units observed at every non-negative requested horizon (Stata: hbalance)
controlsNoControl-variable column names.
as_handleNoIf true, cache the fitted result on the server and return result_id + result_uri alongside the JSON payload so a subsequent tools/call can chain without re-running.
boot_seedNoSeed for the cluster bootstrap (deterministic results).
data_pathYesAbsolute path or URL to a data file. Supported: .csv / .tsv / .txt (delimited), .parquet / .pq, .feather / .arrow, .xlsx / .xls, .dta (Stata), .json / .jsonl. Schemes: file://, s3://, gs://, https://.
pretrendsNoEstimate k placebo pre-trend coefficients (-k..-1) and report their joint Wald test (Stata: pretrends(k))
result_idNoOptional handle to a previously-fitted result (returned by an earlier call when as_handle=true). Tools that operate on a fitted object accept this in place of re-supplying data_path + columns.
se_methodNoShared DiD spelling for vce=: 'analytic', 'bootstrap' or 'auto'. Passing both raises.
first_treatYesFirst-treatment period; 0 = never-treated
data_columnsNoOptional column projection. Parquet/Feather/Stata loaders honour this for fast partial reads.
save_weightsNoStore exact estimation weights w with ATT = w'y in model_info (Stata: saveweights())
data_sample_nNoOptional uniform random subsample size (seed=0, deterministic) — useful on huge panels.
save_residualsNoStore untreated-fit residuals in model_info (Stata: saveresid())
pretrend_methodNoReference convention for the PRE-treatment event-study coefficients. 'bjs' matches Stata did_imputation, 'in-sample' is the fect/did2s residual average (attenuated by N0/N), 'symmetric' is Roth's (2026) TWFE-comparable repair for non-staggered designs. Post-treatment coefficients are identical under all three.bjs
time_covariatesNoControls interacted with the period fixed effects (one coefficient per period). Stata's timecontrols().
unit_covariatesNoControls interacted with the unit fixed effects (one slope per unit). Stata did_imputation's unitcontrols(); unit_covariates=[time] gives unit-specific trends.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, so the description need not repeat safety. It adds valuable context: limitations (R/Stata parity scope), silent absorption of pre-trend violations, cost (fits once, cheap), and bootstrap runtime multiplication. This goes beyond annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections (Validation, Known limitations, Do NOT use when, Cost, Assumptions, Pre-conditions). The core purpose is front-loaded. While lengthy, it's appropriately detailed for a complex econometric tool and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, limitations, cost, assumptions, and pre-conditions. An output schema exists, so return format is covered. However, the pre-conditions section is truncated ('Pre-conditions: panel...'), leaving it incomplete. This minor gap prevents a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds meaningful context for several parameters: vce ('analytic' is anti-conservative ~0.87 coverage), pretrend_method (explains reference conventions), and detail levels (token counts and intended use). This enriches understanding beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as Borusyak-Jaravel-Spiess imputation DiD, explaining the exact methodology (fits TWFE on untreated obs, imputes Y(0), averages residuals). It distinguishes from siblings by mentioning sp.did(method='2x2') as an alternative and highlighting the need for a never-treated group.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly lists three conditions where the tool should NOT be used, each with a specific reason and an alternative (e.g., no never-treated group → imputation has no estimation sample; simple 2x2 → use sp.did(method='2x2')). It also mentions cost implications for bootstrap, giving clear guidance on when to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools