Twin
Digital twins: forecast, simulate, intervene, score, update.
Twin
A digital twin handle bound to one version (the latest unless told otherwise).
Properties
id (
str)name (
str)kind (
str)is_panel (
bool)is_temporal (
bool)versions (
list[dict[str, Any]])version (
dict[str, Any])version_id (
str)source (
Any): The raw source backing this version, or None when it trains off a dataset.graph (
Graph)roles (
dict[str, Any]): The version's variable roles: which variables are sources and which are targets.update_eligibility (
dict[str, Any]): Whether update() would find new data, and whether it can assimilate incrementally.environments (
pd.DataFrame): Panel twins: the environments in the version's data, with sample sizes.groups (
list[Group]): The twin's saved environment groups — the same ones the platform's picker lists.
Twin.at_version
Undocumented; the signature above is the contract.
Twin.delete
Delete this twin permanently: models, versions, runs and record.
Running discovery or simulation workflows are cancelled first. There is no undo — the platform's own delete confirmation exists for a reason. Requires the digital-twins:delete scope.
Twin.link
This twin version's page on the platform, as a clickable URL.
Twin.discover
Run causal discovery on this version and return the discovered graph.
webhook_url
str | None
None
Called with the job result instead of waiting on it.
timeout
float
3600.0
Seconds to wait for the discovery job.
Returns (Graph): The discovered Graph.
Twin.train
Train the model for this version, blocking until done.
An already-trained version is returned as-is: the platform's lifecycle retrains through a new version, not by re-fitting in place. To rebuild a model from scratch (after an engine fix, or a corrupt artifact), use rc.discover(df, force=True) and train the fresh twin it returns.
webhook_url
str | None
None
Called with the job result instead of waiting on it.
timeout
float
7200.0
Seconds to wait for the training job.
Returns (Twin): This twin, trained. An already-trained version comes back unchanged.
Twin.run_pipeline
Discovery + dependencies + roles + training in one pass.
webhook_url
str | None
None
Called with the job result instead of waiting on it.
timeout
float
7200.0
Seconds to wait for the whole pipeline.
Returns (Twin): This twin, trained.
Twin.evaluate
Undocumented; the signature above is the contract.
Twin.new_version
Derive a fresh, untrained version from an existing one — the retrain primitive.
Inherits the base version's configuration and causal graph, resets every training output, and returns the twin pinned to the new version.
bump
str
'patch'
Which part of the version number to advance: patch, minor, or major.
base_version_id
str | None
None
Version to derive from. Defaults to the latest.
dataset_id
str | None
None
Train the new version off a different dataset.
Returns (Twin): A handle bound to the new, untrained version.
Twin.retrain
Create a new version off the latest and train it — the full retrain in one call.
bump
str
'patch'
Which part of the version number to advance: patch, minor, or major.
timeout
float
7200.0
Seconds to wait for the training job.
Returns (Twin): A handle bound to the newly trained version.
Twin.set_roles
Set the version's variable roles ahead of discovery and training.
Roles steer the causal engine: targets are the outcomes the model is for, sources are the levers. Pass either list to change just that side — the other keeps its current (or suggested) value. This is the per-version counterpart of the ontology-level concept.override(suggested_role=...), which sets the default for every future twin built over that concept.
targets
list[str] | None
None
Outcome variables.
sources
list[str] | None
None
Driver variables.
Returns (dict[str, Any]): The stored roles document.
Twin.update
Fold data added to the backing source since the last train/update into the model.
No retrain: incremental assimilation. The job succeeds with a status rather than failing — committed, up_to_date, or retrain_required (the model can't take these rows incrementally; result.reasons says why — call retrain()). Static and temporal twins assimilate out of the box; panel twins need the v2 panel engine. Requires a trained version; extend or sync the source first so there is something new.
webhook_url
str | None
None
Called with the job result instead of waiting on it.
timeout
float
3600.0
Seconds to wait for the update job.
Returns (UpdateResult): An UpdateResult. Never raises on retrain_required.
Twin.env
A handle pinned to a subset of this panel twin's environments.
Name them directly — environment names ("london"), envKeys, or exact {column: value} combos — or select them by data with where=, filtering on any twin column through per-environment statistics:
One saved environment group, by name or id.
name_or_id
str
required
The group's display name (case-insensitive) or its id.
Returns (Group): A Group: the same scoped surface as env(), pinned to a saved membership rule.
Raises
RootCauseError: The twin has no such group; the message names the ones it does have.
Twin.score
Score rows against target outcomes: each row gets its smallest flip.
Static trained twins only. Blocks until the run completes.
rows
pd.DataFrame | list[dict[str, Any]]
required
A DataFrame, or a list of dicts whose keys name twin variables.
targets
list[dict[str, Any]]
required
The outcomes to reach, as [{"variable": ..., "value": ...}].
max_changes
int
3
Most variables any one row is allowed to flip.
constraints
dict[str, Any] | None
None
Per-variable limits on what may change, and how far.
webhook_url
str | None
None
Called with the run result instead of waiting on it.
timeout
float
3600.0
Seconds to wait for the run.
Returns (ScoreResult): A ScoreResult covering every row.
Twin.sample
Raw joint posterior draws — the primitive every simulation family wraps.
n
int
1000
Draws per sampling unit.
do
dict[str, Any] | None
None
Interventions to apply before sampling, as {"variable": rc.set(value)}. A bare value means rc.set.
where
Any
None
Scope the draws to a subpopulation: {"region": "EMEA"} for equality, or {"income": ("<", 5000)} with any of == != > < >= <=, plus in and not_in.
environments
list[str] | None
None
Panel twins: which environments to sample. Each is sampled independently.
seed
int | None
None
Seed for reproducible draws. Panel twins derive stable per-environment child seeds from it.
Returns (SampleDraws): The draws as SampleDraws.
Raises
RootCauseError:environmentswas passed for a twin that is not a panel twin.
Twin.intervene
Run an intervention simulation and block for the result.
Interventions measure their effect through metrics: pass metrics=[rc.metric(...)] for full control, or outcomes=["revenue"] for mean-of-column metrics. For raw effect distributions without metrics, use twin.sample(do=...).
do
dict[str, Any]
required
The interventions, as {"variable": rc.set(value)}. A bare value means rc.set; rc.range(...) sweeps instead of pinning.
where
Any
None
Scope the intervention to a subpopulation: {"region": "EMEA"} for equality, or {"income": ("<", 5000)} with any of == != > < >= <=, plus in and not_in.
metrics
list[dict[str, Any]] | None
None
Metrics to measure the effect through, from rc.metric().
outcomes
list[str] | None
None
Column names to measure as mean-of-column metrics, when metrics is not given.
environments
list[str] | None
None
Panel twins: which environments to simulate.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult.
Raises
RootCauseError: Neithermetricsnoroutcomeswas given.
Twin.forecast
Forecast horizon steps ahead for the target variables.
horizon
int
required
How many steps ahead to forecast.
targets
list[str] | None
None
Variables to forecast. Inferred from the twin when omitted.
environments
list[str] | None
None
Panel twins: which environments to forecast.
confidence
float
0.95
Width of the prediction interval, as a probability.
origin_timestamp
int | None
None
Anchor the forecast start (ms epoch). How a backtest aligns a forecast against data the twin never saw.
aggregate
str | None
None
Panel twins: add a combined series across environments, one of sum, avg, min, max.
timeout
float
3600.0
Seconds to wait for the run.
Returns (ForecastResult): A ForecastResult, tidy long format.
Raises
RootCauseError: The twin is not temporal, oraggregatewas passed for a twin that is not a panel twin.
Twin.predict
Predict target outcomes for input records, with uncertainty intervals.
One prediction per input record: the model reads the values you supply as the drivers and answers for the targets you name. Static twins only: a temporal twin projects forward with forecast() instead.
sample
pd.DataFrame | list[dict[str, Any]]
required
The input records, as a DataFrame or a list of dicts keyed by twin variable name. Leave the target columns out: those are what the model answers with.
targets
list[str] | None
None
Variables to predict. Inferred from the twin when omitted.
confidence
float
0.95
Width of the uncertainty interval, as a probability.
timeout
float
3600.0
Seconds to wait for the run.
Returns (PredictionResult): A PredictionResult, one row per input record.
Raises
RootCauseError: The twin is temporal, whereforecast()is the verb.
Examples
Twin.explain
Explain a causal relationship: what a variable drives, or what drives it.
The mode follows from what you name, so you rarely pass it: cause= alone asks what that variable goes on to affect (impact), effect= alone asks what drives it (discovery), and both together explain the paths from one to the other (directional).
cause
str | None
None
The upstream variable, for impact and directional.
effect
str | None
None
The downstream variable, for discovery and directional.
mode
str | None
None
Override the mode: directional, discovery, or impact.
environments
list[str] | None
None
Panel twins: which environments to explain.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult.
Raises
RootCauseError: Neither variable was named, the mode is unknown, the mode is missing a variable it needs, orenvironmentswas passed for a twin that is not a panel twin.
Examples
Twin.optimise
Search for the actions that best move your objectives.
The optimizer may only touch the variables you list in decision_vars, and it measures every plan through the objectives' SQL, so an objective naming a variable nothing in decision_vars can reach has no plan to find.
objectives
list[dict[str, Any]]
required
What to move and which way, from rc.objective().
decision_vars
list[str]
required
The variables the optimizer is allowed to change.
horizon
int | None
None
Temporal twins: how many steps ahead the plan runs over. Required for a temporal twin, refused for a static one.
environments
list[str] | None
None
Panel twins: which environments to optimize over.
variable_constraints
list[dict[str, Any]] | None
None
Bounds on how far each variable may move.
metric_constraints
list[dict[str, Any]] | None
None
Guardrails every plan must respect.
max_changes
int | None
None
Cap on how many variables a single plan may change.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult.
Raises
RootCauseError: No objectives or no decision variables, an objective that is not arc.objective()payload, a horizon that this twin kind does not take (or a temporal twin given none), orenvironmentson a twin that is not a panel twin.
Examples
Twin.root_cause
Diagnose one variable: trace it upstream to what actually broke it.
Use this when you already know which variable is misbehaving. To find out whether anything is, scan every variable with anomalies().
target
str
required
The variable behaving unexpectedly.
samples
pd.DataFrame | list[dict[str, Any]] | dict[str, list[dict[str, Any]]]
required
The observations to diagnose, as a DataFrame, a list of dicts, or, on a panel twin, a {environment: rows} mapping. A flat list on a panel twin is shared across its environments.
environments
list[str] | None
None
Panel twins: which environments to diagnose.
timestep
int | None
None
Temporal twins: the step to diagnose. Defaults to the one the scan flags.
target_fpr
float
0.005
Detection sensitivity, as a false-positive rate between 0.0001 and 0.1. Lower flags less.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult.
Raises
RootCauseError: No target,environmentsor per-environment samples on a twin that is not a panel twin, ortimestepon a twin with no time axis.
Examples
Twin.anomalies
Scan every variable for causal anomalies, and diagnose what it finds.
The counterpart to root_cause(): this one asks whether anything is broken rather than why a named variable is.
samples
pd.DataFrame | list[dict[str, Any]] | dict[str, list[dict[str, Any]]]
required
The observations to scan, as a DataFrame, a list of dicts, or, on a panel twin, a {environment: rows} mapping. A flat list on a panel twin is shared across its environments.
environments
list[str] | None
None
Panel twins: which environments to scan.
start_step
int | None
None
Temporal twins: first step of the window to scan.
end_step
int | None
None
Temporal twins: last step of the window to scan.
target_fpr
float
0.005
Detection sensitivity, as a false-positive rate between 0.0001 and 0.1. Lower flags less.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult.
Raises
RootCauseError:environmentsor per-environment samples on a twin that is not a panel twin, or a step window on a twin with no time axis.
Examples
Twin.ask
Natural-language question, turned into a scenario and executed.
query
str
required
The question, in plain language.
timeout
float
3600.0
Seconds to wait for the run.
Returns (SimulationResult): A SimulationResult; result.scenario is what the translator produced.
Twin.console
The interactive causal-graph console under the cell: the same app Claude renders.
Explore edges, type intervention values, and re-run scenarios; every control round-trips live through the platform's MCP gateway with this session's credentials. Needs: pip install "rootcause-sdk[jupyter]".
height
int
560
Height of the mounted app, in pixels.
theme
str
''
light, dark, or empty to follow the notebook.
Returns (Any): The mounted widget, displayed by the notebook cell.
Twin.sankey
The causal-flow Sankey under the cell: how influence propagates through the graph.
Pass a variable to see everything flowing into and out of it, or an edge to see the paths running through that one link. Needs a resolved or trained graph and: pip install "rootcause-sdk[jupyter]".
node
str | None
None
Variable to analyse paths around. Exactly one of node and edge must be given.
edge
tuple[str, str] | None
None
A (cause, effect) pair to analyse paths through.
depth
int
2
How many hops to traverse on either side.
height
int
520
Height of the mounted app, in pixels.
theme
str
''
light, dark, or empty to follow the notebook.
Returns (Any): The mounted widget, displayed by the notebook cell.
Twin.review
The graph-review console under the cell: structural findings with accept/reject controls.
Runs the platform's DAG review (cycles, isolated nodes, weak or wrong-direction edges, over-connected hubs) and mounts the interactive console over the findings; applying a fix round-trips live through the MCP gateway. Needs: pip install "rootcause-sdk[jupyter]".
height
int
560
Height of the mounted app, in pixels.
theme
str
''
light, dark, or empty to follow the notebook.
Returns (Any): The mounted widget, displayed by the notebook cell.
Twin.studio
Ask a what-if in plain English; the What-If Studio renders the answer under the cell.
The scenario is inferred from the question and executed server-side; the studio draws the result with the dials behind it, so a tweaked scenario re-runs live through the MCP gateway without leaving the notebook. Needs: pip install "rootcause-sdk[jupyter]".
query
str
required
The question, stated completely — which variables change, to what, and the outcome of interest.
targets
list[str] | None
None
Exact outcome variable names, when inference should not pick them from the question.
horizon
int | None
None
Forecast scenarios only: exact number of steps.
environments
list[str] | None
None
Panel forecasts only: restrict to these environments.
aggregate
str | None
None
Panel forecasts only: sum, avg, min, or max across environments.
height
int
640
Height of the mounted app, in pixels.
theme
str
''
light, dark, or empty to follow the notebook.
Returns (Any): The mounted widget, displayed by the notebook cell.
Twin.save
Export this twin (trained params included) as a portable .rctwin zip.
path
str | Path
required
Where to write the .rctwin file. A directory writes <twin name>.rctwin inside it.
include_runs
bool
False
Include the simulation run history in the export.
timeout
float
3600.0
Seconds to wait for the export job.
Returns (Path): The path written, ready for rc.load_twin().
Raises
InvalidArgumentError: The destination directory does not exist. The check runs before the export job starts.
EnvSubset
A panel twin pinned to a subset of its environments.
Everything on the handle runs scoped to the subset: graph re-aggregates the causal adjacency over just these environments, and sample/intervene/ forecast delegate to the twin with environments= filled in.
Properties
environments (
pd.DataFrame): The environments this handle covers, resolved to a DataFrame.graph (
pd.DataFrame)
EnvSubset.combos
The subset as exact {column: value} combos, resolved against the twin's environments.
The listing carries each environment's values as a list ordered by environmentColumns; zipping the two recovers the combo.
EnvSubset.save
Save this subset on the twin as a named environment group.
The group lives on the twin rather than on a version, so it survives retraining, appears in the platform's environment picker straight away, and comes back next session as twin.group(name). What gets stored is the rule, not the answer: a where= subset saves its filters and re-selects environments as the data moves, while a named subset saves the exact combos it resolved to.
name
str
required
Display name, unique per twin.
Returns (Group): The saved Group.
Raises
RootCauseError: The twin already has a group with this name, or is at its group cap.
EnvSubset.adjacency
The causal adjacency aggregated over just this subset of environments.
Returns the edges as a DataFrame (source, target, strength, agreementRate, …); frame.attrs carries envCount, sampleSize, totalEnvCount, and the threshold.
EnvSubset.sample
Undocumented; the signature above is the contract.
EnvSubset.intervene
Undocumented; the signature above is the contract.
EnvSubset.forecast
Undocumented; the signature above is the contract.
EnvSubset.explain
Undocumented; the signature above is the contract.
EnvSubset.optimise
Undocumented; the signature above is the contract.
EnvSubset.root_cause
Undocumented; the signature above is the contract.
EnvSubset.anomalies
Undocumented; the signature above is the contract.
EnvSubset.link
The parent twin's page on the platform, as a clickable URL.
Group
A saved environment group: the same scoped surface as a subset, kept on the twin.
Everything an EnvSubset does, a group does against its current membership — the rule is stored, not the answer, so it is resolved against this handle's version on first use and re-resolved after an edit. Simulations name the group rather than expanding it, so the run records which group it covered and what that meant at submit time.
doc
dict
The stored group document.
Properties
id (
str)name (
str)definition (
dict[str, Any]): The stored membership rule:environments,columnValues, orstatFiltersmode.
Group.rename
Rename the group in place.
name
str
required
The new display name, unique per twin.
Returns (Group): This group.
Raises
RootCauseError: The twin already has a group with this name.
Group.update
Replace the group's membership rule, in the same vocabulary as twin.env().
Runs already submitted keep the membership frozen on their snapshots; every later read of the group sees the new rule.
Returns (Group): This group, on the new rule.
Raises
RootCauseError: None (or more than one) of the three selection styles was passed.
Group.delete
Delete the group from the twin.
Nothing downstream goes with it: runs scoped to the group keep their snapshots. Deleting a group that is already gone is a no-op.
Group.intervene
Undocumented; the signature above is the contract.
Group.forecast
Undocumented; the signature above is the contract.
Group.explain
Undocumented; the signature above is the contract.
Group.optimise
Undocumented; the signature above is the contract.
Group.root_cause
Undocumented; the signature above is the contract.
Group.anomalies
Undocumented; the signature above is the contract.
Group.link
The parent twin's page on the platform, as a clickable URL.
Last updated

