# Overview

RootCause turns structured business data into an explainable causal model that you can use to test decisions before acting. It connects to your data, discovers cause-and-effect relationships, combines them with human judgment, and produces a runnable Digital Twin. You can then simulate interventions, find optimal strategies, explain past outcomes, and forecast what happens next — all backed by causal evidence, not just historical patterns.

### How It Works

RootCause follows a seven-step workflow. Each step builds on the last, producing a specific artifact that feeds the next stage:

<figure><img src="/files/6sGNVyKjKphE9qEPmfWt" alt="The RootCause seven-step workflow: Connect Data, Build Ontology, Build 360 Table, Build Causal Graph, Build Digital Twin, Run Simulations, Produce Reports"><figcaption></figcaption></figure>

1. [**Connect Data**](/start-here/workflow#1-connect-data) — Import data from files, databases, or APIs
2. [**Build Ontology**](/start-here/workflow#2-build-ontology) — Map your data into a shared semantic layer
3. [**Build 360 Table**](/start-here/workflow#3-build-360-table) — Prepare a single, analysis-ready dataset
4. [**Build Causal Graph**](/start-here/workflow#4-build-causal-graph) — Discover what drives what
5. [**Build Digital Twin**](/start-here/workflow#5-build-digital-twin) — Create a runnable causal model
6. [**Run Simulations**](/start-here/workflow#6-run-simulations) — Test decisions before acting
7. [**Produce Reports**](/start-here/workflow#7-produce-reports) — Package findings into living documents

For the full walkthrough, see the [Seven-Step Workflow](/start-here/workflow). If you want to jump straight in with sample data, try the [Quick Start Tutorial](/start-here/quick-start-tutorial).

***

### Key Concepts

Understanding these terms will help you navigate the platform:

**Dataset**

Raw data imported into RootCause from files or connectors. This is your original data before any transformations.

**Data View**

A transformed and prepared version of one or more datasets, ready for analysis. Data Views let you join, filter, and reshape data without modifying the originals. In the seven-step workflow, this is the "360 Table."

**Ontology Concept**

A unified representation of a column that may appear across multiple datasets. For example, "Customer ID" might appear in your sales data, support tickets, and CRM export — ontology concepts link these together so RootCause knows they refer to the same thing.

**Digital Twin**

A causal model of your business or system that can be used for simulation and optimization. Unlike traditional predictive models that just forecast, a Digital Twin understands *why* things happen, so it can predict the effects of actions you've never taken before.

**Simulation**

A what-if analysis run against your Digital Twin. Simulations let you test interventions ("what if we raise prices?"), find optimal strategies ("what's the best marketing mix?"), or explain outcomes ("why did sales drop last quarter?").

***

### Getting Help

**RootCause Assistant** (BETA)

Click the chat button in the platform toolbar (or press `⌘⇧J`) to ask questions about your data, generate simulations, or get help navigating the platform. See [RootCause Assistant](/more-details/rootcause-assistant).

**Support**

Contact your organization's administrator or reach out to the RootCause team.


# Setup Org and Workspace

Before you begin any analytical work in RootCause, you need to be in the right place. All of the [seven-step workflow](/start-here/workflow) — from connecting data through producing reports — happens inside a workspace. Understanding the container model will help you stay organized as your work grows.

## Organization

Your top-level account. Contains workspaces, users, and billing settings. Most companies have one organization with multiple workspaces for different teams or projects.

<figure><img src="/files/z44hwK5ITsGiSdKpQEFD" alt="Organization home showing a grid of workspaces"><figcaption><p>The Organization home. Each card is a workspace — a self-contained analytical project.</p></figcaption></figure>

Below the workspace cards, the **Manage** section links to organization-level pages, including [Organisation settings](/more-details/organisation-administration) (members, roles, and branding) and [API](/api-and-integrations/api-access) (keys and integrations for programmatic access). **View all** opens the full workspaces list, which is searchable by name, owner, or ID and includes an **Import workspace** action.

## Workspace

A workspace is the collaboration boundary for a specific project or team. Each workspace has its own datasets, ontology, digital twins, simulations, and reports. Use workspaces to separate different analytical domains — marketing might have one workspace, operations another.

To create a workspace, click the **New workspace** card on the Organization home. Give it a descriptive name — the name helps RootCause improve its analysis recommendations.

<figure><img src="/files/dUIOtJTO1aW4YPJGS1HX" alt="New workspace dialog with the name Customer Analytics entered and Cancel and Create buttons"><figcaption><p>Creating a new workspace. A descriptive name helps RootCause suggest relevant analysis as you work.</p></figcaption></figure>

Opening a workspace lands on **Sources** — the de-facto workspace home (the workspace root URL redirects there). A new workspace starts empty, and the guided journey card walks you through the first steps — or click **Don't guide me in this workspace** to navigate freely.

<figure><img src="/files/setk8BwevdVWMHa0kJuc" alt="A fresh workspace opening on the empty Sources page, with the top navigation bar and the setup journey card in the corner"><figcaption><p>A new workspace opens on Sources. The top navigation bar carries the six main sections, which map directly to the seven-step workflow.</p></figcaption></figure>

## Main sections

Within a workspace, six sections in the top navigation bar correspond to the stages of the workflow:

| Section           | Purpose                                                                                             | Workflow steps |
| ----------------- | --------------------------------------------------------------------------------------------------- | -------------- |
| **Sources**       | Import raw data — click **Import data** to upload files or set up connectors                        | Step 1         |
| **Ontology**      | Review and refine the semantic map built from your sources                                          | Step 2         |
| **Datasets**      | Data views derived from your workspace sources — build the [360 Table](/user-guide/data-views) here | Step 3         |
| **Digital Twins** | Build causal graphs, train twins, run simulations                                                   | Steps 4–6      |
| **Reports**       | Create and share analytical reports                                                                 | Step 7         |
| **Applications**  | Build and run apps on your workspace's data                                                         | —              |

The **Applications** section sits outside the seven-step workflow: it is where finished analytical work gets operationalized. Applications are built on your workspace's data and Digital Twins, and their audience can run them without touching the underlying models. See [Applications](/more-details/applications).

## The platform toolbar

The header above the main sections is the same everywhere in the platform:

| Control                             | What it does                                                                                                                                                           |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Workspace switcher**              | The current workspace's name, left of the section navigation. Click to jump to another workspace.                                                                      |
| **Search / command palette** (`⌘K`) | Search the workspace or run a command from anywhere.                                                                                                                   |
| **Notifications**                   | Job completions and platform events.                                                                                                                                   |
| **Chat** (`⌘⇧J`)                    | Toggles the [RootCause Assistant](/more-details/rootcause-assistant) panel.                                                                                            |
| **Help mode**                       | Turns on hover help: point at any element to learn what it does.                                                                                                       |
| **Account menu**                    | Your avatar, top right. Switch organizations, create a new organization, open **User settings** (profile, avatar, password) or **Organisation settings**, and log out. |

The **Platform status** indicator next to the logo reports overall health; clicking it opens the Health Status page with per-component detail.


# Seven-Step Workflow

RootCause transforms your data into an explainable causal model through seven steps. Each step produces a specific artifact that feeds the next stage. The steps are sequential for your first project. Once you are familiar with the system, you may revisit earlier steps as your understanding evolves.

<figure><img src="/files/6sGNVyKjKphE9qEPmfWt" alt="The RootCause seven-step workflow: Connect Data, Build Ontology, Build 360 Table, Build Causal Graph, Build Digital Twin, Run Simulations, Produce Reports"><figcaption></figcaption></figure>

***

## 1. Connect Data

The first step is to get data into RootCause. Open the **Sources** section in the top navigation bar and click **Import data**. The system supports direct file upload for one-off analysis and live data connectors for systems that change regularly.

**File uploads** support tabular formats (CSV, TSV, Parquet, Excel, ODS, JSON) as well as documents and media — see [File Uploads](/more-details/data-management/uploading-datasets/file-uploads) for the full list. You can drag and drop files or use the file picker.

**Live connectors** keep data in sync with external systems. Currently supported connectors include [PostgreSQL](/data-connectors/postgresql), [MySQL](/data-connectors/mysql), [MongoDB](/data-connectors/mongodb), [Snowflake](/data-connectors/snowflake), [REST API](/data-connectors/rest-api), [Amazon S3](/data-connectors/s3), [Azure Data Lake](/data-connectors/azure-data-lake), and [Google Cloud Storage](/data-connectors/google-cloud-storage).

Once connected, data can be refreshed manually or on a schedule. After import, verify column types, preview rows, and check that the dataset name and description clearly reflect the business meaning.

**Why this matters:** Everything downstream depends on having the right data in the workspace. Garbage in, garbage out.

See: [Selecting Data](/more-details/data-management/uploading-datasets), [File Uploads](/more-details/data-management/uploading-datasets/file-uploads), [Data Connectors](/more-details/data-management/uploading-datasets/data-connectors)

***

## 2. Build Ontology

After the data is loaded, RootCause builds and maintains an ontology — the semantic map of your business. The ontology identifies when fields from different datasets represent the same underlying concept and classifies them in ways that matter for downstream analysis.

Concepts are classified as one of four types:

* **Identifier** — Fields used for linking records (e.g., Customer ID). Generally excluded from causal modeling.
* **Time** — Fields that tell the model to respect chronological ordering.
* **Location** — Fields that represent geographic or spatial dimensions.
* **Entity** — Ordinary business variables used in analysis (e.g., Revenue, Churn Status).

RootCause creates ontology concepts automatically when data is uploaded, inferring types and suggesting merges across similar columns. You should review the results and adjust where needed — merge concepts that refer to the same thing, split concepts that were incorrectly combined, and reclassify any that were tagged with the wrong type.

**Why this matters:** The ontology is the foundation of the platform. If it misunderstands what your data means, everything built on top of it will be wrong.

See: [Ontology Concepts](/user-guide/ontology-concepts), [Ontology (Core Technology)](/core-technologies/ontology)

***

## 3. Build 360 Table

Once the ontology exists, you create the analysis-ready dataset. In RootCause, this is called a **Data View** — you build and manage them in the **Datasets** section of the top navigation bar. A Data View is a reusable preparation layer between raw data and modeling — it lets you join sources, filter rows, aggregate data, create calculated fields, clean duplicates and missing values, standardize categories, and perform time-series transformations, all without modifying the original datasets.

For most Digital Twins, you should prepare a single, coherent analysis table that represents the domain you want to model. For example, combining customer demographics, transactions, and support tickets into one row per customer. That is why "Build 360 Table" is a better way to think about this step than just "create a Data View" — it tells you what you are producing, not just the product term.

{% hint style="warning" %}
**Important:** Applying operations does not finalize the Data View. You must click **Save** before leaving the editor.
{% endhint %}

**Why this matters:** Causal discovery works best with a single, coherent dataset that represents your analytical domain. The 360 Table is the input for the Digital Twin.

See: [Data Views](/user-guide/data-views)

***

## 4. Build Causal Graph

The next step is to discover and refine the causal graph. A causal graph, or **Directed Acyclic Graph (DAG)**, is a visual map of what drives what in the system. It uses arrows to show cause-and-effect relationships, and it has no feedback loops — causes flow in one direction.

RootCause builds this graph from your 360 Table, combining domain rules with statistical evidence. The system initially produces a **CPDAG (completed partially directed acyclic graph)** — a graph where some causal directions are still uncertain. You then use the Relationships tab to refine the discovered structure: resolving ambiguous directions, removing spurious links, and adding known relationships that the algorithm may have missed.

This step is distinct from building the Digital Twin. The graph is the structural layer — the map of what causes what. The twin (next step) is the operational model that quantifies those relationships and makes them runnable.

**Why this matters:** The causal graph is the heart of the Digital Twin. If the structure is wrong, simulations will give misleading answers. Human review at this stage catches errors that no algorithm can.

See: [Causal Graph](/user-guide/causal-graph), [Causal Discovery (Core Technology)](/core-technologies/causal-discovery)

***

## 5. Build Digital Twin

After the graph is discovered and reviewed, RootCause creates the Digital Twin — the causal model of your business or system and the execution layer of the platform. The twin takes the graph structure and fits equations, constraints, and optional confounder logic to create a model that can actually run simulations.

RootCause supports four twin types (see [Types of Digital Twins](/more-details/build-digital-twin/twin-types)):

* **Static** for cross-sectional data (one snapshot in time).
* **Temporal** for time-series data with lags and changing effects over time.
* **Multi-environment** for many groups (products, regions, segments) observed as snapshots, sharing one causal structure.
* **Multi-environment temporal** for many groups each tracked over time (panel data).

The builder detects which types your data supports and recommends the most specific one.

**Advanced configuration** lets you refine the model before training:

* **Variable roles** — Mark pure drivers as **Sources** (exogenous factors the business cannot directly control, e.g., gender or partner status) and pure outcomes as **Targets**. Setting these correctly constrains the model to respect reality.
* **Known relationships** — Rules you already know about the system that you want the model to respect.
* **Variable ordering** — Constraints that tell the system some variables must logically come before others (e.g., a customer must have internet service before they can have streaming), narrowing the search space.

**What happens during training:** RootCause prepares the data, searches for plausible causal structure, tests for latent confounders (hidden common causes), fits equations to the discovered relationships, and packages the result into a Digital Twin ready for simulation.

**Why this matters:** The graph is the structure; the twin is the operational model. This is where cause-and-effect understanding becomes a tool for decision support.

See: [Creating a Digital Twin](/user-guide/creating-digital-twin), [Digital Twin (Core Technology)](/core-technologies/digital-twin-and-simulations)

***

## 6. Run Simulations

Once the twin exists, RootCause becomes actionable. Simulations are the payoff for all the prior work: connecting data, building ontology, preparing the 360 Table, and discovering causes.

Static twins support seven simulation types:

| Simulation                   | Question it answers                                                           |
| ---------------------------- | ----------------------------------------------------------------------------- |
| **Prediction**               | "What is the likely outcome for this specific case?"                          |
| **Intervention**             | "What happens if we do X?"                                                    |
| **Optimization**             | "What is the best action given goals and constraints?"                        |
| **Best Action**              | "What is the smallest change needed to hit a target?"                         |
| **Explanation**              | "Why did this outcome happen?" (works backward from outcome to likely causes) |
| **Root Cause Analysis**      | "Which upstream drivers are behind this outcome?"                             |
| **Anomaly Scan & Diagnosis** | "Which records look abnormal, and why?"                                       |

Temporal twins run a time-aware family of their own. Available today: **Forecast** ("What will happen over time?"), **Temporal Intervention** ("How does a time-bounded change play out?"), and **Causal Health Monitor** ("Is the system drifting from its expected causal behavior?"), with time-aware counterparts of the remaining types rolling out. Panel twins run per-environment variants of the same families.

**Why this matters:** This is the main decision surface of the system. Everything before this step was preparation — simulations are where you get answers.

See: [Simulations](/user-guide/simulations)

***

## 7. Produce Reports

The last step is reporting. Reports are not just presentation — they are documentation of the analytical work. A report packages the model's conclusions into an auditable narrative that others can review, challenge, and build on.

Reports can include:

* Headings and narrative text
* Live widgets — charts, KPIs (headline metrics), and tables
* Evidence links and inline mentions of workspace objects (Data Views, Digital Twins, simulation runs)
* Code blocks for technical documentation

Widgets can draw from Data Views, Digital Twin results, or custom queries, and they update when underlying data changes. Reports can be exported to PDF for sharing outside the platform.

**Why this matters:** Analysis that lives only in the Simulations tab gets forgotten. Reports make findings shareable, auditable, and connected to the evidence that produced them.

See: [Reports](/user-guide/reports)


# Quick Start Tutorial

Your First Analysis

This tutorial walks through all seven steps of the RootCause workflow using sample data. Download the two CSV files below — they represent customer demographics and subscription information for a fictional telecoms company.

{% file src="/files/oOa9U6C1e7nwpYruDlSZ" %}

{% file src="/files/KEiTi6YXSMtM3ycDnXWv" %}

***

### Step 1: Connect Data

Go to **Sources** and click **Import data**. Select **Local File Upload**, drag both CSV files onto the drop zone, and click **Upload**. RootCause will process the files and begin building the ontology automatically.

<figure><img src="/files/SPbCJ4FrE7lI25LTjjXn" alt="Two CSV files staged and ready to upload"><figcaption></figcaption></figure>

Full details: [Connect Data](/user-guide/connecting-data)

***

### Step 2: Build Ontology

Go to **Ontology**. RootCause has already scanned both datasets and built a semantic map — identifying that `Customer Id` appears in both files and linking them. Review the network to confirm the connections look right. No action is required to proceed.

<figure><img src="/files/nuN1X41N9vg3fdqIXvcT" alt="Ontology network showing two datasets linked through a shared Customer Id concept"><figcaption></figcaption></figure>

Full details: [Build Ontology](/user-guide/ontology-concepts)

***

### Step 3: Build 360 Table

Go to **Ontology** and look at the **Recommended Datasets** section in the right panel. Click the recommendation to create a joined view of both datasets in one click. RootCause generates the join recipe automatically — you can inspect and edit it in the Operations editor.

<figure><img src="/files/aIbmFZgv68e9rzKC31Zq" alt="The joined dataset with its Operations panel showing the auto-generated left join on Customer Id"><figcaption></figcaption></figure>

Full details: [Build 360 Table](/user-guide/data-views)

***

### Step 4: Build Causal Graph

Causal discovery runs when you build a Digital Twin. Go to **Digital Twins** and click **New Digital Twin** (or, on the Ontology page, click **Create & build twin** on the recommended dataset — it opens the same builder with the view pre-selected). Keep the default method — **Discover from data** — and pick your joined Data View with **Static** as the type. The result of this run — a directed graph of cause-and-effect relationships — will land on the twin's **Relationships** tab, where you can click any node to see its top drivers and path analysis.

<figure><img src="/files/OxDnZRTdcCjFAt2cHk78" alt="The Relationships view: the discovered causal graph beside the relationships table"><figcaption></figcaption></figure>

Full details: [Build Causal Graph](/user-guide/causal-graph)

***

### Step 5: Build Digital Twin

In the builder's final **Review & run** step, click **Discover & train**. This one action runs causal discovery and trains the model. Training runs a sequence of stages and takes a few minutes. When it completes you'll see a model fit score and a set of suggested simulations.

<figure><img src="/files/HPoj0HwRocOyx7Mm7BJW" alt="The builder&#x27;s Review &#x26; run step, recapping the data and variables, with the Discover &#x26; train button"><figcaption></figcaption></figure>

Full details: [Build Digital Twin](/user-guide/creating-digital-twin)

***

### Step 6: Run Simulations

From your Digital Twin, click the **Simulations** tab and then **New Simulation**. Try typing a plain-language question — for example, "What happens to churn if we give away free tech support?" — and click **Generate Scenario**. Review the generated configuration and run it.

<figure><img src="/files/H5N3qITBXdHyrsUIA4Ch" alt="New Simulation screen showing the Generate from Query field, Quick Start, and the simulation type cards"><figcaption></figcaption></figure>

Full details: [Run Simulations](/user-guide/simulations)

***

### Step 7: Produce Reports

Go to **Reports**, click **New report**, and choose **Generate with AI**. Describe the report you want — for example, "Causal analysis of churn drivers and the effectiveness of service interventions" — and use `@` to reference your Digital Twin so the draft is grounded in it. RootCause produces a structured report with an Executive Summary and evidence-linked findings. Export to PDF to share it.

<figure><img src="/files/qcGJIgAOj7eecfNE1IWR" alt="Reports home with the New report button"><figcaption></figcaption></figure>

Full details: [Produce Reports](/user-guide/reports)

***

### What success looks like

If you followed all seven steps, you now have: two datasets linked through a shared `Customer Id` in the ontology, one joined Data View, and a trained Digital Twin with a model fit score on its Evaluation tab. Your simulation run shows a **Completed** status with an AI summary of the effect and the detailed result sections below it — and it stays in the Simulations tab's run list to revisit or export. From here, the same loop applies to your own data: connect it, review the ontology, build the view, train the twin, and start asking what-if questions.


# Connect Data

Connecting data is the first step in the seven-step workflow. Add data by uploading files directly or by connecting to an external source. RootCause supports connecting to databases, data warehouses, cloud storage or APIs.

***

## The Import Manager

Open the **Sources** section in the top navigation bar and click **Import data**. The Import Manager opens with two tabs:

* **Current Imports** — data sources already connected to this workspace
* **New Import** — add a new source

Filter by category: **All Sources**, **Databases**, **Cloud Storage**, **File Upload**, and **APIs & Services**. Alongside the external connectors, the list also offers **From Organization** — reuse datasets that already exist in your organization — and **Web Research**, which builds a table from AI-driven web research.

<figure><img src="/files/Hv6OfYz7QpLEm4kmK7V8" alt="Import Manager showing all available data source connectors"><figcaption><p>The Import Manager lists all available connectors. Sources marked Setup need credentials configured before use.</p></figcaption></figure>

***

## File Upload

File upload is the quickest way to get started. RootCause accepts tabular files (CSV, TSV, Parquet, JSON, Excel, ODS), documents (PDF, Word, PowerPoint, Markdown, plain text), images, and video files.

1. In the Import Manager, click **Local File Upload**
2. Drag files onto the drop zone, or click to browse

<figure><img src="/files/iqYswMKDW2Km7cfqiScq" alt="File upload drop zone"><figcaption><p>Drop files onto the zone or click to browse. You can add multiple files at once.</p></figcaption></figure>

3. Files appear in a list with names and sizes — remove any with the **×** button
4. Click **Upload (n)** to start the transfer

<figure><img src="/files/SPbCJ4FrE7lI25LTjjXn" alt="Two files staged and ready to upload"><figcaption><p>Files staged and ready. The Upload button shows the number of files queued.</p></figcaption></figure>

Upload progress is tracked in the Import Manager's **Current Imports** tab. When all files show "Completed", ontology processing begins automatically in the background.

<figure><img src="/files/H2eA9lNLuIvBevOu1nD3" alt="The Import Manager&#x27;s Current Imports tab showing both CSV files completed, with row and column counts"><figcaption><p>Current Imports. Each file reports its size, rows, and columns once the upload completes; <strong>View</strong> opens the imported source.</p></figcaption></figure>

***

## What happens after upload

RootCause processes imported data in three steps:

1. **Schema detection** — column types are inferred (Number, Text, DateTime, Boolean, Category)
2. **Ontology building** — each column becomes a concept; columns with shared names or matching patterns across datasets are flagged for review
3. **Data Views created** — a default Data View is generated for each dataset; datasets that share an identifier column get a recommended joined view (covered in [Step 3: Build 360 Table](/user-guide/data-views))

When processing finishes, the **Sources** page lists your datasets with row counts, sizes, and an analysis status; the recommended join appears on the Ontology page's **Recommended Datasets** panel.

<figure><img src="/files/B1gupZ4gJGpdEgD52Xjv" alt="The Sources page after upload showing both datasets with 4,998 rows each, sizes, and analysis status dots"><figcaption><p>Sources after processing: both datasets imported and analyzed. The journey card in the corner offers the next steps — understand why, build a report, or build an app.</p></figcaption></figure>

***

## Data Connectors

For live, continuously synced data, connect directly to your source system. Each connector requires credentials — click **Setup** next to the connector name to configure.

**Databases**

* [PostgreSQL](/data-connectors/postgresql)
* [MySQL](/data-connectors/mysql)
* [MongoDB](/data-connectors/mongodb)

**Data Warehouses**

* [Snowflake](/data-connectors/snowflake) *(Beta)*

**Cloud Storage**

* [Amazon S3](/data-connectors/s3)
* [Azure Data Lake](/data-connectors/azure-data-lake)
* [Google Cloud Storage](/data-connectors/google-cloud-storage) *(Beta)*

**APIs & Services**

* [REST API](/data-connectors/rest-api)

**Coming soon:** BigQuery, Databricks, Azure Synapse, Redshift, Salesforce, Hubspot, NetSuite, Kafka

***

## Live Data Sync

After connecting a source, configure its sync frequency — manual, hourly, daily, weekly, or monthly. When a sync runs, all dependent Data Views and analyses update automatically.

***

## Next steps

By the time import finishes, RootCause has already built a first-pass ontology. [Step 2: Build Ontology](/user-guide/ontology-concepts) covers how to review the auto-detected concepts, merge columns that represent the same thing, and classify identifiers and time fields.

After that, [Step 3: Build 360 Table](/user-guide/data-views) shows how to turn those datasets into a single joined table ready for causal analysis — using the recommended join RootCause has already prepared.


# Build Ontology

When your data finishes importing, RootCause automatically builds an ontology. It scans every dataset, identifies each column's type and role, and maps connections between columns that represent the same concept across different datasets. You do not need to create it — it is ready by the time your data is processed.

***

## What the ontology does

The ontology is the semantic layer that makes everything downstream possible. When "customer\_id" in your sales data and "cust\_id" in your support data are recognized as the same concept, RootCause can join those datasets automatically. When a column is classified as a Time concept, causal discovery respects temporal ordering. When a column is classified as an Identifier, it is used as a join key rather than treated as a variable in the causal model.

***

## Reviewing your ontology

Open **Ontology** in the top navigation bar. The **Network** visualization shows a relationship graph: datasets appear as colored clusters, concepts as labeled nodes, and edges between them show which concepts are shared across sources.

<figure><img src="/files/nuN1X41N9vg3fdqIXvcT" alt="Ontology network view showing two dataset hubs, Customer Subscription info with 15 concepts and Customer Details with 7, connected through a shared Customer Id identifier"><figcaption><p>The ontology network. Each colored cluster is a dataset (Customer Subscription info with 15 concepts, Customer Details with 7); the node where they meet is the shared Customer Id identifier.</p></figcaption></figure>

The right panel groups the ontology's actions:

* **Recommended Datasets** — "Ways to combine your sources into datasets ready for analysis and digital twins": joins the platform has detected based on shared identifier concepts. This is the most important panel on the screen — it is the bridge between your ontology and Step 3.
* **Query your data** — search, filter, and combine concepts across datasets. Recent queries are kept in a history list below the button.
* **New Group / Compare** — group comparable concepts, with an **AI** option that proposes the grouping for you.
* **Derive** — derive a new concept from a SQL formula.

<figure><img src="/files/VgH1Y8d1xW2SKCokyR15" alt="The Ontology page in the Strata view, 21 concepts across 2 datasets, with the Recommended Datasets panel on the right proposing a Customer Subscription info combination tagged Static twin, above a View all recommendations link"><figcaption><p>A recommended dataset, tagged <strong>Static twin</strong>: the platform has detected the join between the two sources. <strong>View all recommendations</strong> opens the full card, the one-click path to Steps 3 and 4.</p></figcaption></figure>

***

## Concept classifications

Concepts can be classified as Identifier, Time, or Location — anything unclassified appears as Entity:

**Identifier** — unique keys that link records across datasets: Customer ID, Product SKU, Order Number. These serve as join keys and are not used as causal variables.

**Time** — temporal columns: Order Date, Timestamp, Created At. Defines event ordering for time-series analysis and temporal Digital Twins.

**Location** — geographic columns: City, Region, Postal Code. Enables location-based filtering and analysis.

**Entity** — everything without a specific classification: Revenue, Quantity, Churn, Monthly Charges. These are the variables that participate in causal relationships.

The visualization toggle at the top of the Ontology page offers three ways to browse the concepts: **Table**, **Strata**, and **Network** (shown above). A separate **Grouping** toggle controls how concepts are clustered in the view: by source **Dataset**, by dataset **Links**, by **ID** (identifier), or by **Time**.

In the graph, the legend distinguishes three kinds of node:

* **Identifier** — a concept used as a key to match records across datasets (Customer ID, SKU). Identifiers are how separate files get linked together.
* **Concept** — a single thing your data measures or describes, like Customer, Revenue, or Timestamp, unified across every dataset that mentions it.
* **Composite** — a concept built by linking identifiers or time dimensions across datasets, so columns from several sources can be used together in one calculation.

<figure><img src="/files/CHOvTabFZGFjRgxp90pZ" alt="Ontology Table view listing 21 concepts across 2 datasets with their type, classification, datasets, and last update, with Customer Id classified as an identifier"><figcaption><p>The Table view: concepts as a sortable table, the fastest way to check that identifiers and time fields have been correctly detected. Here Customer Id is the only classified concept, an identifier shared by both datasets.</p></figcaption></figure>

***

## Refining your ontology

For most projects the auto-generated ontology is accurate enough to proceed. If a concept has been misclassified, or if two columns that represent the same thing were created as separate concepts, you can correct this at any time — reclassify a concept, merge two into one, or split one that incorrectly combines two different things. Related concepts can also be organized into ontology groups — comparable measurements sharing a unit, categorical variants of the same field, or replicas of the same source column — so they are treated consistently in analysis.

***

## Export and reset

Two further tools sit at the bottom of the right panel:

* **Export ontology** — download the concept graph as **JSON** or **GraphML**, for use in external tools or as a snapshot before making large changes.
* **Reset ontology** — delete all concepts and re-run extraction for the workspace or chosen sources.

{% hint style="warning" %}
**Reset is destructive.** All manual refinements — reclassifications, merges, groups — are lost when the ontology is re-extracted. Export the ontology first if you want a record. Use reset only when the ontology has drifted too far to repair by hand.
{% endhint %}

***

## Next step

With the ontology in place, RootCause knows how your datasets connect. [Step 3: Build 360 Table](/user-guide/data-views) walks through creating the single analysis-ready dataset that the causal engine trains on.


# Build 360 Table

Causal discovery requires a single, coherent table that represents the domain you want to model. If your data lives across multiple datasets — customers in one file, transactions in another — you need to join them before the engine can work.

RootCause calls this joined table a **Data View**. The friendly name for it in this workflow is the **360 Table**: one row per entity of interest, with all the variables you want to analyze in a single flat structure.

The good news: RootCause builds it for you. After the ontology runs, it has already identified which datasets share common identifiers and can recommend a join recipe ready to use in one click.

***

## The recommended path

After the ontology finishes processing, open the **Datasets** section in the top navigation bar.

<figure><img src="/files/oby2E0DWQPkYGTsZwCu2" alt="Datasets list showing two auto-generated single-source views and the joined Customer Subscription info × Customer Details dataset"><figcaption><p>Two single-source Data Views were created automatically during ontology processing; the joined dataset was created from the ontology's recommendation.</p></figcaption></figure>

You will see:

* **Auto-generated views** — one per dataset, created automatically, with zero operations (a direct pass-through to the raw data).
* **Recommended Datasets** — on the Ontology page's right panel, RootCause identifies datasets that share an identifier and proposes a join. Click the recommendation to create the joined view instantly.

The recommendation is derived from the ontology: when two datasets share the same identifier concept (for example, `Customer Id`), RootCause proposes joining them on that field, with the larger dataset as the main table.

***

## The Operations editor

Clicking a recommendation creates the view and opens it in the Operations editor.

<figure><img src="/files/aIbmFZgv68e9rzKC31Zq" alt="The joined dataset with its data preview and the Operations panel showing two source datasets and an auto-generated left join on Customer Id"><figcaption><p>The joined view with its Operations panel: two source datasets joined on Customer Id, 4,998 rows out. The join type, key columns, and table order are all editable.</p></figcaption></figure>

The editor shows your recipe as a visual graph:

* **Source nodes** (blue cards) — one per input dataset.
* **Operation nodes** — transformations applied in sequence. The recommended view starts with a single JOIN node: *"Left join on Customer Subscription info - customerID = Customer Details - customerID."*
* **Bezier edges** connecting each source into the join.

**The recipe is fully editable.** Each node has pencil (edit) and trash (delete) controls. You can change the join type from left to inner, switch which table is primary, or add further operations — a filter to exclude inactive records, an aggregate to roll up transaction-level data to customer level, or a derived column calculation.

The accept-as-is path takes one click. The edit path uses the same interface. You do not need to rebuild from scratch to change what the platform inferred.

***

## Adding operations manually

To build a view from scratch, or to add steps to an existing view, use **Add Source** and **Add Operation** in the top-right of the Operations panel. Available operations include:

| Category               | Operations                                                                                                              |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Data combination       | Join, Time Series Join, Concatenate                                                                                     |
| Filtering and cleaning | Filter, Remove Duplicates, Drop Nulls, Impute Nulls, Clip Outliers                                                      |
| Reshaping              | Aggregate, Sort, Transpose Panel                                                                                        |
| Column manipulation    | Split Column, Drop Columns, Replace Values, Cast Type, Normalize                                                        |
| Categories             | Map Categories                                                                                                          |
| Time series            | Interpolate Time, Time Series Aggregate, Frequency Analysis, Cyclic Aggregate, Vertical Diff, Date Span, Cumulative Sum |
| Arrays                 | Decompose Array, Consolidate into Array, Explode Array (long), Aggregate Array                                          |
| Custom logic           | SQL Query                                                                                                               |

The specialized time-series and array operations, briefly:

* **Time Series Join** — join two sources on time, with exact, nearest (as-of), or granularity-based matching.
* **Transpose Panel** — collapse a long-format panel dataset into a single wide-format time series, one column per environment and value.
* **Frequency Analysis** — run FFT or Welch's method over a time series to surface its frequency content.
* **Cyclic Aggregate** — group rows by a cycle component (hour of day, day of week, …) and aggregate, revealing the shape of a cycle.
* **Vertical Diff** — the change from each row to the next along the time axis (first difference).
* **Date Span** — the interval between two date columns in the same row, in the unit you choose.
* **Cumulative Sum** — a running total along the time axis.
* **Decompose Array** — spread an array column into one scalar column per position, or one boolean column per distinct value.
* **Consolidate into Array** — merge several scalar columns into one array column.
* **Explode Array (long)** — unnest an array column into one row per element.
* **Aggregate Array** — reduce each row's array to a single value (mean, sum, min, max, median, or count).

Operations execute in sequence — each takes the output of the previous step as input. Preview results after each addition to verify the output before continuing.

***

## What's next

When the view looks right, you're ready for causal discovery. It runs when you build a Digital Twin from this view — either click **Create & build twin** on the Ontology page's recommended dataset, or start from **Digital Twins → New Digital Twin** and pick the view in the builder.

Next step: [Step 4: Build Causal Graph](/user-guide/causal-graph)


# Build Causal Graph

When you build a Digital Twin with the **Discover & train** action, RootCause runs causal discovery across all the variables in your 360 Table. The output is a **causal graph** — a directed map of cause and effect relationships in your data.

The graph answers a different question from standard analytics. Correlation tells you which variables move together. The causal graph tells you which ones *drive* others, which direction influence flows, and where the real leverage points are.

For the technical background on how discovery works, see [Causal Discovery](/core-technologies/causal-discovery).

***

## Starting discovery

Discovery runs as part of building a Digital Twin, and there are two ways into the same builder:

* **From the Ontology page** — the **Recommended Datasets** panel proposes analysis-ready views; **Create & build twin** saves one as a dataset and opens the twin builder with it pre-selected.
* **From the Digital Twins list** — click **New Digital Twin** and pick your Data View in the builder's data step.

Either way, keep the default **Discover from data** method and click **Discover & train** in the final step. RootCause discovers the causal structure and trains the model in one run, which takes a few minutes depending on dataset size. When it completes, open the twin's **Relationships** tab to review the discovered graph. [Step 5: Build Digital Twin](/user-guide/creating-digital-twin) walks through the builder itself.

***

## Reading the graph

<figure><img src="/files/OxDnZRTdcCjFAt2cHk78" alt="The Relationships view: the discovered causal graph on the left and the relationships table on the right"><figcaption><p>The Relationships view: the causal graph beside the relationships table — 31 relationships here, with a further 140 candidate connections tested and ruled out. Clicking any node reveals what drives it and how much each driver contributes.</p></figcaption></figure>

The graph has two elements:

* **Nodes** — each node is a variable from your Data View
* **Edges** — lines between nodes represent causal relationships

**Edge types:**

| Edge                    | Meaning                                               |
| ----------------------- | ----------------------------------------------------- |
| A → B (solid arrow)     | A causes B — direction is well-evidenced              |
| A — B (undirected line) | A and B are related, but direction is uncertain       |
| A ↔ B (bidirectional)   | A and B share an unobserved common cause (confounder) |

Nodes are color-coded by data type. Clicking any node opens a **Variable Details** panel on the right, showing how well the variable is explained, which variables drive it, and a Sankey diagram of the causal paths flowing into or out of it.

***

## Reviewing the graph

The graph opens as a flowchart of draggable nodes on a pannable canvas. Click a node to highlight its direct connections. To navigate:

* **Canvas controls** — zoom in and out, fit the graph to the window, and lock the canvas against accidental dragging. **Recompute layout** redraws the arrangement after you have moved nodes around. None of these change the model itself.
* **Search variables** — find a node by name in a large graph.
* **Path Analysis** — from a node's Variable Details panel, Sankey diagrams show how causal influence flows into a target variable (inbound) or out of a source variable (outbound). The width of each flow indicates contribution weight.

Start with your key outcome variable (churn, revenue, conversion rate). Click it to see what drives it directly and what the major inbound paths are. Then expand outward.

***

## Refining with domain knowledge

The discovered graph is a statistical starting point. You can incorporate what you already know:

**Known relationships** — if you're certain a causal link exists (from an experiment, physical law, or domain expertise), declare it. RootCause will respect the constraint when re-running discovery.

**Blocked relationships** — if a relationship is impossible (for example, customer age cannot be caused by purchase behavior), block it. The algorithm will exclude that edge.

To add constraints, open the twin's **Config** tab and click **Modify model**. In the builder's **Add domain knowledge** step, add your known or blocked relationships, then choose **Re-discover & train**. The graph updates to reflect both the statistical evidence and your domain rules.

**Undirected edges** (A — B) are flagged for human review. If you know which direction causality runs, add a Known relationship to resolve it. If you're uncertain, it's fine to leave it — the model handles it.

***

## Evaluating model quality

The **Evaluation** tab shows how well each variable is predicted by its causes in the graph:

* **Categorical variables:** Accuracy, AUC
* **Numeric variables:** MSE, MAE, R²

Variables with weak metrics may need more data, additional drivers, or a refinement pass on the graph structure.

***

## Next step

With the causal graph reviewed and refined, you're ready to fit it into a runnable model.

Next step: [Step 5: Build Digital Twin](/user-guide/creating-digital-twin)


# Build Digital Twin

The causal graph from Step 4 is a structural map — it shows which variables influence which others. A **Digital Twin** takes that structure and fits it with equations, giving you a runnable model you can interrogate with simulations. In RootCause, both happen in one run of the twin builder: **Discover & train** discovers the graph and trains the model in a single action.

Building the Digital Twin is largely automatic. Your main decisions are: which data and type of twin to build, what you already know about the causal structure, and which training options to enable.

***

## Open the twin builder

There are two ways into the same builder:

* From the top navigation bar, open **Digital Twins**, then click **New Digital Twin**.
* From the Ontology page's **Recommended Datasets** panel, click **Create & build twin** — this saves the recommendation as a dataset and opens the builder with it pre-selected.

<figure><img src="/files/LDrawcpEVkcWCUwOmZ3Z" alt="Digital Twins list showing one trained twin, Digital Twin - Customer Subscription info x Customer Details, with a New Digital Twin button"><figcaption><p>The Digital Twins list. Click <strong>New Digital Twin</strong> to begin.</p></figcaption></figure>

***

## The builder wizard

The builder walks four steps.

<figure><img src="/files/HPoj0HwRocOyx7Mm7BJW" alt="The twin builder&#x27;s Add domain knowledge and Review &#x26; run steps, with a plain-language recap of the data and variables and the Discover &#x26; train button"><figcaption><p>The twin builder. Choose a method, pick the data, add what you know, then review and run.</p></figcaption></figure>

**1. How do you want to build it?** Two methods:

* **Discover from data** *(default)* — causal discovery finds the graph from your data; anything you add is prior knowledge it must respect.
* **Build a graph by hand** — draw the causal graph yourself (or import it from a CSV) and train directly on it, with no discovery step.

**2. Choose your data.** Pick the Data View — the 360 Table you built in Step 3 — and the twin type:

| Type                       | When to use                                                                                         |
| -------------------------- | --------------------------------------------------------------------------------------------------- |
| Static                     | Data without meaningful time ordering — customer attributes, cross-sectional snapshots, survey data |
| Temporal                   | Time-series data where variables influence each other across periods — trends, lags, forecasting    |
| Multi-environment          | Many distinct groups (products, regions, stores) observed as snapshots                              |
| Multi-environment temporal | Many groups tracked over time — panel data                                                          |

The builder ticks every type your data supports and selects the most specific; types the data cannot support are disabled. Temporal types ask for a **time column**; multi-environment types ask for **environment columns**. See [Types of Digital Twins](/more-details/build-digital-twin/twin-types).

**3. Add domain knowledge** *(with discovery)* **or build your causal graph** *(by hand)*. On the discovery path this step is optional: set variable roles (drivers and outcomes), add known or impossible links, and declare event order — hints discovery must respect. On the by-hand path, this is where you draw the model itself.

**4. Review & run.** A plain-language recap of the data, variables, roles, and prior knowledge, with validation checks. **Advanced settings** holds the training options, algorithm versions, and parallelism controls — see [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration).

**Training options** (under Advanced settings):

* **Account for hidden factors** (confounder modeling) — detects and accounts for hidden variables that influence multiple observed variables. Recommended on.
* **Show the formula** (equation discovery) — fits symbolic equations to describe each relationship precisely. Recommended on.
* **Delayed effects** (lag discovery; temporal types, experimental) — finds effects that appear one or more time steps after their cause.

***

## Start training

The run button's label depends on the method you chose in step 1:

* **Discover & train** — runs discovery, then trains — one action. This is the normal path.
* **Train model** — trains directly on the graph you drew, with no discovery step.

(When modifying an existing twin, the same actions appear as **Re-discover & train** and **Retrain model**.)

Click **Discover & train** to proceed.

***

## Training progress

Training runs a sequence of stages — which ones depends on the training options you enabled.

<figure><img src="/files/hVamBs2uEKANP9UgigWF" alt="Training in progress: Training Model at the Latent Confounder Modeling stage, 2 of 5 stages done, with the full stage list and progress bars below"><figcaption><p>Training progress. The stages run in sequence; each can take from seconds to several minutes depending on dataset size.</p></figcaption></figure>

| Stage                                      | What happens                                          |
| ------------------------------------------ | ----------------------------------------------------- |
| Preparing Data                             | Variables standardized, missing values handled        |
| Causal Discovery                           | Statistical tests identify cause-and-effect structure |
| Latent Confounder Modeling *(if enabled)*  | Hidden common causes detected and modeled             |
| Symbolic Equation Discovery *(if enabled)* | Equations fitted to quantify each relationship        |
| Building & Evaluating Model                | Final model assembled and quality metrics computed    |

Training time ranges from a few minutes for small datasets to longer for large ones. You can navigate away — training continues in the background, and the twin's page shows live stage progress until it finishes.

***

## Review the trained twin

When training completes, you land on the Digital Twin overview.

<figure><img src="/files/lWmrXR4b3B8sbRtL0AXH" alt="Digital Twin Home after training, showing the causal graph and cards for Configuration, Versions, Simulations, Graph explorer, and Model evaluation"><figcaption><p>The twin Home after training: Configuration (19 variables, 31 relationships), Versions (v1.0.0), Simulations, Graph explorer, and Model evaluation (69.6% model fit).</p></figcaption></figure>

The overview shows:

* **Configuration** — the twin type, variable count, and relationship count.
* **Versions** — each training run creates a new version. Previous versions are retained and can be compared or switched between.
* **Simulations** — run interventions, predictions, and the other simulation types against the trained model.
* **Graph explorer** — which variables influence which, and how many candidate relationships were tested and ruled out.
* **Model evaluation** — overall model fit. A score above 60% is generally good; lower scores may indicate missing variables or data quality issues worth investigating.

***

## Next step

Your Digital Twin is trained and ready. Now you can run simulations to ask what-if questions, find key drivers, and test interventions.

Next step: [Step 6: Run Simulations](/user-guide/simulations)


# Run Simulations

With a trained Digital Twin, you can ask questions that standard analytics cannot answer: not just what happened, but why — and what would happen if you acted differently. Simulations are how you do that.

Each simulation type is designed for a different kind of question. You can describe what you want in plain language and let RootCause generate the configuration, or choose a simulation type directly and configure it yourself.

For the technical background, see [Digital Twin & Simulations](/core-technologies/digital-twin-and-simulations).

***

## Starting a simulation

From your Digital Twin, click the **Simulations** tab, then **New Simulation**.

<figure><img src="/files/H5N3qITBXdHyrsUIA4Ch" alt="New Simulation screen showing the Generate from Query field, the Quick Start section with a Generate suggestions button, and the first simulation type cards, with the run list on the right"><figcaption><p>The New Simulation panel. Type a plain-language question to auto-generate a configuration, generate Quick Start suggestions, or choose a simulation type directly.</p></figcaption></figure>

**Generate from Query** — type a question ("What happens to churn if we give away free tech support?") and click **Generate Scenario**. RootCause maps your question to a simulation type and pre-fills the configuration. Review and adjust before running.

**Quick Start** — click **Generate suggestions** and RootCause proposes ready-to-run simulation ideas based on the relationships in the model. Pick one to load it as a pre-filled configuration.

***

## Simulation types

<figure><img src="/files/6Nt6NEZvKlHAG7hXFq4h" alt="The OR CHOOSE A TYPE grid with the seven static simulation type cards: Prediction, Intervention, Optimization, Best Action, Explanation, Root Cause Analysis, and Anomaly Scan &#x26; Diagnosis"><figcaption><p>The seven simulation types available on a static twin.</p></figcaption></figure>

| Type                                                                                       | Question it answers                                                 |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| [**Prediction**](/more-details/digital-twin/simulation-types/prediction)                   | What outcome is most likely for a specific case?                    |
| [**Intervention**](/more-details/digital-twin/simulation-types/intervention)               | What happens if we change variable X?                               |
| [**Optimization**](/more-details/digital-twin/simulation-types/optimization)               | What combination of inputs best achieves our goal?                  |
| [**Best Action**](/more-details/digital-twin/simulation-types/best-action)                 | What is the minimum change needed to reach a target outcome?        |
| [**Explanation**](/more-details/digital-twin/simulation-types/explanation)                 | What drives this outcome, and how much does each driver contribute? |
| [**Root Cause Analysis**](/more-details/digital-twin/simulation-types/root-cause-analysis) | What caused this specific observed outcome?                         |
| [**Anomaly Scan & Diagnosis**](/more-details/digital-twin/simulation-types/anomaly-scan)   | Which variables are behaving anomalously, and why?                  |
| **Forecast** *(temporal twins only)*                                                       | How will this variable evolve over time?                            |
| **Temporal Intervention** *(temporal twins only)*                                          | How does a time-bounded intervention affect outcomes over time?     |
| **Causal Health Monitor** *(temporal twins only)*                                          | What emerging issues should I be alerted to before they escalate?   |

On temporal twins the picker swaps in a time-aware family. The temporal types available today are **Forecast**, **Temporal Intervention**, and **Causal Health Monitor**; counterparts for the remaining static types are rolling out. See [Temporal Simulations](/more-details/digital-twin/temporal-simulations).

Panel (multi-environment) twins get per-environment **Panel** variants of the available types. Each runs the analysis across the twin's environments, so you can see where an effect holds and where it differs.

***

## Intervention

Tests "what if" scenarios. Set a change to one or more variables; the simulation propagates that change through the causal graph and shows the effect on your outcomes.

**How to run:**

1. Select **Intervention**
2. Add interventions — choose a variable, pick the change type (a **Target value** or a **Relative change**), and set the new value
3. Optionally add conditions ("only for premium customers") to control which records the change applies to
4. Define metrics to measure — built in natural language, a visual builder, or SQL (see the [Intervention](/more-details/digital-twin/simulation-types/intervention) page for the metric builder)
5. Click **Run Simulation**

**Results:** Side-by-side baseline vs. intervention comparison with confidence intervals and an effect breakdown by causal path. Full walkthrough: [Intervention](/more-details/digital-twin/simulation-types/intervention).

***

## Optimization

Finds the best combination of inputs to maximize or minimize an objective, given constraints you define.

**How to run:**

1. Select **Optimization**
2. Set the objective — variable to optimize, direction (maximize/minimize), measurement
3. Define decision variables (what the optimizer can change)
4. Set constraints (limits that must be respected)
5. Click **Run Simulation**

**Results:** Recommended values for each decision variable, expected outcome at the optimum, and trade-off analysis if you have multiple objectives.

***

## Best Action

Finds the minimum change to a specific case that would flip the predicted outcome. Useful for individual-level decisions: what is the smallest intervention that would prevent this customer from churning?

**How to run:**

1. Select **Best Action**
2. Provide sample records (specific cases to analyze)
3. Set the target outcome you want to achieve
4. Configure constraints (what can and cannot be changed)
5. Set a maximum number of changes to keep recommendations practical
6. Click **Run Simulation**

**Results:** Specific recommended changes per case, predicted outcome if applied, and confidence level.

***

## Explanation

Identifies the drivers of an outcome and quantifies how much each contributes. Three modes:

* **Discovery** — "What influences outcome B?" Finds all causes of a specific variable.
* **Directional** — "How does A affect B?" Traces the specific causal path between two variables.
* **Impact** — "What does A affect?" Finds all downstream effects of a specific variable.

<figure><img src="/files/qoww4W0f7orDfpJ4DJND" alt="A completed Explanation run for the question What are the main drivers of customer churn: the Key Driver Analysis bar chart of relative causal contribution to Churn, with Contract highest, and the ranked driver table beneath it with contribution, range, and confidence per driver"><figcaption><p>A completed Explanation. The Key Driver Analysis ranks each variable's causal contribution to churn: Contract leads at 44.4%, then InternetService (25.4%) and OnlineSecurity (17.0%), each with a range and a confidence rating.</p></figcaption></figure>

**How to run:**

1. Select **Explanation**
2. Choose the mode
3. Select source and/or target variables
4. Optionally add segment filters
5. Click **Run Simulation**

**Results:** Causal paths with contribution weights, ranked driver table, and segmented breakdowns if requested.

***

## Prediction

Generates a predicted outcome for a specific case, with uncertainty estimates.

**How to run:**

1. Select **Prediction**
2. Enter input data (values for known variables)
3. Select target variables to predict
4. Click **Run Simulation**

**Results:** Most likely outcome per target variable, confidence intervals, and full probability distribution.

***

## Root Cause Analysis

Traces a specific observed outcome backward through the causal graph to identify its underlying causes. Different from Explanation, which identifies general drivers — Root Cause Analysis focuses on why a particular outcome occurred. Full walkthrough: [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis).

***

## Anomaly Scan & Diagnosis

Scans all variables for anomalous behavior and uses the causal graph to diagnose which upstream variables are responsible. Useful for monitoring and incident investigation. Full walkthrough: [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan).

***

## Forecast *(temporal twins only)*

Projects variables forward in time using causal relationships and temporal patterns.

**How to run:**

1. Select **Forecast**
2. Select target variables
3. Set the forecast horizon (number of periods ahead)
4. Set confidence level for uncertainty bands
5. Click **Run Simulation**

**Results:** Time series of projected values with widening confidence bands.

***

## Temporal Intervention *(temporal twins only)*

Scripts an intervention that happens within a specific time window, and shows how effects build, peak, and decay over time.

***

## Causal Health Monitor *(temporal twins only)*

Watches a time series — either observed data you supply or the twin's own forecast — and scores every variable at every timestep against the model's expectations. The result is a health timeline with per-variable alerts, a causal ordering of which alerts drove which, and (optionally) an automatic Root Cause Analysis for what it flags. Use it to catch emerging issues before they escalate.

***

## Natural language queries

For any simulation type, you can describe the scenario in plain language and let RootCause generate the configuration. Click **Generate Scenario**, review the interpretation, adjust if needed, and run.

***

## Reading results

All simulations include confidence intervals — wider intervals mean more uncertainty. Intervention and optimization results always compare against a baseline, showing the marginal effect of your action rather than the absolute outcome.

Results can be exported to PDF or saved for reference. Saved simulations appear in the Simulations tab of your Digital Twin and can be re-run or included in Reports.

***

## Finding past simulations

The **Simulations** list on the Simulations tab keeps every run. To find one:

* Filter by outcome (**All**, **Succeeded**, **Failed**), by simulation **Type**, by **Variable**, or by time range.
* The **Ran by** toggle separates runs started by **People** from runs started by **Apps** (see [Applications](/more-details/applications)).
* Tick the checkbox on one or more runs to select them for report export.

***

## Next step

Simulations produce findings. The next step is to turn those findings into a document you can share.

Next step: [Step 7: Produce Reports](/user-guide/reports)


# Produce Reports

Simulations produce findings. Reports package those findings into a document you can share — with an executive, a client, or a colleague who doesn't work in the platform.

RootCause reports are living documents. Charts and metrics stay connected to live data, so a report you build today reflects updated numbers tomorrow without manual edits. They also serve as an audit trail: by linking conclusions to specific Data Views, Digital Twins, and simulation runs, you document not just what you found but how you found it.

***

## Create a report

Open **Reports** in the top navigation bar and click **New report**.

<figure><img src="/files/qcGJIgAOj7eecfNE1IWR" alt="Reports home with the New report button and one report listed with a Ready status"><figcaption><p>The Reports home lists every report in the workspace with its owner and status. <strong>New report</strong> starts a draft.</p></figcaption></figure>

Two paths:

**Generate with AI** — describe the report in the text field (for example, "Causal analysis of churn drivers and the impact of service enhancement interventions") and type `@` to reference datasets, Data Views, or Digital Twins so the draft is grounded in that data. RootCause generates a structured report with an Executive Summary, section headings, and evidence-linked prose drawn from your workspace data.

**Build manually** — opens a blank editor. Build the report yourself using the editor toolbar.

<figure><img src="/files/7sM4b4wVwzia3TxzsYYF" alt="The New report screen on Generate with AI: a prompt field hinting to type @ to reference a dataset, data view, or digital twin, and a Generate report button"><figcaption><p>Generate with AI: describe the report and type <code>@</code> to ground it in your data — Enter generates.</p></figcaption></figure>

***

## The report editor

<figure><img src="/files/XhAcitc6JKpWj9iX2P1n" alt="The report editor showing a generated report titled Causal Drivers of Customer Churn and the Effectiveness of Service Interventions, with a formatting toolbar, Insert widget, Share, Export PDF and Save controls, a Contents outline on the right, and an Executive Summary whose key numbers are evidence links"><figcaption><p>A generated report in the editor. Sections are structured, the Contents rail tracks the outline, and the highlighted numbers are evidence links back to the underlying runs. The report can be edited freely after generation.</p></figcaption></figure>

The editor works like a modern document tool. Type to add text; use `/` to insert blocks:

* `/heading` — H1, H2, H3 for structure
* `/bullet` — bullet list
* `/quote` — block quote
* `/widget` — embed a live chart, KPI, or table from your workspace data

**Widgets** connect directly to Data Views and simulation results. A chart widget referencing a Data View updates automatically when the underlying data changes — no manual refresh or re-export needed.

**Mentions** — type `@` to reference workspace objects inline. `@Sales_2024` becomes a clickable link to that Data View; `@Q4_Simulation` links to a specific simulation run. Readers can follow the link to inspect the underlying analysis.

***

## Evidence and audit trail

For conclusions that will drive decisions, link them to evidence:

1. Select the text of a claim or recommendation
2. Click **Add Evidence**
3. Choose the source — Data View, Simulation, or Digital Twin
4. Select the specific object

The evidence link is embedded in the report. Readers can click through to verify the data behind each conclusion. This is what separates a report from a presentation: the reasoning is inspectable, not just asserted.

***

## Export and share

**PDF Export** — click **Export PDF** in the top right to generate a polished PDF snapshot. Suitable for sharing outside the platform with clients or leadership. The PDF is static — it captures the report at the moment of export.

**Within the platform** — click **Share** to control who can open the report. Add individual users or whole roles, each at **read** (view only), **write** (edit but not delete), or **full** (everything, including delete) access. The **General access** setting controls the report's share link: **Restricted** (only the owner and the people or roles added), **Workspace** (anyone with access to the workspace), **Organisation** (anyone in your organization), or **Anyone with the link** (no account needed). A new report starts Restricted. Anyone with access can view and navigate the evidence links.

***

## Suggested structure

Generated reports follow a standard pattern. For manually built reports, the same structure works well:

```
# Executive Summary
## Key Findings
## Recommendations

# Analysis
## Data Overview
## Causal Relationships
## Simulation Results

# Appendix
## Methodology
## Data Sources
```

Lead with conclusions — executives read the top. Provide supporting detail below for those who want it.


# Data Management

All analysis in RootCause starts with data. This section covers how to bring data into the platform and what happens to it once it arrives.

***

### Getting data in

[**Selecting Data**](/more-details/data-management/uploading-datasets)

Upload files — tabular formats (CSV, TSV, Parquet, Excel, ODS, JSON) as well as documents and media (see [File Uploads](/more-details/data-management/uploading-datasets/file-uploads) for the full list) — or connect to external databases and APIs. File uploads are instant; connected sources stay in sync automatically.

For step-by-step connector setup, see [Data Connectors](/more-details/data-management/uploading-datasets/data-connectors).

***

### Preparing for analysis

Once your data is in the platform, two further steps prepare it for causal analysis:

* [**Build Ontology**](/user-guide/ontology-concepts) — map column names across datasets to shared concepts so RootCause understands your data structure
* [**Build 360 Table**](/user-guide/data-views) — join, filter, and transform datasets into the analysis-ready view your digital twin will use

These are Steps 2 and 3 of the [seven-step workflow](/start-here/workflow).


# Selecting Data

RootCause adapts to your data in its current format, without requiring lengthy data engineering work.

**Upload a file**, and the platform automatically detects column types, identifies patterns, and prepares your data for analysis.

**Connect a database**, and your data stays in sync without manual exports.

<figure><img src="/files/Hv6OfYz7QpLEm4kmK7V8" alt="Import manager showing file upload area and database connector options"><figcaption><p>The import manager. Choose file upload for one-off imports or a database connector to keep data in sync automatically.</p></figcaption></figure>

If a connector you need is not yet supported, you can export from the source system and upload directly.

***

### Viewing a dataset

Click on any dataset to see its full details: schema (columns and data types), a data preview, row count, and column statistics.

<figure><img src="/files/cSA8sF4qPKTefaM0X0Ot" alt="Dataset detail view showing the data preview with per-column statistics for a joined view of 4,998 rows and 21 columns"><figcaption><p>The dataset detail view. Every column carries its type and value distribution; the panel on the right reports the sources, concepts, and operations behind the view.</p></figcaption></figure>

***

### Refreshing connected data

For connected sources, data can be kept current in two ways:

* **Sync Now** — click to refresh immediately
* **Schedule Sync** — set automatic refresh intervals (hourly, daily, weekly, monthly)

When a sync runs, RootCause pulls fresh data and updates all Data Views and analyses that depend on it.

***

### Schema detection

RootCause automatically analyzes your data to detect column types. This matters because causal discovery algorithms treat numbers, categories, and dates differently.

| Detected type | Description                                               |
| ------------- | --------------------------------------------------------- |
| Number        | Integers and decimals (revenue, counts, measurements)     |
| Text          | Strings and categorical values (names, IDs, labels)       |
| DateTime      | Dates and timestamps (order dates, event times)           |
| Boolean       | True/false values (flags, binary indicators)              |
| Category      | Columns with limited unique values (status, region, tier) |

Automatic detection is usually correct. If a column is detected incorrectly — ZIP codes detected as numbers, for example — open the dataset, click the column type, and select the correct type from the dropdown.

***

### Next steps

Once your data is uploaded:

1. Review the [ontology](/user-guide/ontology-concepts) RootCause built automatically — it links related data across sources
2. Create a [Data View](/user-guide/data-views) to transform and combine your datasets
3. [Build a Digital Twin](/user-guide/creating-digital-twin) using your prepared Data View


# File Uploads

The simplest way to get data into RootCause. Use file uploads for one-time analyses, spreadsheets from stakeholders, or exports from systems without native connectors.

**Supported formats:**

*Tabular data*

| Format    | Notes                                         |
| --------- | --------------------------------------------- |
| CSV / TSV | Comma- or tab-separated values                |
| Parquet   | Columnar format — recommended for large files |
| JSON      | JSON or newline-delimited JSON                |
| Excel     | `.xlsx` and `.xls` files                      |
| ODS       | OpenDocument spreadsheets                     |

*Documents*

| Format          | Notes                                |
| --------------- | ------------------------------------ |
| PDF             | Documents for analysis and reporting |
| Word            | `.docx` files                        |
| PowerPoint      | `.pptx` files                        |
| Markdown / Text | `.md`, `.markdown`, and `.txt` files |

*Media*

| Format | Notes                                                    |
| ------ | -------------------------------------------------------- |
| Image  | PNG, JPG, GIF, BMP, TIFF, and SVG                        |
| Video  | MP4, MOV, AVI, WebM, MKV, and other common video formats |

**To upload a file:**

1. Navigate to **Sources** and click **Import data**
2. Select **Local File Upload**, then drag and drop files into the upload area
3. Wait for the upload to complete
4. Review the detected schema

<figure><img src="/files/iqYswMKDW2Km7cfqiScq" alt="Import manager upload area ready for file drop"><figcaption><p>The upload area. Drag and drop files directly, or click to browse.</p></figcaption></figure>

**What happens on upload:**

1. The file is securely stored in your workspace's isolated data lake
2. Schema detection analyzes columns to determine data types
3. A data preview is generated for verification
4. The dataset becomes available across your workspace for Data Views, analysis, and reporting

<figure><img src="/files/cSA8sF4qPKTefaM0X0Ot" alt="Dataset detail view of the joined Customer Subscription info × Customer Details data, 4,998 rows across 21 columns, showing detected column types, per-column statistics, and a summary panel"><figcaption><p>The dataset view shows the detected schema, a preview with per-column statistics, and the summary panel: here the joined customer view, 4,998 rows across 21 columns.</p></figcaption></figure>


# Data Connectors

For data that changes frequently — sales transactions, user events, operational metrics — file uploads become tedious. Data connectors solve this by establishing a live link to your source systems.

Once connected, you can refresh data on demand or schedule automatic syncs. Your analyses stay current without manual intervention.

**Available connectors:**

* **Databases:** [PostgreSQL](/data-connectors/postgresql), [MySQL](/data-connectors/mysql), [MongoDB](/data-connectors/mongodb)
* **Data Warehouses:** [Snowflake](/data-connectors/snowflake) *(Beta)*
* **Cloud Storage:** [Amazon S3](/data-connectors/s3), [Azure Data Lake](/data-connectors/azure-data-lake), [Google Cloud Storage](/data-connectors/google-cloud-storage) *(Beta)*
* **APIs:** [REST API](/data-connectors/rest-api)

The Import Manager shows the full, current catalogue, including upcoming connectors marked **Soon** — see [Connect Data](/user-guide/connecting-data) for the list.

**To connect a data source:**

1. Navigate to **Sources** and click **Import data**
2. In the Import Manager, locate the connector type and click **Setup**
3. Enter connection credentials
4. Configure a sync schedule and save

<figure><img src="/files/Hv6OfYz7QpLEm4kmK7V8" alt="Import manager showing available connector types"><figcaption><p>The import manager. Select a connector type to begin the connection setup.</p></figcaption></figure>

***

### Next steps

Once your data is connected:

1. Review the [ontology](/user-guide/ontology-concepts) RootCause built automatically — it links related data across sources
2. Create a [Data View](/user-guide/data-views) to transform and combine your datasets
3. [Build a Digital Twin](/user-guide/creating-digital-twin) using your prepared Data View


# Digital Twin Build Reference

This section is the detailed reference for building a Digital Twin — the in-depth companion to [Step 5: Build Digital Twin](/user-guide/creating-digital-twin). It follows the order you actually work in: choose the data, understand the kind of twin it produces, set the configuration, and tune it for a good fit.

Everything here happens in the twin builder, a four-step wizard (how to build, choose your data, add domain knowledge, review and run). Two paths lead into it for a new twin: **New Digital Twin** on the Digital Twins list, or **Create & build twin** from the Ontology page's recommended datasets. A third, **Modify model** on an existing twin, reopens the same builder seeded with the current configuration and creates a new version when run.

* [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view) — the one choice that triggers everything, and what the platform auto-detects when it reads the file.
* [Types of Digital Twins](/more-details/build-digital-twin/twin-types) — Static, Temporal, and the two Multi-Environment variants, and how the platform decides which fits your data.
* [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration) — every control on the build screen: environments, fields, training options, algorithm versions, and variable roles.
* [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit) — the change-config, retrain, read-fit loop, and the levers that move the result most.

Once a twin is built, see [Configuration for Existing Twin](/more-details/digital-twin/configuration) and the other Digital Twin pages for working with it.


# Selecting your Data View

Building a digital twin begins with one choice: which data it learns from. Almost everything else on the build screen is then proposed for you.

In RootCause that data is a **Data View** — the analysis-ready table (the "360 table") you assembled in [Build 360 Table](/user-guide/data-views). When you select a Data View, the platform reads its structure and fills in a complete build configuration: the twin's type, how it handles time, how it groups the data, which variables to include, and how they relate. You review and adjust that proposal rather than build one from nothing.

***

## Starting a new digital twin

From the Digital Twins section, choose **New Digital Twin**. In the builder's **Choose your data** step, the one required choice is the **Data View** — select one and the rest of the configuration autofills.

<figure><img src="/files/N9cS305wxrLqLcgfngSC" alt="The builder&#x27;s first two steps: How do you want to build it with Discover from data selected, and Choose your data with the Data View picker set to Customer Subscription info x Customer Details and a Type selector where Static is marked Recommended and the time-based types are disabled"><figcaption><p>The builder's opening steps: pick the Data View and the platform marks which twin types the data supports, here Static as Recommended with the time-based types disabled.</p></figcaption></figure>

The **Name** fills in automatically from the data view's name — here, *Digital Twin - Customer Subscription info × Customer Details*. Leave it to auto-generate or type your own. A **Validate** check confirms the data view is usable for training.

***

## What the platform fills in

The proposal is not a fixed form. The platform picks the most specific **twin type** your data supports and shows only the controls that type needs — so the screen you see depends on the data you selected. A simple table produces a short screen; a grouped time series produces a long one. Two examples show the range.

### Example: a static twin

A *static* twin treats each row as an independent case — one row per customer, say — with no time dimension. The build screen stays short: the data view, a **Type** of Static, the **Fields** to include, a couple of training options, and the inherited **Advanced Configuration**. No time column and no environments — there is no time axis, and no groups to separate.

### Example: a multi-environment temporal twin

A *multi-environment temporal* twin tracks many groups over time. Take an example dataset — a table of sales orders, each tagged with a **product** and a **city**, recorded over time (just one example; your data will differ). The same screen now carries more, because the data has both a time axis and groups to keep apart: it adds a **Time Column** and **Environment Columns** that the static screen never shows.

### What appears, and when

Every build screen, whatever the type, includes:

* **Name** — auto-generated from the data view; editable.
* **Type** — Static, Temporal, Multi-Environment Static, or Multi-Environment Temporal. The platform ticks every type your data supports and selects the most specific one. See [Types of Digital Twins](/more-details/build-digital-twin/twin-types).
* **Fields** — the variables fed into causal discovery. All are included by default; free-text (string) columns are ignored, because the discovery algorithm cannot use them.
* **Training options** — toggles such as accounting for hidden factors and recovering the underlying formula behind a relationship.
* **Advanced Configuration** — variable roles, prior knowledge, and ordering constraints, all *inherited from the ontology* you built earlier.

Other controls appear only when the type calls for them:

* **Time Column** — for temporal types: the field that orders events over time (here, *Order Date*).
* **Environment Columns** and **Parallel pieces** — for multi-environment types: the categorical columns that split the data into separate environments (for example, *Product* or *City*), and — under the review step's Advanced settings — how many parallel pieces to split training into.
* **Lagged-effect discovery** — for temporal types: an option to find delayed effects across time steps.

Either way, the result is a working configuration before you have changed a single setting.

***

## What to do next

The proposal is a starting point, not a verdict. Two of the auto-filled choices do most to shape the result:

* **Type** and **Environment Columns** decide how the model partitions and learns from your data. They are the settings most worth understanding, and the first ones to revisit if the model fits poorly — see [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit).
* Every control on the screen can be changed before you train. [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration) walks through each one.

When the configuration looks right, you train the twin from the **Review & run** step: **Discover & train** runs discovery and training in one action, or **Train model** trains directly on a graph you drew by hand.

***

## Other Build a Digital Twin pages

* [Types of Digital Twins](/more-details/build-digital-twin/twin-types) — Static, Temporal, and the two Multi-Environment variants.
* [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration) — every control on the build screen.
* [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit) — adjusting the configuration to improve model fit.

See [Digital Twin overview](/more-details/digital-twin) for the bigger picture.


# Types of Digital Twins

When you select a data view, RootCause reads it and proposes the most specific twin type the data supports (see [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view)). There are four, and they differ on just two questions:

* **Is there a time dimension?** Does each row belong to a sequence ordered in time, or is each row a standalone snapshot?
* **Are there multiple environments?** Is the data one homogeneous set, or many distinct groups — products, cities, stores, customer segments — that you want modeled together?

Crossing those two questions gives the four types.

<figure><img src="/files/9naioJxFMBaexwxjODqf" alt="A 2x2 diagram of the four digital twin types, split by whether the data has a time dimension and whether it has multiple environments"><figcaption><p>The four twin types, by time dimension and number of environments.</p></figcaption></figure>

***

## The four types

### 1. Static

Observations with **no time information**. Each row is an independent case — one row per customer, say. The twin learns what drives what from a single snapshot, ignoring any time element. Best when your rows are independent cases rather than a series of dates.

### 2. Temporal

Observations **with time**: a single series ordered by a time column. The twin learns both immediate effects and *lagged* effects — causes whose impact shows up one or more time steps later.

### 3. Multi-Environment Static

**Many groups, no time.** Each environment — a product, a region, a segment — is observed as a snapshot, and the twin discovers one shared cause-and-effect network across all of them while allowing a limited set of differences between them. This setting is also called *pooled cross-section* or *multi-context* data. It is **not** panel data: there is no time axis.

### 4. Multi-Environment Temporal

**Many groups tracked over time** — the richest type. Take an example: a table of sales orders tagged with a **product** and a **city**, recorded over time (just one example; your data will differ). It combines the time dimension of a Temporal twin with the grouping of a multi-environment twin. This is what statisticians call **panel data**; the platform labels a trained one a *Panel Time Series Model*.

***

## Why "environments," not "groups"?

A multi-environment twin does more than sort your data into buckets. It assumes every environment shares the **same underlying cause-and-effect structure**, and that only a few specific mechanisms differ between them. That shared causal core is what the twin sets out to discover; the differences are treated as information, not noise.

This is why the platform says *environments* and not *groups*. In statistics a "group" is just a partition — a bucket of rows that may differ from the next bucket in any way at all. An "environment" is a stronger idea, borrowed from causal inference: a setting in which the causal mechanisms are mostly stable and only sparsely perturbed.

And the differences between environments are an **asset, not a nuisance**. Each environment behaves like a natural experiment: by seeing how cause and effect shift from one environment to the next, the twin can pin down the direction of relationships it could never resolve from a single pooled dataset. Modeling many environments together is therefore *more* accurate than modeling each one alone — provided they genuinely share a common causal core.

The research behind this idea is listed under [Further reading](#further-reading).

***

## How the platform chooses

The moment you select a data view, RootCause inspects it and **ticks every type the data supports**, selecting the most specific one by default. You can override the choice, but the auto-detected type is almost always the right starting point.

<figure><img src="/files/N9cS305wxrLqLcgfngSC" alt="The builder&#x27;s Choose your data step with the Type selector: Static is marked Recommended and selected, while Temporal and Multi-env time are disabled because the data has no time column"><figcaption><p>The Type selector after picking a data view: Static is marked Recommended, and the types the data cannot support are disabled.</p></figcaption></figure>

***

## Further reading

The "environments" framing — and the finding that variation across environments *helps* causal discovery — comes from a body of causal-inference research:

* Peters, J., Bühlmann, P. & Meinshausen, N. (2016). Causal inference by using invariant prediction: identification and confidence intervals. *Journal of the Royal Statistical Society: Series B*, 78(5), 947–1012. — introduces "environments" (Invariant Causal Prediction).
* Arjovsky, M., Bottou, L., Gulrajani, I. & Lopez-Paz, D. (2019). Invariant Risk Minimization. arXiv:1907.02893. — popularised the term in machine learning.
* Mooij, J. M., Magliacane, S. & Claassen, T. (2020). Joint Causal Inference from Multiple Contexts. *Journal of Machine Learning Research*, 21(99), 1–108. — discovery across multiple environments/contexts.
* Perry, R., von Kügelgen, J. & Schölkopf, B. (2022). Causal Discovery in Heterogeneous Environments Under the Sparse Mechanism Shift Hypothesis. *Advances in Neural Information Processing Systems*, 35. — why sparse differences across environments make the full causal structure identifiable.
* Günther, W., Ninad, U. & Runge, J. (2023). Causal Discovery for Time Series from Multiple Datasets with Latent Contexts. *Uncertainty in Artificial Intelligence (UAI)*. — the multi-environment *temporal* (panel) case.
* Sun, Y., Wang, Y., Jin, Y., Chan, D. & Koehler, J. (2017). Geo-level Bayesian Hierarchical Media Mix Modeling. Google Inc. — the hierarchical "groups / partial pooling" framing, for contrast.

***

## Other Build a Digital Twin pages

* [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view) — choosing the data and reading the auto-filled configuration.
* [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration) — every control on the build screen.
* [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit) — adjusting the configuration to improve model fit.

See [Digital Twin overview](/more-details/digital-twin) for the bigger picture.


# Configuration to Build Digital Twin

This page is the reference for every control in the **twin builder**. The builder is a four-step wizard — how to build, choose your data, add domain knowledge (or draw the graph), then review and run — and the controls appear once you select a data view (see [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view)). Which ones you see depends on the [twin type](/more-details/build-digital-twin/twin-types) the data supports. RootCause fills them all in for you; this page explains what each does and when it is worth changing.

> **You can change these later.** These are the settings you choose *while creating* a twin. After it is built, the twin's read-only [Config tab](/more-details/digital-twin/configuration) documents them, and **Modify model** reopens the builder — each run creates a new version and retrains.

<figure><img src="/files/V1wEChdfGT8P8dae4304" alt="The twin builder&#x27;s Advanced settings and Review &#x26; run step, showing the Training Options toggles — Account for hidden factors and Show the formula — the Discovery engine choice of SPARC and SPARC-fast, and the plain-language recap"><figcaption><p>The <strong>Advanced settings</strong> panel and the Review &#x26; run step: training options and engine choices above the plain-language recap. Temporal and multi-environment twins add controls to the same screen.</p></figcaption></figure>

***

## Data and structure

### Data View

The dataset the twin learns from. Selecting it triggers everything below. Covered in [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view).

### Name

A label for the twin, auto-generated from the data view name (for example, *Digital Twin - View of Sales Data*). Edit it or leave it to auto-generate. **Validate** confirms the data view is usable.

### Type

Static, Temporal, Multi-Environment Static, or Multi-Environment Temporal. The platform ticks every type the data supports and selects the most specific. See [Types of Digital Twins](/more-details/build-digital-twin/twin-types). The remaining controls in this section appear only for the types that need them.

### Time Column *(temporal types)*

The field that orders observations in time — here, *Order Date*. Identified automatically from the data view's time field.

### Environment Columns *(multi-environment types)*

The categorical columns that split the data into **environments** — the groups the model treats separately while it learns one shared cause-and-effect map across them all.

The platform creates **one environment per unique combination** of the selected columns' values. In the sales data example — a table of orders tagged with a **product** and a **city**, recorded over time (just one example; your data will differ) — selecting *Product* and *City* produces 171 environments, while *Product* alone produces 19. **Each environment needs at least 10 rows of overlapping history to be modeled.**

This is the cause of the common error:

> **"No environment has at least 10 rows."**
>
> You have selected environment columns that split the data into many tiny partitions, each below the 10-row threshold. Select **fewer or coarser** columns so each environment holds enough history. Fewer environment columns mean fewer, larger environments.

Choosing environment columns is also the single biggest lever on model fit — see [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit).

### Parallel pieces *(multi-environment types)*

Multi-environment workloads can be split into pieces and trained in parallel across the cluster. The control lives in the review step under **Advanced settings → Speed**: set **Parallel pieces**, or leave it blank ("auto") to use the split the platform recommends — a "\~N recommended" hint shows alongside the field. The recommended value is right for most jobs; raise it only when a large workload needs more parallelism.

***

## Fields

The variables fed into causal discovery. Every column from the data view is listed with its data type, and **all are included by default**. Free-text (string) columns are ignored automatically, because the discovery algorithm cannot use them.

Exclude a field when it carries no causal meaning — a unique identifier, a metadata column, or a field that duplicates another. Include anything you might want to predict, simulate, or trace a causal path through.

***

## Training Options

Each option improves the model but adds training time, which is why they are toggles rather than always on. For most work, leave **Account for hidden factors** and **Show the formula** on; turn them off only for a faster, exploratory pass.

* **Account for hidden factors** (confounder modeling) — detects and accounts for hidden variables that are not in your data but could influence the variables that are. This improves the *defensibility* of the causal claims the twin makes. Recommended on.
* **Show the formula** (equation discovery) — recovers the actual equations behind each relationship, not just which variables connect. You get an interpretable functional form rather than a black box. Recommended on.
* **Delayed effects** (lag discovery; temporal types, experimental) — finds *lagged* causal relationships: effects that show up one or more time steps after their cause.

***

## Algorithm Versions

Two engine choices, one per stage. The defaults are correct for most cases — change them only deliberately.

* **Causal Discovery** — finds the cause-and-effect structure. Two engines are offered for every twin type: **SPARC-fast** (the default) and **SPARC** (adaptive multi-stage discovery).
* **Digital Twin** — fits the runnable model on top of the discovered structure. **CausalBART** (a causal Bayesian-network simulator) is the default for static and multi-environment static twins; **GAAMT** (temporal causal network simulation) is used for temporal twins. Multi-environment temporal twins offer two variants: **GAAMT** (the default), which trains an independent temporal network for each environment — best when environments differ substantially or have abundant per-environment data — and **Pooled GAAMT + BART**, which trains one shared temporal network across all environments and applies per-environment BART corrections — best when environments share structure or some have limited data.

***

## Advanced Configuration *(inherited from the ontology)*

These settings are carried over from the ontology you built earlier, so they usually need no change. You are free to adjust them for this twin version without affecting the ontology itself.

### Derived Columns

Columns the system has detected as **calculated from other columns** — for example *Hour = hour(Order Date)*. The twin takes the derivation into account, so causal discovery does not mistake a mathematical identity for a genuine cause. Removing a row here changes only this twin version; your underlying data and saved ontology settings stay the same, and re-syncing from the ontology may bring it back.

### Variable Roles

Classify a variable as a **Source** (an exogenous driver or input — say, a macroeconomic indicator) or a **Target** (an outcome you care about — say, sales). This keeps drivers upstream of outcomes when the model draws its causal arrows: a source can only receive incoming edges from other sources, and a target can only send outgoing edges to other targets. ("Incoming edges" are arrows pointing *into* a variable — that is, something causing it.) **From Ontology** and **Suggest with AI** fill the roles for you.

### Prior Knowledge

Tell the model what you already know about specific relationships. Both lists are optional and both sharpen results when you have real knowledge to add:

* **Known Relationships** — pairs you know are connected (for a temporal twin you can also set a lag).
* **Blocked Relationships** — pairs you know are unrelated, so the model never links them.

### Variable Ordering

Constrains which variables may precede others, so an effect can never be proposed as the cause of its own cause — *"Sales must come after Order Date, Price Each, and Hour."* Useful when temporal or domain order is known.

***

## Training the twin

The run button sits in the **Review & run** step, and its label depends on the method chosen in step 1:

* **Discover & train** — runs causal discovery, then trains the complete, runnable model — one action. This is the normal path.
* **Train model** — trains directly on a graph you drew by hand, with no discovery step.
* **Re-discover & train** / **Retrain model** — the same two actions when modifying an existing twin.

A plain-language recap above the button restates your configuration (data and type, variables in play, roles, and prior knowledge), alongside validation checks, so you can confirm it before you start.

***

## Other Build a Digital Twin pages

* [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view) — choosing the data and reading the auto-filled configuration.
* [Types of Digital Twins](/more-details/build-digital-twin/twin-types) — Static, Temporal, and the two Multi-Environment variants.
* [Tuning for Fit](/more-details/build-digital-twin/tuning-for-fit) — adjusting the configuration to improve model fit.

See [Digital Twin overview](/more-details/digital-twin) for the bigger picture.


# Tuning for Fit

A first training run rarely produces the best model. Tuning is the loop that follows: adjust the build configuration, retrain, watch the fit score move, and repeat until the model is good enough to act on. This page explains how to read fit and which controls move it most.

It builds on [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration), which documents every control; here we cover how to *use* those controls to improve a model.

***

## Reading model fit

After training, the twin's Home shows a **model fit** percentage — how well the model predicts each variable, averaged across all of them. A low score comes with a prompt to act:

> Low overall predictive accuracy — try adding more data, removing noisy variables, or editing causal relationships.

<figure><img src="/files/yQ7P6beWiIBEGekXwVwE" alt="A trained twin&#x27;s Home showing a 17.1% model fit with a low-accuracy warning"><figcaption><p>A first run with a poor fit — 17.1%. The averaged score is the headline, but the variable you care about may score differently.</p></figcaption></figure>

One number rarely tells the whole story. The fit is an average, so a model can predict the outcome you care about well while scoring poorly on variables you don't. Always check the per-variable breakdown before judging a model — see [Reviewing Model Quality](/more-details/digital-twin/model-quality).

***

## The tuning loop

1. Build and train the twin ([Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration)).
2. Read the fit score and the per-variable detail.
3. Change **one** thing.
4. Save as a new version and retrain.
5. Compare against the previous version, and keep the better one.

Every retrain creates a new version, so you can compare runs side by side and roll back if a change makes things worse — see [Version History](/more-details/digital-twin/version-history) and [Model Comparison](/more-details/digital-twin/model-comparison).

***

## The biggest lever: environment columns

For a multi-environment twin, the single largest influence on fit is **how many columns define your environments**. Each unique combination of the selected columns becomes one environment, and each environment needs at least 10 rows of history to learn from. Select too many columns and the data shatters into many tiny environments, each with too little history — fit suffers, and you may hit the "no environment has at least 10 rows" error.

To see the effect, take an example dataset — a table of sales orders, each tagged with a **product** and a **city**, recorded over time. (Just one example; your data will differ.) Changing the environment columns changes the result sharply:

| Environment columns | Environments | Rows each | Model fit |
| ------------------- | -----------: | --------: | --------- |
| Product **+** City  |          171 |   \~1,087 | 17.1%     |
| Product only        |           19 |   \~9,787 | **29.1%** |

In the sales data example, dropping City left fewer, larger environments — each with far more history — and fit improved substantially, from 17.1% to 29.1%. (This better run also added prior knowledge and corrected the variable ordering, below, so the gain reflects several tuning steps together — which is how tuning usually works in practice.)

<figure><img src="/files/4ey391Bld3k1z3evAsZ1" alt="The retrained twin&#x27;s Home showing model fit improved to 29.1% after reducing the environment columns to Product only"><figcaption><p>The retrained twin after dropping City to leave 19 environments — fit rose to 29.1%.</p></figcaption></figure>

Note that 29.1% is still flagged as low. That is the point of the per-variable view: an averaged score can be modest while the model predicts the variable you actually care about well — so judge the model on the outcome that matters, not the headline number (see [Reviewing Model Quality](/more-details/digital-twin/model-quality)).

The rule of thumb: **start coarse and add granularity only if fit holds.** Begin with the smallest set of environment columns that still reflects how your business actually differs, and split further only when the data supports it.

***

## Other levers

When environment columns aren't the issue, or you have already tuned them:

* **Fields** — remove noisy or irrelevant variables that add confusion without explanatory power.
* **Causal relationships** — add relationships you know to be real, block ones you know to be impossible, or edit individual edges. See [Inspecting Causal Relationships](/more-details/digital-twin/causal-relationships).
* **Training options** — keep **Account for hidden factors** and **Show the formula** on for a more defensible, interpretable model.
* **More data** — a longer history or more records per environment is often the most direct fix.

***

## Check the variable ordering

The build screen suggests **variable ordering** automatically — constraints such as *"Sales must come after Order Date."* These suggestions are generated for you and are a useful starting point, but they are **not infallible**: some will not reflect how your domain actually works.

Walk through each ordering rule and confirm it makes real-world sense before you train. A wrong rule quietly forces — or forbids — a causal direction, and that can pull the whole model off course. Correcting nonsensical ordering constraints is one of the simplest ways to improve a model.

***

## Knowing when to stop

Fit is a means to a decision, not a target in itself. Stop tuning when the model predicts the variable you care about well enough to act on — even if the averaged fit score is not high. A model that nails your key outcome and is honest about the rest is more useful than one chasing a higher average.

***

## Other Build a Digital Twin pages

* [Selecting your Data View](/more-details/build-digital-twin/selecting-data-view) — choosing the data and reading the auto-filled configuration.
* [Types of Digital Twins](/more-details/build-digital-twin/twin-types) — Static, Temporal, and the two Multi-Environment variants.
* [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration) — every control on the build screen.

See [Reviewing Model Quality](/more-details/digital-twin/model-quality) for reading fit in depth, and the [Digital Twin overview](/more-details/digital-twin) for the bigger picture.


# Digital Twin

A Digital Twin is a causal model of your business or system. Unlike traditional predictive models that learn correlations, a Digital Twin understands cause and effect — enabling simulation, optimization, and counterfactual reasoning.

Building and using a Digital Twin covers Steps 4–6 of the [seven-step workflow](/start-here/workflow): Build Causal Graph, Build Digital Twin, and Run Simulations.

***

### Building

[**Creating a Digital Twin**](/user-guide/creating-digital-twin) — Select a Data View, configure model settings, and train the twin. This is where causal discovery runs.

[**Causal Graph**](/user-guide/causal-graph) — Read, interpret, and refine the discovered cause-and-effect graph with domain knowledge.

***

### Using

[**Simulations**](/user-guide/simulations) — Run what-if scenarios, optimize decisions, find root causes, and predict outcomes.

***

### Comparing

[**Model Comparison**](/more-details/digital-twin/model-comparison) — Put two Digital Twin versions side by side to understand exactly what changed in structure and parameters.

***

### The Digital Twin interface

Once created, you interact with a Digital Twin through five sections — panel twins add a sixth. The twin's **Home** shows the causal graph with a side panel of cards — Configuration, Versions, Simulations, Graph explorer, Model evaluation — and opening a card switches the view; the URL tracks the active section (`?tab=…`):

| Section                           | Purpose                                                                                                     |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Home                              | The causal graph, model status, and the cards linking to every other section                                |
| Config                            | The data, fields, and algorithms behind the current version (read-only; **Modify model** opens the builder) |
| Relationships                     | View and edit causal relationships                                                                          |
| Evaluation                        | Model quality metrics                                                                                       |
| Simulations                       | Run all simulation types                                                                                    |
| Environments *(panel twins only)* | Per-environment insights                                                                                    |

Selecting a node or edge on the causal graph opens a details panel with **Path Analysis** and **Model Probabilities** views — plus **Seasonal Trends** on temporal twins and **Environment Analysis** on panel twins. [Version History](/more-details/digital-twin/version-history) opens from the **Versions** card on Home, and two twins or versions can be compared side by side on the separate Compare page — see [Model Comparison](/more-details/digital-twin/model-comparison).

<figure><img src="/files/lWmrXR4b3B8sbRtL0AXH" alt="Digital Twin Home showing the causal graph and side-panel cards for Configuration, Versions, Simulations, Graph explorer, and Model evaluation"><figcaption><p>A trained Digital Twin's Home. The cards on the right report 19 variables and 31 relationships, version v1.0.0, and a 69.6% model fit — and open each section.</p></figcaption></figure>


# Model Comparison

Causal models evolve. You might train a Digital Twin on January data, then retrain on February data. Or experiment with different configurations — omitting certain variables, adding domain knowledge, changing temporal settings.

Model Comparison lets you put two Digital Twin versions side by side and understand exactly what changed: which relationships appeared, disappeared, or reversed direction, and how the underlying probability distributions shifted.

This is essential for model governance. Before promoting a new model version, you need evidence of how it differs from the current one.

***

### Accessing Model Comparison

Model Comparison is its own page, not a tab on the twin: the **Compare** page under the Digital Twins section of your workspace (at `…/twins/compare`). The twin and version selectors are in the upper right corner.

***

### Selecting models

The comparison tool lets you compare any two Digital Twin versions — including versions from different twins.

Common scenarios:

* **Same twin, different versions** — track how the model evolved over retraining
* **Same data, different configurations** — compare the effect of constraints or excluded variables
* **Different time periods** — see how causal relationships changed between datasets

***

### Comparing twins

Once two models are selected, the comparison view shows both causal graphs side by side with structural differences highlighted.

<figure><img src="/files/TgjLwC1wxoX57RGyhvK8" alt="The Compare page in Separate view: the v1.1.0 and v1.0.0 graphs with a Comparison Overview panel reporting 19 variables in each, 32 vs 31 relationships, 28 common edges, and evaluations of 71.7% vs 69.6%"><figcaption><p>Two versions compared in the Separate view. The Comparison Overview reports size, structural overlap, and evaluation for both models — here v1.1.0 carries 32 relationships to v1.0.0's 31, sharing 28 edges.</p></figcaption></figure>

Switching to **Diff** merges both graphs into a single view, color-coding the edges unique to either model and any whose direction changed. The **Comparison Overview** panel summarizes the structural overlap, evaluation, equations, and parameters, with **Details** links into a full breakdown of each.

<figure><img src="/files/YFOLGQpkxPVCfTUbzbMB" alt="The Compare page in Diff view: a merged graph with a legend for Model 1 Only, Model 2 Only, Both Models, and Direction Changed, with a handful of coloured unique edges among the shared grey ones"><figcaption><p>The merged diff view. The 28 shared edges render grey; the coloured edges are unique to one model or flipped direction between them — exactly the differences re-discovery introduced.</p></figcaption></figure>

***

### Interpreting differences

**Structural changes**

* **New edges** — the model found a relationship not present before; may reflect new patterns in updated data
* **Removed edges** — a previously discovered relationship is no longer supported; may indicate data drift
* **Direction changes** — causality now flows the opposite way; investigate why

**Parameter changes**

Even when structure is identical, parameters can differ. The conditional influence between variables may have become stronger, weaker, or changed in functional form.

**Questions to ask**

1. Are structural changes expected given the data differences?
2. Do direction changes make domain sense?
3. Would these changes affect downstream decisions?

***

### Creating a second twin to compare

To compare two configurations or time periods, create a second Digital Twin from the same (or a different) Data View. Both twins will then be available in the Compare page selectors.

For Digital Twin creation steps, see [Build Digital Twin](/user-guide/creating-digital-twin).


# Exploring the Causal Model

When you open a Digital Twin from the Digital Twins list, the causal graph fills the center and the right-hand panel opens on the **Home** tab. The graph is where the model lives — every variable, every relationship, every direction of cause and effect is visible at once.

This page covers the two things you do most often in this view: read the graph canvas, and drill into a single variable to see what drives it. The other views — model quality, configuration, version history, individual relationships — have their own pages.

For context on how a Digital Twin is built in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## The graph canvas

The canvas lays the model out as a flowchart: variables positioned by their place in the causal chain, inputs toward the edges and outcomes downstream, with every edge an arrow of cause and effect. Each node carries its data-type badge.

<figure><img src="/files/JGBnqDjjkA3feX9ZukMT" alt="A trained Digital Twin open on its Home tab: the causal graph canvas fills the center with variables laid out left to right, and the right panel stacks the Model trained and ready banner with the Configuration, Versions, Simulations, Graph explorer, and Model evaluation cards"><figcaption><p>The twin Home. The causal graph fills the canvas; the card panel on the right summarizes the state of the model.</p></figcaption></figure>

Controls sit in the bottom-left corner: zoom in and out, fit the whole graph to the window, and lock the canvas against accidental dragging. **Recompute layout** redraws the arrangement after the graph changes. The model itself is untouched by any of these: they only change how it is drawn.

***

## The Home tab

The right-hand panel's Home view is a stack of cards summarizing the state of the twin:

* **Model status** — a banner reporting whether the twin is trained and ready to simulate.
* **Configuration** — the type, variable count, and relationship count behind the model. The [Config tab](/more-details/digital-twin/configuration) holds the detail, and **Modify model** starts a new version.
* **Versions** — the current version and its status; switch, compare, and manage saved versions via [Version History](/more-details/digital-twin/version-history).
* **Simulations** — recent runs. The [Simulations tab](/user-guide/simulations) runs and lists them.
* **Graph explorer** — how many relationships are in the model and how many candidate connections were tested and ruled out.
* **Model evaluation** — model fit at a glance. The [Evaluation tab](/more-details/digital-twin/model-quality) has the full metrics.

***

## Inspecting a single variable

Open a variable from the Relationships view (or click its node in the graph) and its full detail page opens. You see:

* A natural-language summary of how the variable is influenced, with how much of its behavior the model explains.
* A **Prediction quality** verdict on held-out data.
* The **distribution** the variable takes under the model's learned parameters.
* A ranked **Relationships** panel of its drivers, each marked direct or indirect with its relative strength.

<figure><img src="/files/2okpMDAKumgnBen5cawI" alt="The Variable Details page for Churn: an outcome driven by 4 variables with 26% of its behaviour explained, a Good fit verdict of 81% accuracy, 0.88 F1 and 0.84 AUC, the learned distribution chart, and a Relationships panel ranking Contract, InternetService, OnlineSecurity, and TechSupport as direct drivers"><figcaption><p>Variable Details for Churn. Contract, InternetService, OnlineSecurity, and TechSupport are its direct drivers; prediction quality and the learned distribution sit below the summary.</p></figcaption></figure>

***

## What to look for

* **The chain from input to outcome.** Pick the variable you care about — usually a business outcome — and trace backward through the graph. The strongest drivers in its Relationships panel tell you where intervention will have the most leverage.
* **Direct vs indirect drivers.** A variable can affect an outcome through several routes. The driver ranking shows the relative weight; the graph shows the actual path.
* **Surprises.** A driver you didn't expect in the top three. A relationship that runs the wrong way. A central variable that nothing else points to. These are usually the most interesting findings — and the most useful to validate with domain knowledge.

***

## Other Working with a Digital Twin pages

* [Reviewing Model Quality](/more-details/digital-twin/model-quality) — how trustworthy is the model?
* [Inspecting Causal Relationships](/more-details/digital-twin/causal-relationships) — individual edges and their statistics.
* [Configuration for Existing Twin](/more-details/digital-twin/configuration) — model settings, included variables, constraints.
* [Version History](/more-details/digital-twin/version-history) — multiple versions of the same twin.

See [Digital Twin overview](/more-details/digital-twin) — general overview.


# Reviewing Model Quality

Causal discovery finds relationships; evaluation tells you how trustworthy the model actually is. The **Evaluation** tab shows overall predictive accuracy, per-variable performance, and side-by-side version comparisons.

Read this before you trust simulation results. A model that predicts poorly will also simulate poorly.

For context, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin) and [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model).

***

## Opening the Evaluation tab

The twin's Home shows the headline accuracy figure on its **Model evaluation** card; open the card for the full view, which fills the page: the best-predicted charts and per-node metrics on the left, with the version-comparison configuration and a **Model health** panel on the right.

<figure><img src="/files/NvbZB3vUzE7jFZKb05uA" alt="The Model Evaluation page for a 19-variable, 31-relationship Churn model, with best-predicted charts, the version comparison selector, and a Model health panel reporting 69.6% predictive accuracy"><figcaption><p>The full Evaluation view. The Model health panel carries the headline verdict; the charts and table break it down per variable.</p></figcaption></figure>

***

## Predictive accuracy at a glance

The **Model health** panel is the summary verdict:

* A single headline accuracy number (here, 69.6%).
* How many nodes scored well, mid, and poor (4 above 80%, 9 between 50-80%, 1 below 50%, across 14 evaluatable nodes).
* A note that deterministic variables are excluded from the aggregate score.
* A reminder that the variable you care most about may score very differently — check the per-node table.

If you recently removed redundant or derived columns, the headline number can drop because near-perfect-fit nodes are no longer in the average. That's not a degradation in quality; it's a change in what's being averaged.

***

## Best predicted variables

Two bar charts highlight the model's strengths:

* **Best Predicted Categories** — ranked by accuracy: the percentage of correct predictions. 100% means every prediction was right.
* **Best Predicted Numeric Variables** — ranked by R²: how much of each variable's variation the model can explain. 1.0 is perfect; 0 is no better than guessing the mean; negative means worse than that.

***

## Per-variable metrics

The table at the bottom of the panel shows every variable and its performance. Click a row to expand a per-class accuracy breakdown.

| Variable type         | Metrics shown                                           |
| --------------------- | ------------------------------------------------------- |
| Boolean / Category    | Accuracy, Precision, Recall, F1, Weighted Accuracy, AUC |
| Numeric               | MSE, MAE, R², Log Likelihood                            |
| Numeric (time series) | MAPE per forecast horizon                               |

Reading the classification metrics:

* **Accuracy** — overall correctness.
* **Precision** — when the model says "yes", how often is it right?
* **Recall** — of all true "yes" cases, how many did the model find?
* **F1** — the harmonic mean of precision and recall.
* **AUC** — discrimination ability. 1.0 is perfect; 0.5 is chance.

For rare-event variables, precision and recall are usually more informative than accuracy alone.

***

## Comparing versions

The **Version Comparison** dropdown selects one or more versions to chart side by side. Useful for confirming a configuration change improved things — and for spotting versions that improved some metrics while quietly degrading others.

***

## When a variable scores poorly

A low metric is information, not a verdict. Common causes:

* **Missing causes.** The variable's true drivers aren't in the model.
* **Data quality.** Noise, errors, or too many missing values.
* **Wrong model type.** A time-dependent variable in a static twin.
* **Too little data.** Not enough examples to learn the pattern.

If the missing driver is already a column in the Data View, open the twin's Config tab, click **Modify model**, include the field, and retrain — see [Configuration for Existing Twin](/more-details/digital-twin/configuration). If it isn't in the Data View yet, add it there first (see [Build 360 Table](/user-guide/data-views)), then rebuild. If the variable is genuinely hard to predict, that's a constraint to remember for any simulation that touches it.

***

## Other Working with a Digital Twin pages

* [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model) — graph layouts and variable details.
* [Inspecting Causal Relationships](/more-details/digital-twin/causal-relationships) — individual edges and their statistics.
* [Configuration for Existing Twin](/more-details/digital-twin/configuration) — model settings, included variables, constraints.
* [Version History](/more-details/digital-twin/version-history) — multiple versions of the same twin.

See [Digital Twin overview](/more-details/digital-twin) — general overview.


# Inspecting Causal Relationships

Causal discovery produces dozens or hundreds of cause-and-effect relationships. The Relationships panel lists every one of them in a sortable, searchable table, with controls to add, remove, or flip directions, and an **AI Sanity Check** that flags relationships that don't look right.

This is where human judgment meets algorithmic output. Read the list, prune the spurious, fix the wrong-direction ones, and the model becomes more trustworthy.

For context, see [Step 4: Build Causal Graph](/user-guide/causal-graph) and [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model).

***

## Opening the Relationships tab

Open the twin's **Relationships** tab. The graph stays visible on the left; the right panel shows the relationships table.

<figure><img src="/files/e5IhicUk676xwFEseZUD" alt="The Relationships panel for a Churn model, listing its 31 relationships in a sortable table next to the causal graph, with a footer reporting 140 connections tested and ruled out"><figcaption><p>The Relationships panel beside the graph. The header shows the total relationship count (31 here); the footer reports the 140 connections tested and ruled out.</p></figcaption></figure>

***

## Reading the table

Three columns:

* **Cause** — the source variable. The **Observed** tag marks variables that come from your data rather than synthetic.
* **Effect** — the target variable.
* **Strength** — a percentage with a colored bar. Higher means a stronger causal link; color shifts from red (weak) through yellow to green (strong).

Sort by any column. Use the search box to filter by variable name; the **All** dropdown filters by type.

***

## Editing the graph

The panel supports the three changes most often needed after causal discovery:

* **Add Relationship.** Click **+ Add** to insert an edge the algorithm missed. You know the relationship exists; the algorithm did not have enough signal to find it.
* **Remove.** Drop a relationship that doesn't make sense — a spurious correlation, or a side-effect of an unmeasured confounder.
* **Flip direction.** Reverse a relationship the algorithm got the direction wrong on. The data alone often cannot distinguish A → B from B → A; your domain knowledge can.

Saving edits creates a new version of the twin and preserves the original in history. Training is a separate step — make your changes, then train the new version when you are satisfied with the graph.

***

## AI Sanity Check

Click **AI Sanity Check** to have the model review the relationship list and flag the ones that look implausible. Useful as a second pair of eyes — the AI catches obvious "this doesn't make sense" mistakes, but the final call is yours.

***

## What to look for

* **The strong ones.** Top of the strength column — these carry most of the causal signal. They should match your intuition about how the business works.
* **Wrong directions.** A relationship that runs A → B when domain knowledge says B → A. Common when the two events happen close together in time.
* **Spurious links.** A pair with no plausible mechanism. Usually a coincidence in the data or a side-effect of a missing variable. Remove it.
* **Surprises.** A direction or pair you didn't expect. Sometimes the algorithm is right and you were wrong. Worth a second look before deleting.

***

## Other Working with a Digital Twin pages

* [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model) — graph layouts and variable details.
* [Reviewing Model Quality](/more-details/digital-twin/model-quality) — predictive accuracy and per-variable metrics.
* [Configuration for Existing Twin](/more-details/digital-twin/configuration) — model settings, included variables, constraints.
* [Version History](/more-details/digital-twin/version-history) — multiple versions of the same twin.

See [Digital Twin overview](/more-details/digital-twin) — general overview.


# Configuration for Existing Twin

The Configuration panel defines what goes into a Digital Twin: the data it runs on, the variables included in causal discovery, the algorithms used, and any prior knowledge about which relationships are known or impossible. Get this right and discovery has a fair chance. Get it wrong and you'll miss real effects or fabricate spurious ones.

The Config tab is read-only — it documents the version you are looking at. To change anything, click **Modify model**, which opens the twin builder for this twin; every run there creates a new version and retrains, leaving the current one untouched.

This page covers a twin that already exists. For the same controls as they appear while first building a twin, see [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration). For more context, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin) and [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model).

***

## Opening Configuration

Open the twin's **Config** tab from the **Configuration** card on Home. The page documents the current version's configuration; the **Build summary** panel on the right reports the model size, algorithms, and per-stage training times.

<figure><img src="/files/Xczqmw6kL1k296rCFBTj" alt="The Configuration page for a Churn Digital Twin, showing the Data View, the Fields list with 20 included and 1 excluded, the SPARC-fast and CausalBART algorithm versions, and a Build summary panel reporting a Static Model with 19 variables, 31 relationships, and stage times totaling 47 seconds"><figcaption><p>The Config tab. All sections are read-only; <em>Modify model</em> opens the builder to change them, starting a new version.</p></figcaption></figure>

***

## Data View

The dataset the twin is built from. Changing it triggers a new **major** version, because the twin is now based on different data — as does a change in the underlying data itself, or a change to which fields are included.

***

## Fields

Every column from the Data View, with its data type (Boolean, Category, Number, Date/Time, Array/Set). The header shows the include count ("20 included, 1 excluded" in the example). Use the filter at the top to find a field by name; toggle each field to include or exclude.

Exclude:

* **Unique identifiers** (customer\_id, order\_id) — no causal meaning.
* **Metadata** (created\_at, updated\_by) — usually irrelevant.
* **Redundant fields** that duplicate another column.

Include anything you might want to predict, simulate, or trace a causal path through.

***

## Algorithm Versions

Two algorithm choices, one per stage:

* **Causal Discovery** — builds the graph. Default: **SPARC-fast**; **SPARC** (adaptive multi-stage discovery) is also available.
* **Digital Twin** — fits the probabilistic model on top. Default: **CausalBART** (causal Bayesian network simulation) for static and multi-environment static twins, **GAAMT** (temporal causal network simulation) for temporal ones. Multi-environment temporal twins offer **GAAMT** (the default, one temporal network per environment) or **Pooled GAAMT + BART** (one shared network with per-environment corrections).

See [Configuration to Build Digital Twin](/more-details/build-digital-twin/build-configuration#algorithm-versions) for when to choose which.

***

## Variable Roles

Variable Roles fence off the ends of the causal chain:

* **Sources (exogenous)** — pure drivers. Only other sources are allowed to influence them.
* **Targets (outcomes)** — pure outcomes. They can only send edges to other targets.

Variables not marked are free to be cause or effect, in either direction. In the example, customerID, InternetService, MultipleLines, and PhoneService are sources; Churn is the target.

***

## Prior Knowledge

Encode certainty about specific edges before discovery runs:

* **Known relationships** — edges that must exist. Use when you have experimental evidence or domain certainty.
* **Blocked relationships** — edges that cannot exist. Use when a connection is logically impossible.

Both lists are optional; both improve the resulting graph when you have real prior knowledge to add.

***

## Variable Ordering

Constrains causal precedence at the variable level. *"TechSupport must come after InternetService"* tells discovery that TechSupport cannot be a cause of InternetService — only an effect, direct or indirect. Useful when temporal order is known or domain logic is clear.

***

## What happens when you run

Click **Modify model**, change what you need in the builder, and run. A new version of the twin is created and trained against the updated configuration. The kind of change decides the version number:

* **Major** (1.0.0 → 2.0.0) — the data changed: a different Data View, a change in the underlying data itself, or a different set of included fields.
* **Minor** (1.0.0 → 1.1.0) — a configuration-only change (algorithm versions, training options, variable roles, prior knowledge, or ordering constraints) — or any **Re-discover & train** run, which starts a fresh discovery pass and advances the minor version even with an unchanged configuration.
* **Patch** (1.0.0 → 1.0.1) — a plain **Retrain model** of the existing graph with no changes at all.

***

## Other Working with a Digital Twin pages

* [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model) — graph layouts and variable details.
* [Reviewing Model Quality](/more-details/digital-twin/model-quality) — predictive accuracy and per-variable metrics.
* [Inspecting Causal Relationships](/more-details/digital-twin/causal-relationships) — individual edges and their statistics.
* [Version History](/more-details/digital-twin/version-history) — multiple versions of the same twin.

See [Digital Twin overview](/more-details/digital-twin) — general overview.


# Version History

A [Digital Twin](/more-details/digital-twin) is not a single fixed model. Every time you train it — on a new Data View, a changed configuration, or a refreshed dataset — RootCause keeps the result as a numbered **version**. Each version bundles a configuration and the model trained from it, so you can compare versions, return to an earlier one, and see how the twin has evolved.

One version is **current** at any time: the one your [simulations](/more-details/digital-twin/simulation-types) run against. The others stay on record, ready to be switched back to.

***

## The Version History view

Open a twin and, from its Home, open the **Versions** card. The page lists every version with its status, creation time, type, and model fit, with the current version marked; click a row to see its details, what changed compared to the version before it, and to switch to it.

<figure><img src="/files/jQrrKfd53cIQIPIe7tPO" alt="The Version History page listing two versions: v1.1.0 as the Current trained Static Model with a 71.7% model fit, and v1.0.0 below it with 69.6%"><figcaption><p>Version History. Here v1.1.0 is Trained and Current at a 71.7% model fit, with v1.0.0 preserved below it; select a row to inspect a version or switch back to it.</p></figcaption></figure>

Each version carries a **status**:

* **Current** — the version simulations run against. Exactly one version is current at a time.
* **Trained** — a completed version, ready to be switched to.
* **Failed** — training did not complete. The version is kept on record but cannot be used; retrain or delete it.

A version mid-training shows its progress in place until it resolves to Trained or Failed.

***

## How versions are numbered

Versions follow a three-part **major.minor.patch** scheme, and the kind of change you make decides which number advances:

* **Major** version (e.g. 1.0.0 → 2.0.0) — the **data** changed: a different Data View, a change in the underlying data itself, or a different set of included fields. A model built on different data is a different model, so it earns a new major number.
* **Minor** version (e.g. 1.0.0 → 1.1.0) — a configuration-only change: algorithm versions, training options, variable roles, prior knowledge, or ordering constraints. A **Re-discover & train** run also advances the minor version even when the configuration is unchanged — a fresh discovery pass can produce a different graph, so it is more than a plain retrain.
* **Patch** version (e.g. 1.0.0 → 1.0.1) — a plain **Retrain model** with no data or configuration changes at all.

See [Configuration for Existing Twin › What happens when you run](/more-details/digital-twin/configuration#what-happens-when-you-run).

***

## Creating a new version

From a twin's Config tab, click **Modify model**. This opens the twin builder — the same wizard used to [create the twin in the first place](/user-guide/creating-digital-twin) — seeded with the current version's configuration: data, type, fields, roles, prior knowledge, training options, and algorithm versions.

<figure><img src="/files/8qhaO1pkOzldq71qnfCt" alt="The Modify model screen: a choice between Re-discover with new priors and Edit the graph &#x26; retrain, the data inherited from v1.0.0, and the domain-knowledge step seeded with the current model"><figcaption><p>Modifying a twin. The builder opens seeded with the current version's configuration; the method chosen in step 1 decides how the next version is built.</p></figcaption></figure>

The builder's final step launches the work with one of two actions, depending on the method you chose:

* **Re-discover & train** — re-run causal discovery with your updated priors, then train. Use this when the data or your prior knowledge changed.
* **Retrain model** — retrain directly on your edited graph, with no discovery step. Use this when you adjusted the graph by hand.

***

## Training and the result

While a version trains, the twin shows a live status banner — **Discovering relationships…**, then **Training model…** — and a list of processing stages — preparing data, causal discovery, then, when the options are enabled, confounder modeling and equation discovery, and finally building the model. The configuration cannot be edited until training finishes.

<figure><img src="/files/lbbEXPkINVufMZrvexAV" alt="A twin mid-training: the Causal Discovery stage in progress with the five processing stages listed, the stage progress bars, and the Versions card showing the new version as Created"><figcaption><p>A version in training. Each of the five stages reports progress; the run can be cancelled.</p></figcaption></figure>

On success the banner turns to **Model trained & ready**, the version's status becomes Trained (and Current if it is the first), and simulations can run against it. The Config tab now shows the version's configuration, and **Modify model** starts the next iteration.

<figure><img src="/files/CCJ5zAG1UhA84Pp1xuIw" alt="A successfully trained twin: a Model trained &#x26; ready banner, the causal graph, and cards reporting v1.1.0 as Trained with a 71.7% model fit"><figcaption><p>A finished version — here v1.1.0, trained and current at a 71.7% model fit. The model fit score reports how well this version fits the data — see Reviewing Model Quality.</p></figcaption></figure>

***

## Seeing every version at a glance

The Digital Twins list shows each twin with its training status and owner — the fastest way to scan what exists across a workspace. Per-version detail lives in each twin's **Versions** page.

<figure><img src="/files/nJsYET3HIQtU5lx1TyKa" alt="The Digital Twins list showing a trained twin with its status and owner"><figcaption><p>The management list. Open a twin's Versions card for the per-version breakdown.</p></figcaption></figure>

To compare two versions side by side — their graphs, metrics, and relationships — use [Model Comparison](/more-details/digital-twin/model-comparison).

***

## Other Working with a Digital Twin pages

* [Exploring the Causal Model](/more-details/digital-twin/exploring-causal-model) — graph layouts and variable details.
* [Reviewing Model Quality](/more-details/digital-twin/model-quality) — predictive accuracy and per-variable metrics.
* [Inspecting Causal Relationships](/more-details/digital-twin/causal-relationships) — individual edges and their statistics.
* [Configuration for Existing Twin](/more-details/digital-twin/configuration) — the fields behind every version.

See [Digital Twin overview](/more-details/digital-twin) — general overview.


# Simulation Types

A simulation uses a [Digital Twin](/more-details/digital-twin), which is RootCause's runnable causal model of your business, to answer a specific kind of question. Each simulation type runs on the same underlying twin but is configured for a different purpose: predicting outcomes, testing interventions, finding optimal inputs, diagnosing anomalies, and more.

This section has one page per simulation type, covering when to use it, how to set it up, and how to read the result. For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

## The seven types

Static Digital Twins support seven simulation types.

| # | Type                                                                                   | Question it answers                                          |
| - | -------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| 1 | [Prediction](/more-details/digital-twin/simulation-types/prediction)                   | What outcome is most likely for a specific input?            |
| 2 | [Intervention](/more-details/digital-twin/simulation-types/intervention)               | What happens if we change variable X?                        |
| 3 | [Optimization](/more-details/digital-twin/simulation-types/optimization)               | What combination of inputs best achieves our goal?           |
| 4 | [Best Action](/more-details/digital-twin/simulation-types/best-action)                 | What is the minimum change needed to reach a target outcome? |
| 5 | [Explanation](/more-details/digital-twin/simulation-types/explanation)                 | What drives an outcome, and what does a cause influence?     |
| 6 | [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) | What caused this specific observed outcome?                  |
| 7 | [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan)   | Which records are anomalous, and why?                        |

Temporal Digital Twins — those built on time-series data — support a parallel family of time-aware simulations. **Forecast**, **Temporal Intervention**, and the temporal-only **Causal Health Monitor** ship today; counterparts to the remaining static types are rolling out. Panel (multi-environment) twins get per-environment **Panel** variants of the available types. See [Temporal Simulations](/more-details/digital-twin/temporal-simulations).


# Prediction

Prediction takes a [Digital Twin](/more-details/digital-twin) and an input scenario, and returns the most likely value of a target variable with a confidence interval.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Why a Digital Twin prediction beats an LLM prediction

A prediction from a Digital Twin gives you three things an LLM cannot.

1. **Repeatable.** The same input always produces the same output.
2. **Explainable.** The prediction comes from a DAG — a system of equations whose causal logic can be inspected end-to-end.
3. **Calibrated.** Every prediction carries a known confidence interval and an understood distribution of outcomes.

A completed Prediction looks like this.

<figure><img src="/files/ZazUsGa4ychkZjn41DvM" alt="A completed Predict Churn run: the AI summary reports Churn predicted as Yes with 60.07% probability for the first case and No with 98.66% probability for the last, above a predictions table covering 3 input scenarios at 95% confidence"><figcaption><p>A completed Prediction run: the AI summary states the headline probabilities, and the predictions table below covers every input scenario, here 3 of them, with 95% confidence intervals.</p></figcaption></figure>

***

## Starting a simulation

Open a Digital Twin from the Digital Twins list, open the **Simulations** tab, then click **New Simulation**. This opens the [type picker](/more-details/digital-twin/simulation-types) — choose **Prediction**.

<figure><img src="/files/HCRdqHYVZ7NkUtL6rukJ" alt="A Digital Twin&#x27;s simulations: a completed run open in the main view, with the Simulations panel on the right listing recent runs"><figcaption><p>The Simulations panel on the right lists recent runs against the twin; <strong>New Simulation</strong> opens the type picker.</p></figcaption></figure>

***

## Step 1: Choose target variables

Target variables are the outcomes you want to predict. Selecting a target removes it from the input table on the next step — you supply its drivers, not the target itself.

<figure><img src="/files/EsFnzUQPT85I7c9uA459" alt="Step 1 of the Prediction setup: choose target variables, with Churn selected"><figcaption><p>One target is enough; multiple targets run in the same simulation.</p></figcaption></figure>

***

## Step 2: Provide input records

Each row is one scenario. RootCause filters the columns to variables with a causal path to the target.

The form starts empty; you cannot run the simulation until a target is chosen and the required inputs are filled.

<figure><img src="/files/phx1kVkIQSV7DPjoGDjL" alt="The Prediction setup form, empty: the Choose target variables list with 0 of 19 selected, and the Provide input records step starting below"><figcaption><p>The setup form, empty — no target chosen yet (0 of 19), no input records below.</p></figcaption></figure>

Numeric fields take values directly; categorical fields offer dropdowns. Pick `<MISSING>` for any field you don't have a value for.

<figure><img src="/files/xcZQKnG0pyUhs5KB7Rvz" alt="The Provide input records step with three filled scenarios, one column per record, below a note reading Showing 7 of 20 variables, only those with a causal path to your selected target are included; 13 variables have no causal influence on the targets and were filtered out"><figcaption><p>Three scenarios filled in, one column per record. The banner above the grid shows the causal filter at work: only the 7 variables with a causal path to the target remain as inputs; the other 13 were filtered out.</p></figcaption></figure>

The tabs above the form offer three other input methods:

* **File Upload** — a CSV or Parquet file with one row per scenario.
* **Dataset** — pull rows directly from a saved dataset.
* **Field Input** *(default)* — the form view shown above.

***

## Step 3: Confidence level

The default of 0.95 means the model is 95% confident the actual value falls within the shown range. Higher confidence widens the interval; lower narrows it. Leave the default unless you have a specific reason to change it.

***

## Reading the result

Clicking **Run Simulation** opens the result page, with the configuration summary, an AI summary of the prediction, and the predictions table — the run shown at the top of this page. The full output is one shareable record of the prediction: the table shows each input scenario, the predicted class or value, and the confidence interval, and every section exports as PDF.

***

## Past simulations

The Simulations panel lists every run against the twin, with a search field to find past ones. **View all simulations** on the twin's Home opens the same list in full.

<figure><img src="/files/owImM7ix5MFiVEbnxpUe" alt="The New Simulation screen with the Simulations panel on the right listing all nine completed runs against this twin, each with its status and type, above a search field"><figcaption><p>The Simulations panel lists every run against this twin, here nine completed, with search. Click any entry to reopen its result.</p></figcaption></figure>

***

## Other Simulation Types

* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that maximizes or minimizes a target.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — find the minimum change needed to reach a target outcome.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — understand the drivers and impacts behind an outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose the cause of a specific abnormal value.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Step 6: Run Simulations](/user-guide/simulations) — general overview.


# Intervention

Intervention asks the [Digital Twin](/more-details/digital-twin) a counterfactual question: what would happen to a target metric if we changed a variable?

Unlike a [prediction](/more-details/digital-twin/simulation-types/prediction), which estimates an outcome given known inputs, an intervention reaches into the causal graph and forces a variable to a new value. Every downstream variable adjusts according to its causal mechanism, and the change in the target metric is reported with a confidence interval.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Starting a simulation

Open a Digital Twin from the Digital Twins list, open the **Simulations** tab, then click **New Simulation**. This opens the [type picker](/more-details/digital-twin/simulation-types) — choose **Intervention**.

The setup form has three sections plus a configuration summary at the foot. Each section answers part of the question being asked: *what changes, how do we measure the effect, and across which subgroups?*

<figure><img src="/files/7rK4cRg9A3F1CQMjT54n" alt="The empty Intervention setup form, with Section 1 What will you change showing an unset variable picker and Section 2 Define success metrics starting below"><figcaption><p>The empty setup form. Sections build the experiment top to bottom.</p></figcaption></figure>

***

## Target and intervention

Two ideas drive every intervention simulation.

**The target.** The metric whose movement you care about — reducing churn, increasing average revenue per user, cutting handling time.

**The intervention.** The lever you want to test against the target — what if every customer got online backup as part of their package, or month-to-month contracts came at a discount, or onboarding emails went out within an hour of signup?

The form takes them in the opposite order: Step 1 sets the intervention, Step 2 sets the metric. Fix the target in mind first — the intervention is only meaningful as a way to move it.

***

## Step 1: What will you change?

In the example, the change being tested is *move every month-to-month customer onto a two-year contract* — `Contract` set to `Two year`. The **change type** controls how the change is applied; *Target value* (shown) sets a single value uniformly across the population.

<figure><img src="/files/oYVGajhahazMhG7LBXh5" alt="Section 1 of the Intervention form with Contract selected, Target value as the change type, Two year as the new value, and an Estimated Intervention Effect chart previewing the Before and After distribution of Contract"><figcaption><p>Choosing the variable, the change type, and the new value. The Estimated Intervention Effect preview shows how the chosen change shifts the variable's distribution before you run anything.</p></figcaption></figure>

For categorical variables, the **New value** dropdown lists every level the variable can take. For numeric variables, you enter a value directly.

Once a variable is picked, a **Downstream causal paths from "X"** row appears below. Expand it to see which downstream variables the change will propagate to according to the causal graph — useful for confirming what is in scope before you run.

**+ Add condition** restricts the intervention to records matching a filter. Without conditions, the change applies to the entire population. **+ Add intervention** layers a second change on top of the first to test a combined scenario.

***

## Step 2: Define success metrics

A metric is the number whose movement you want to read. At least one is required.

Each metric has a name, a unit (`# Count`, `$`, `%`, …), and a direction — *Higher is better* or *Lower is better*. The direction drives the color of the up and down arrows on the results page.

The query that computes the metric can be built three ways:

* **Natural Language** — describe the metric in plain English; the system writes the SQL.
* **Builder** — pick an aggregation and a column, optionally add filters. The simplest path for standard metrics.
* **SQL** — write the query by hand.

The three tabs stay in sync up to a point: once the SQL has been edited by hand, the Builder locks and offers **Reset Builder** to start fresh.

<figure><img src="/files/lg9JVlMVvx3FRuKFJI1f" alt="The Define success metrics section with metric name churn_rate_after_intervention, unit ratio, direction Lower is better, and the SQL tab open on a CASE-based churn query, with Test SQL reporting Test passed Result: 0.241; a second metric, overall_churn_rate, starts below"><figcaption><p>A metric on the SQL tab. The query must return a single <code>value</code> column; click <strong>Test SQL</strong> to run it against the underlying data; here it passes with a baseline churn rate of 0.241. A second metric, <code>overall_churn_rate</code>, is stacked below.</p></figcaption></figure>

In the Builder, tick **Return 0 instead of NULL when no rows match** if the metric should fail gracefully when filters exclude every record. Without it, an empty result returns NULL and the metric is undefined for that run. **+ Add metric** stacks further metrics; every one is reported separately in the result.

***

## Step 3: Segment definitions

Segments split the result into subgroups so you can compare the effect across them. Each segment is a named filter — for example, *Customers with a Partner* (`Partner equals Yes`) and *Customers without a Partner* (`Partner equals No`).

If no segments are defined, the simulation reports a single overall effect. Segments are optional but the effect of an intervention is rarely uniform across a population, so at least one segmentation is usually worth running.

***

## Configuration Summary

The card at the foot of the form mirrors back the experiment in plain English, with the version of the twin the simulation will run against.

<figure><img src="/files/bJJFmiMy6hw6LN68jbvC" alt="The foot of the Intervention form: an empty Segment definitions section, the version picker set to 1.0.0, and the Configuration Summary reading What if we change Contract to Two year, only when Contract equals Month-to-month, to measure impact on churn_rate_after_intervention and overall_churn_rate, both with Aim: Lower, above the Validate and Run Simulation buttons"><figcaption><p>A completed configuration. The summary mirrors the experiment back in plain English: the change (Contract to Two year, applied only when Contract equals Month-to-month) and the two churn-rate metrics it will be judged on, both aiming lower. <strong>Validate</strong> checks the setup; <strong>Run Simulation</strong> launches it.</p></figcaption></figure>

***

## Reading the result

Clicking **Run Simulation** opens the result page. A progress bar reports the current stage while the simulation runs.

<figure><img src="/files/mV9EMIBCRefgxogSqZFS" alt="The Intervention run page mid-run, with a Simulation Running progress bar and the run&#x27;s configuration — OnlineSecurity to Yes, measured on churn_rate — restated in the sidebar"><figcaption><p>A run in progress; the sidebar restates what is being changed and measured. Static interventions usually complete in seconds.</p></figcaption></figure>

A completed run carries a green **Completed** pill, a duration, and **Export PDF** and **Edit Config** controls. The page leads with an AI summary that states the headline effect in plain English.

<figure><img src="/files/2nse3DLzWFA1NAJOYmhC" alt="A completed Intervention run: the AI Summary reports overall_churn_rate falling by 0.1894, from 0.2427 to 0.0533, when month-to-month customers move to a two-year contract, above the Intervention Impact chart and metric table showing the −78.05% change flagged statistically significant"><figcaption><p>The top of a completed run. The AI summary states the headline effect: churn falls from 0.24 to 0.05, a −78.05% change flagged statistically significant, above the Intervention Impact chart and per-metric table.</p></figcaption></figure>

Below that, four sections give the full picture.

* **Intervention Impact.** A paired bar chart and a metric table reporting **Baseline** vs **After**, the absolute change, the percentage change, and whether the difference is statistically significant.
* **Uncertainty.** The central readout: average effect with its 95% confidence band, the confidence level used, and the significance verdict. A very small p-value indicates the effect is unlikely to be due to chance.
* **Why did the metric move?** A causal-path explanation: for each downstream variable that contributed, the path it took through the graph and how its distribution shifted.
* **Segment Comparison.** Bar chart and table reporting before, after, change, and percentage change for each segment. Useful for spotting heterogeneous effects — segments often move in the same direction with different magnitudes.

<figure><img src="/files/VlNVE9JDEFv3w4EufjmB" alt="The Segment Comparison section of the Intervention result: a per-segment bar chart and table of churn before and after the change across six segments, with the fiber-optic segment falling from 0.40 to 0.11 and another from 0.27 to 0.04, while a segment that already had tech support barely moves"><figcaption><p>Segment Comparison in the result. The fiber-optic internet segment drops from 0.40 to 0.11 while segments that barely churned barely move: the effect is real but concentrated where the change bites. Every section exports as PDF.</p></figcaption></figure>

***

## Past simulations

Past runs appear in the Simulations tab's run list inside the twin, and **View all simulations** on the twin's Home opens the full history. The workflow is the same as for any other simulation type — see [Prediction › Past simulations](/more-details/digital-twin/simulation-types/prediction#past-simulations).

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — predict an outcome for a specific input.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that maximizes or minimizes a target.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — find the minimum change needed to reach a target outcome.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — understand the drivers and impacts behind an outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose the cause of a specific abnormal value.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Step 6: Run Simulations](/user-guide/simulations) — general overview.


# Optimization

Optimization is a search question put to the [Digital Twin](/more-details/digital-twin): across many combinations of input variables, which combination moves a target metric the most in the desired direction?

Unlike a [prediction](/more-details/digital-twin/simulation-types/prediction), which estimates the outcome of one specified input, or an [intervention](/more-details/digital-twin/simulation-types/intervention), which forces one or two variables and reports the downstream effect, an optimization explores a space. You name the objective and the levers the optimizer may pull; it returns the best combination it can find.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Starting a simulation

Open a Digital Twin from the Digital Twins list, open the **Simulations** tab, then click **New Simulation**. This opens the [type picker](/more-details/digital-twin/simulation-types) — choose **Optimization**.

<figure><img src="/files/H5N3qITBXdHyrsUIA4Ch" alt="The New Simulation screen with a Generate from Query box, a Quick Start section, and the simulation type cards below: Prediction, Intervention, Optimization, Best Action, Explanation, and Root Cause Analysis"><figcaption><p>The New Simulation screen. Each type opens its own setup form.</p></figcaption></figure>

The setup form has four numbered sections plus a configuration summary at the foot. Only the first two — the objective and at least one decision variable — are required; constraints are optional and can be skipped on a first pass.

***

## Objective and decision variables

Two ideas drive every optimization.

**The objective.** The metric the optimizer will push in one direction — *Maximize TotalCharges*, *Minimize Churn*, *Maximize NPS*. The direction matters: maximize and minimize are different searches.

**The decision variables.** The levers the optimizer may pull on the way to the objective. A handful of well-chosen levers produces a recommendation a business can act on; selecting every variable invites combinations no operator would ever apply.

The example below minimizes the customer churn rate with three levers as decision variables: `Contract`, `OnlineSecurity`, and `TechSupport`.

***

## Step 1: Optimization objectives

An objective has a name, a direction (Maximize or Minimize), an importance weight, and a SQL expression for the metric.

The metric can be specified three ways, matching the metric builder used elsewhere in the product: **Natural Language** describes it in plain English and lets the system generate the SQL; **Builder** offers aggregation and column pickers for standard metrics; **SQL** writes the query by hand.

<figure><img src="/files/ezLXkp1js0SN0tEZ9ElI" alt="Section 1 of the Optimization form with Goal Minimize, Objective name Customer churn rate, Importance weight 1, and the Natural Language tab selected, its description box awaiting a plain-English metric description above a Generate SQL button"><figcaption><p>Natural Language. Describe the metric in plain English, say <em>the share of customers who churn</em>, and <strong>Generate SQL</strong> writes the query.</p></figcaption></figure>

<figure><img src="/files/87cjftqIhvwhzfcje4tK" alt="The same section on the SQL tab with Goal Minimize and Objective name Customer churn rate, showing SELECT COALESCE(AVG(CASE WHEN Churn = &#x27;Yes&#x27; THEN 1.0 ELSE 0.0 END), 0) as value FROM df and Test passed Result: 0.241"><figcaption><p>SQL. <strong>Test SQL</strong> confirms the baseline before the run: here, the current churn rate is 0.241.</p></figcaption></figure>

The result of **Test SQL** is the baseline against which all improvements are measured. **+ Add objective** stacks a second objective, in which case the importance weights determine the trade-off.

***

## Step 2: Decision variables

A scrollable list of every variable in the twin, with a checkbox against each one. Tick the levers the optimizer is allowed to change; selections appear as chips below the list so the chosen set is visible at a glance.

Anything left unchecked is held at its current distribution. That is useful for pinning demographics or contract terms while letting the optimizer play with product offerings.

***

## Step 3 (optional): Constraints

Two kinds of constraint narrow the search space.

**Variable constraints** bound an individual decision variable — *PhoneService can only be set to Yes*, or *MonthlyCharges must stay between 30 and 100*. **Auto Generate Constraints** asks the model to suggest sensible bounds based on the variables you picked; the suggestions can be edited manually before the run.

**Metric constraints** set rules the optimizer must respect even at the cost of a weaker objective — *average Churn must stay below 0.1*, *Electronic check share of PaymentMethod must not rise*. They are how you encode trade-offs the objective alone cannot express.

Both sections are optional. The example below uses neither — the optimizer is free to explore the unconstrained search space.

***

## Configuration Summary

The card at the foot of the form mirrors back the run in plain English, with the version of the twin the simulation will run against.

<figure><img src="/files/MxxBY35UTS3wt46vIfQS" alt="The foot of the Optimization form: an empty Metric constraints section, the version picker set to 1.0.0, and the Configuration Summary reading Finding optimal settings to Minimize Customer churn rate by adjusting Contract, OnlineSecurity, and TechSupport, above the Validate and Run Simulation buttons"><figcaption><p>The completed configuration. The summary mirrors the run back in plain English: <em>Minimize Customer churn rate</em> by adjusting Contract, OnlineSecurity, and TechSupport, with both constraint sections left empty. <strong>Validate</strong> checks the setup; <strong>Run Simulation</strong> launches the search.</p></figcaption></figure>

***

## Reading the result

A completed run carries a green **Completed** pill, a duration, and **Export PDF** and **Edit Config** controls. The page leads with three headline numbers: how many solutions the optimizer found, whether constraints were satisfied, and how long the search took.

The AI summary states the recommendation in one sentence.

<figure><img src="/files/gG5j2ofOFyoMyWaT6HBM" alt="A completed Optimization run titled Optimize minimize Customer churn rate: the AI Summary reports that setting Contract to Two year, OnlineSecurity to MISSING, and TechSupport to Yes reduces the churn rate by 87.1%, from a 0.2426 baseline to 0.0312, above the Optimization Results stats of 1 solution found, constraints satisfied, 8.7s execution, and the Recommended Solution card"><figcaption><p>The top of a completed run. The AI summary states the recommendation: a three-lever change cutting churn 87.1% from the 0.24 baseline, with all constraints satisfied, above the three headline stats. It also notes the cost side plainly: the solution requires 3 interventions.</p></figcaption></figure>

Below that, three sections give the full picture.

* **Recommended Solution.** A card describing the winning combination in plain English, with the optimized metric, the baseline, and the percentage uplift. The Recommended Changes row lists each variable that has to move and the value it has to move to. A *Global strategy* badge confirms the change applies to the entire population.
* **Baseline vs Optimized.** A paired bar chart for each objective, with baseline and optimized values side by side. The percentage label on the right is the absolute uplift.
* **All Solutions.** A table of every candidate the search produced, ranked by objective improvement. The baseline appears as row 0 for reference; ticks in the **Status** column flag solutions that satisfied every constraint. Useful for comparing runner-up strategies — a slightly worse-scoring solution sometimes involves fewer or cheaper changes.

<figure><img src="/files/lp1vAKMreLblSua1wkSA" alt="The lower half of the Optimization result: three Recommended Changes rows (Contract Month-to-month to Two year, OnlineSecurity No to MISSING, TechSupport No to Yes), an All constraints satisfied banner, the Baseline vs Optimized bar chart showing the churn rate falling from 0.24 to 0.03 (−87.14%), and the All Solutions table with the baseline as the reference row"><figcaption><p>The rest of the result: the three recommended changes, the baseline-vs-optimized chart (0.24 → 0.03, −87.14%), and the All Solutions table with the baseline as row 0. Note the OnlineSecurity recommendation: the optimizer searches every level present in the data, including a missing/blank level, so inspect recommended values before acting on them. Every section exports as PDF.</p></figcaption></figure>

***

## Past simulations

Past runs appear in the Simulations tab's run list inside the twin, and **View all simulations** on the twin's Home opens the full history. The workflow is the same as for any other simulation type — see [Prediction › Past simulations](/more-details/digital-twin/simulation-types/prediction#past-simulations).

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — predict an outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — find the minimum change needed to reach a target outcome.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — understand the drivers and impacts behind an outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose the cause of a specific abnormal value.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Step 6: Run Simulations](/user-guide/simulations) — general overview.


# Best Action

Best Action runs the [Digital Twin](/more-details/digital-twin)'s counterfactual reasoning in reverse: given a record you want to change, what is the smallest set of changes that would reach a target outcome?

Where an [optimization](/more-details/digital-twin/simulation-types/optimization) searches a whole population for the combination that pushes a metric furthest, Best Action starts from specific records — individual customers, machines, or cases — and finds the minimal action for each one. A [prediction](/more-details/digital-twin/simulation-types/prediction) tells you a customer is likely to churn; an [intervention](/more-details/digital-twin/simulation-types/intervention) tells you what one change would do across everyone; Best Action tells you the fewest changes that would turn *this* customer from churn to retained, and how confident the model is in each.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Starting a simulation

Open a Digital Twin from the Digital Twins list, open the **Simulations** tab, then click **New Simulation**. This opens the [type picker](/more-details/digital-twin/simulation-types) — choose **Best Action**.

The setup form has four numbered sections plus a configuration summary at the foot. Only the first two — the target outcomes and at least one baseline record — are required; constraints and the change limit refine the search but can be left at their defaults on a first pass.

<figure><img src="/files/VlKuHXDIqmYjqbDBJiRl" alt="The empty Best Action setup form: Target outcomes with the target variable and value unset, and Baseline states reading No records added yet"><figcaption><p>The empty setup form. The stepper at the top walks the sections in order; nothing runs until a target and at least one record are set.</p></figcaption></figure>

***

## Targets and baselines

Two ideas drive every Best Action run.

**The target.** The outcome you want each record to reach — *Churn = No*, *Defect = Pass*, *Approved = Yes*. This is the destination the solver works back from.

**The baseline states.** The records you want to move there — the customers at risk, the cases that failed, the units that fell out of spec. Each row is a starting point; the solver treats them independently and returns one action plan per row. This is what sets Best Action apart from the other simulation types: it operates on concrete records, not the population as a whole.

***

## Step 1: Target outcomes

Set the outcome the solver must reach. Each target is a variable and the value it should take — for example `Churn` set to `No`.

<figure><img src="/files/ozix8LjR9cgcXpm1V0YX" alt="Section 1 of the Best Action form with target variable Churn and target value No, a note reading Match mode: Exact — tolerance and direction modes apply only to numeric targets, and the Baseline states section starting below"><figcaption><p>A target outcome, Churn set to No. For categorical targets the match is exact; numeric targets add tolerance and direction modes. The Baseline states section, covered next, starts below.</p></figcaption></figure>

For a categorical target such as `Churn`, the match mode is **Exact** — the outcome must equal the chosen value. Numeric targets unlock tolerance modes (reach within a band) and direction modes (at least, at most). **+ Add target** stacks a second outcome the solver must satisfy at the same time.

***

## Step 2: Baseline states

The records to act on. Each row is a starting state the solver will try to nudge to the target. There are three ways to supply them:

* **Field Input** — enter records by hand in a table, one column per record, choosing a value for each variable from a dropdown. Best for a handful of cases.
* **File Upload** — drop in a CSV. The file must carry every variable in the twin as a column; the panel lists the exact set it expects.
* **Dataset** — pull rows straight from an existing [dataset](/user-guide/data-views), the natural choice when the records you care about already live in the workspace.

<figure><img src="/files/JJDquhExXMnPagvwC9Qd" alt="The Baseline states section on the Field Input tab, showing an Input Records table with a column per record and a value set for every variable — customerID, gender, SeniorCitizen, Partner, tenure, Churn, and so on"><figcaption><p>Field Input. Each record is a column; set a value for every variable to define a starting state.</p></figcaption></figure>

<figure><img src="/files/hK0ET7BwLn3UCHvkNTMl" alt="The Baseline states section on the File Upload tab, with a dashed drop zone reading Click to Upload CSV File and the list of required columns the file must contain"><figcaption><p>File Upload. The CSV must contain every variable the twin uses as a column.</p></figcaption></figure>

The more representative the baseline records, the more actionable the result — a row that is already close to the target needs only a small change, which is exactly the recommendation Best Action is designed to surface.

***

## Step 3 (optional): Constraints

Constraints work exactly as they do for an [optimization](/more-details/digital-twin/simulation-types/optimization#step-3-optional-constraints). A constraint can pin a variable so the solver may not touch it — useful for fields a business cannot change, such as a customer's tenure or demographics — or puts bounds on the values an eligible variable may take. **Auto Generate Constraints** proposes sensible bounds from the variables in the twin, which can then be edited by hand.

Any variable without a fixed constraint is eligible to change. Constraints are optional; leaving them empty lets the solver consider every variable.

***

## Step 4: Limit changes

The defining control of Best Action. **Max changes** caps how many variables the solver may change in any single record's recommendation. A low cap yields simple, actionable plans — change one or two things — while a higher cap lets the solver reach harder targets at the cost of asking more of the operator.

This is the knob that makes the result a *next best action* rather than a wholesale redesign: it forces the solver to find the shortest path to the target, not merely a path.

***

## Configuration Summary

The card at the foot of the form mirrors back the run in plain English — the target, the number of starting records, and the change cap — alongside the version of the twin the simulation will run against.

<figure><img src="/files/3t60twDlO62nZPAGErGQ" alt="The populated Best Action form with target Churn = No, match mode Exact, and a Baseline states table of customer records on the Field Input tab"><figcaption><p>The populated form: target Churn = No and the baseline records in place. <strong>Run Simulation</strong> launches the search across every baseline record.</p></figcaption></figure>

***

## Reading the result

A completed run carries a green **Completed** pill, a duration, and **Export PDF** and **Edit Config** controls. The page leads with an AI summary that reads the whole result set at once — the most consistent lever across records, how many targets were met, and where the easy wins are.

Below the summary, **Next Best Action Results** lists one block per baseline record. Each block names the record (Sample #1, #2, …), reports how many actions were found, and lists each recommended change as a row: the variable, its current value, the value to move it to, and a **confidence** score for that change. Records needing more than a few changes show a **Show N more actions** expander.

Because the recommendations are per record, the result is a worklist rather than a single headline: high-confidence single-change records are the cheapest wins, while records that need several changes can be triaged or set aside.

<figure><img src="/files/MBq9ZIkLhNzEguTTWefI" alt="The Next Best Action Results for Samples #1 and #2, each with one recommended action pairing a Contract change with OnlineSecurity set to Yes, at 81.22% and 94.95% confidence, next to a sidebar showing the run configuration Churn should be No exactly across 2 starting records with at most 3 variables changed per scenario"><figcaption><p>The result list, one block per record. Sample #1 reaches Churn = No by moving Contract to One year and OnlineSecurity to Yes at 81.22% confidence; Sample #2 moves Contract to Two year and OnlineSecurity to Yes at 94.95%. The sidebar restates the run: Churn = No across 2 starting records, at most three variables changed per scenario. Every section exports as PDF.</p></figcaption></figure>

***

## Past simulations

Past runs appear in the Simulations tab's run list inside the twin, and **View all simulations** on the twin's Home opens the full history. The workflow is the same as for any other simulation type — see [Prediction › Past simulations](/more-details/digital-twin/simulation-types/prediction#past-simulations).

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — predict an outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that maximizes or minimizes a target.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — understand the drivers and impacts behind an outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose the cause of a specific abnormal value.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Step 6: Run Simulations](/user-guide/simulations) — general overview.


# Explanation

Explanation reads the [Digital Twin](/more-details/digital-twin) to answer *why*, not *what-if*. It takes a relationship that already exists in the model and decomposes it: how strongly one variable drives another, which drivers matter most, and the pathways an effect travels along. The product sums it up in one line: *understand drivers and impacts for outcomes*.

Where a [prediction](/more-details/digital-twin/simulation-types/prediction) tells you an outcome, an [intervention](/more-details/digital-twin/simulation-types/intervention) tells you what one change would do, and an [optimization](/more-details/digital-twin/simulation-types/optimization) finds the best combination to aim for, Explanation steps back and accounts for the causal structure itself. Nothing is changed and no new scenario is run — the tool reads the trained twin and explains it.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Overview

Open a Digital Twin from the Digital Twins list, open the **Simulations** tab, click **New Simulation**, and choose **Explanation** from the [type picker](/more-details/digital-twin/simulation-types).

<figure><img src="/files/fdJFOoBxL97oOYL9NWjC" alt="The Explanation setup form opening on Step 1, Explanation mode, with three tiles — Directional, Discovery, Impact — Directional selected, and the Variables step below asking for a Cause and an Effect variable, both still empty"><figcaption><p>The Explanation setup opens on the mode step: Directional, Discovery, or Impact. The mode chosen here decides which variables the next step asks for.</p></figcaption></figure>

Every Explanation run follows the same five steps.

**1. Pick the mode.** The mode frames the question and decides which variables you supply next:

* **Directional** — explain a specific cause → effect relationship.
* **Discovery** — find the strongest drivers of an effect.
* **Impact** — see what outcomes a cause influences.

**2. Select the variables.** A **Cause variable** is the lever; an **Effect variable** is the outcome. The mode decides which you need — Directional asks for both, Discovery for the effect alone, Impact for the cause alone.

**3. Add segments (optional).** A segment is a filter — one or more conditions, such as *tier = premium* — that the simulation runs separately, so you can compare how an explanation differs across subgroups. **Suggest Segments** proposes them from the twin; **+ Add segment** defines one by hand. Leave the section empty to run across the whole population.

**4. Run the simulation.** The Configuration Summary restates the run as a plain-English **Research question**. **Validate** checks the configuration; **Run Simulation** launches it against the chosen twin version.

**5. Review the results.** A finished run shows a green **Completed** pill, a duration, **Export PDF** and **Edit Config**, and opens with the Configuration Summary and an **AI Summary**. Everything below that depends on the mode.

***

## Detailed explanation

The mode chosen in step 1 changes both the inputs you supply and the result you get back. Each of the three is shown below with its own setup (input) and result (output).

### Option 1 — Directional

*Explain a specific cause → effect relationship.* Use Directional when you already have a hypothesis — "does Contract affect Churn?" — and want it quantified. It asks for both a **Cause variable** and an **Effect variable**.

<figure><img src="/files/JIGkKvTU0CxTyF81w3pt" alt="The Explanation setup form in Directional mode: Step 1 has Directional selected, Step 2 shows Cause variable Contract and Effect variable Churn, and the optional Segments step follows below"><figcaption><p><strong>Input.</strong> Both a Cause variable (Contract) and an Effect variable (Churn) are set; Step 3 Segments is left empty to run across the whole population.</p></figcaption></figure>

The result leads with **Causal Relationship Analysis** — a headline card for the pair, here *Contract → Churn*: a sustained Contract change moves the probability of *Churn: Yes* from **22.7% to 35.5%** (+12.7 percentage points), with a confidence rating, a result-reliability note, and an effect range. Below it, **Categorical Outcome Analysis** breaks the shift down by outcome value as *Delta Probabilities*. **Causal Pathways** then decomposes the total effect into a **Direct Effect** and the ranked indirect paths it travels (Path 1, Path 2, …), each with its share and effect size, drawn as a *Pathway Contributions* donut. A **Segment Analysis** section closes the page.

<figure><img src="/files/hYfQXx46bNWNYr6DRiXh" alt="A Directional Explanation result for the research question How does Contract influence Churn? The AI summary reports a 0.134979 average increase in Churn with very strong statistical support, driven almost entirely by the direct Contract to Churn path; the Causal Relationship Analysis card reads Contract arrow Churn, Churn Yes 22.7% to 35.5%, plus 12.7 percentage points, High confidence, over a 10,000 sample size, above the start of the Delta Probabilities chart"><figcaption><p><strong>Output.</strong> The headline card quantifies the single relationship, Contract shifting <em>Churn: Yes</em> from 22.7% to 35.5%, with the AI summary spelling out the effect size and its significance above it.</p></figcaption></figure>

<figure><img src="/files/IwggcW6eGiuUmwM3cAPy" alt="Further down the same Directional result: the Causal Pathways donut attributing 97.8% of the effect to the Direct Effect, with three small indirect paths through TechSupport, PaymentMethod, and OnlineSecurity; and Segment Analysis for the overall population with per-contract-type effects, all High confidence"><figcaption><p>Deeper in the same result: Causal Pathways attributes 97.8% of the effect to the direct path, and Segment Analysis breaks the effect out by contract type.</p></figcaption></figure>

### Option 2 — Discovery

*Find the strongest drivers of an effect.* Use Discovery when you know the outcome you care about but not what moves it most. It asks only for the **Effect variable**.

<figure><img src="/files/3WNF27nBpqDssUFsUz7u" alt="The Explanation setup form in Discovery mode. Step 1 has Discovery selected; Step 2 Variables asks only for an Effect variable, set to Churn; the optional Segments step follows with a How segments work note"><figcaption><p><strong>Input.</strong> Discovery needs only the Effect variable (Churn); the Segments section is identical across all three modes.</p></figcaption></figure>

The result is a **Key Driver Analysis** — a ranked bar chart of each driver's *Relative contribution (%)* to the *Causal Effect on Churn*, with Contract, InternetService, and OnlineSecurity topping the list.

Beneath the chart, every driver is a row — **Driver**, **Rank**, **Contribution**, **Range**, **Confidence** — and each one expands into the same deep analysis a Directional run produces for a single pair. Discovery is, in effect, Directional run across every driver at once and ranked.

<figure><img src="/files/qoww4W0f7orDfpJ4DJND" alt="The Discovery Explanation result: the Key Driver Analysis bar chart titled Causal Effect on Churn with Contract highest, above the ranked driver table where Contract contributes 44.4%, InternetService 25.4%, OnlineSecurity 17.0%, TechSupport 7.7%, and PaymentMethod 3.2%, each row with a range, a direct and indirect split, and High confidence"><figcaption><p><strong>Output.</strong> The ranked drivers: each row carries its contribution, range, and confidence, and expands into the full pathway breakdown.</p></figcaption></figure>

### Option 3 — Impact

*See what outcomes a cause influences.* Use Impact when you know the lever and want to trace everything downstream of it. It asks only for the **Cause variable**.

<figure><img src="/files/6TPm1Fu8WlZ86lqrX1bw" alt="The Explanation setup form in Impact mode. Step 1 shows the three mode tiles — Directional, Discovery, Impact — with Impact selected; Step 2 Variables asks only for a Cause variable, set to Contract; the optional Segments step follows below"><figcaption><p><strong>Input.</strong> Impact needs only the Cause variable (Contract).</p></figcaption></figure>

The result is an **Impact Analysis** — a *Downstream Effects* chart plotting the *Causal impact from* the chosen cause across the variables it reaches, and an **Affected Variable** table giving each one a **Contribution** (split into direct and indirect), a **Range**, and a **Confidence** rating. It is the mirror image of Discovery: one cause, many effects, rather than one effect, many causes.

<figure><img src="/files/SxZ1RhXNbutIygA5zQY2" alt="An Impact Explanation result for the research question What does Contract influence? The Downstream Effects of Contract chart shows TotalCharges towering over every other variable, and the Affected Variable table lists TotalCharges at 98.3% contribution, then tenure, TechSupport, Churn, PaymentMethod, OnlineSecurity, and PaperlessBilling, each with a range and High confidence"><figcaption><p><strong>Output.</strong> Contract's downstream footprint is dominated by TotalCharges at 98.3%; every other affected variable, including Churn, carries a sliver of the total impact.</p></figcaption></figure>

***

## Past simulations

Past runs appear in the Simulations tab's run list inside the twin, and **View all simulations** on the twin's Home opens the full history. The workflow is the same as for any other simulation type — see [Prediction › Past simulations](/more-details/digital-twin/simulation-types/prediction#past-simulations).

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — predict an outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that maximizes or minimizes a target.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — find the minimum change needed to reach a target outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose the cause of a specific abnormal value.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Step 6: Run Simulations](/user-guide/simulations) — general overview.


# Root Cause Analysis

Root Cause Analysis answers a specific question: *this value came out wrong — why?* You point it at a variable that behaved unexpectedly, give it the record you want to diagnose, and it traces **upstream** through the [Digital Twin](/more-details/digital-twin)'s causal graph to find what drove the anomaly.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## How it works: expected vs. observed

A trained Digital Twin doesn't only predict an outcome from inputs — it learns the expected relationships among *all* the variables. So for any record, it can say, for each value: *given everything else I know about this record, here is the value I'd expect, and the range it should fall in.*

A **deviation** is the gap between the value you observed and the value the model expected. RootCause measures it as a **z-score** — the number of standard deviations the observation sits from expectation:

* A z-score near **0** means the value is in line with what the model expected.
* A **large** z-score (positive or negative) means the value is genuinely surprising — it doesn't fit what the model learned.

Root Cause Analysis starts from the variable you flag as anomalous and walks the causal graph upstream, scoring the deviation of each variable along the way. The upstream variables with the largest deviations are the candidate root causes: they are the surprises that explain the surprise you started with.

> **Root Cause Analysis vs. Anomaly Scan.** They answer opposite questions. **Anomaly Scan & Diagnosis** watches your data and surfaces anomalies *for* you — you don't have to know what's wrong. **Root Cause Analysis** is deliberate: you already know something is off, name it, and ask the platform to diagnose the cause.

***

## Starting a simulation

Open your trained Digital Twin from the Digital Twins list.

<figure><img src="/files/lWmrXR4b3B8sbRtL0AXH" alt="A trained Digital Twin&#x27;s Home showing the causal graph, a Model trained and ready banner, and side cards reporting 19 variables, 31 relationships, and a 69.6% model fit"><figcaption><p>Root Cause Analysis runs against a trained Digital Twin — the same causal model that powers every other simulation type.</p></figcaption></figure>

Open the **Simulations** tab, click **New Simulation**, and choose **Root Cause Analysis** from the type picker.

<figure><img src="/files/IcWpqsKu28TR33c4yN2i" alt="The empty Root Cause Analysis setup form: Step 1 Anomalous variable with the Select variable to diagnose dropdown unset, and Step 2 Observed data with one blank record on the Field Input tab"><figcaption><p>The Root Cause Analysis setup as it opens: the anomalous variable to diagnose on top, the observed data to diagnose it against below.</p></figcaption></figure>

***

## Step 1: Choose the anomalous variable

Select the variable showing unexpected behavior. This is the starting point — the analysis traces upstream from here through the causal graph to find likely root causes.

In the example below, the anomalous variable is **MonthlyCharges**: we want to understand why customers' observed charges sit where they do relative to what the model expects.

***

## Step 2: Provide the observed data

Supply the record you want to diagnose. Each row is one independent sample; you can diagnose several at once. As with Prediction, you can enter records by hand (**Field Input**), upload a **File**, or pull rows from a **Dataset**.

Each record carries the full customer profile — services, contract, tenure, and the observed MonthlyCharges value. The platform validates required fields before it will run.

<figure><img src="/files/gNlfT1lLMimorItbvf83" alt="The Root Cause Analysis setup form with MonthlyCharges as the anomalous variable and an Input Records table of customer records, one column per record, filled in on the Field Input tab"><figcaption><p>The setup filled in: MonthlyCharges as the anomalous variable, with the observed customer records to diagnose — one column per record.</p></figcaption></figure>

***

## Step 3: Detection settings *(optional)*

These tune how sensitive the analysis is — how large a deviation has to be before a variable is flagged.

* **Target false-positive rate** — the slider runs from 0.1% (strict) to 5% (loose). A lower rate flags fewer variables and reduces false positives; a higher rate flags more. The default is 0.50%.

Leave the default unless you have a reason to change it. Pick the twin version to run on, review the **Configuration Summary**, and click **Run Simulation**.

***

## Running the analysis

The twin runs the diagnosis — scoring the observed records against its learned expectations and tracing the causal path upstream from the anomalous variable. Even a large batch is fast: the run below scored 4,998 records in seconds.

<figure><img src="/files/zkfLq9qpfxAFP2xNrV6b" alt="The Root Cause Analysis run page just after completion: the AI summary and the per-sample deviation table are populated, with the run configuration — diagnosing root causes of anomaly in MonthlyCharges across 4,998 input samples at a 1.00% target FPR — in the sidebar"><figcaption><p>The run page as the analysis lands: the AI summary and the per-sample table arrive together. The sidebar restates the run — diagnosing MonthlyCharges across 4,998 samples, here at a 1.00% target FPR.</p></figcaption></figure>

***

## Reading the result

The result opens with an **AI Summary** — a plain-language verdict on the variable you flagged — followed by the **Root Cause Analysis** table: one row per sample, each carrying the target's observed value, the expected value and its range, a severity z-score, whether the sample counts as anomalous, and (when one is found) the top root cause with its confidence.

<figure><img src="/files/aZ64peuv5YiMp1XCuWsg" alt="A completed Root Cause Analysis: the AI Summary reports no identified upstream root cause for MonthlyCharges, with z-scores ranging from −1.27 to 0.20, fully explained by observable factors with observable attribution 1.0 and latent attribution 0.0, above the per-sample table where every row shows a mild z-score near 1.9 against an expected 65.02 ± 27.75 and Anomalous: No"><figcaption><p>A completed analysis. The AI Summary is the headline verdict; the table below shows the working: observed vs expected, severity, and the anomalous flag for every sample.</p></figcaption></figure>

In this run, the verdict was that there was **no clear cause to find**:

> All five samples show no identified upstream root cause for MonthlyCharges, with targetZScore values ranging from **−1.27 to 0.20**, so the anomaly is mild rather than strongly abnormal. The results are fully explained by observable factors, with observableAttribution at 1.0 and latentAttribution at 0.0, **and no causalPaths were found.**

This is the system working as intended, not failing. Across all 4,998 samples the deviations stayed mild: the largest z-scores sat around 1.9, well inside the expected range of 65.02 ± 27.75, so no sample cleared the 0.50% false-positive threshold and none was flagged anomalous. Rather than manufacture a tidy explanation, the platform reported that the observed charges are consistent with what the model expects, and the Observable/Latent attribution split confirms the small deviations that do exist are carried by measured variables, not hidden ones.

That restraint is the point. A Digital Twin's Root Cause Analysis is grounded in the causal model and the evidence in front of it. When the evidence supports a cause, it names it and shows the deviation that justifies it; when the evidence doesn't, it says so. The answer is always defensible, because it never fakes one.

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — the most likely outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that best meets a goal.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — the minimum change needed to reach a target outcome.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — the drivers and impacts behind an outcome.
* [Anomaly Scan & Diagnosis](/more-details/digital-twin/simulation-types/anomaly-scan) — scan every variable for anomalies and diagnose each one.

See [Simulation Types](/more-details/digital-twin/simulation-types) for the full picture and [Step 6: Run Simulations](/user-guide/simulations) for the general overview.


# Anomaly Scan & Diagnosis

Anomaly Scan & Diagnosis answers the question you ask when you *don't* yet know what is wrong: *is anything in this data off — and if so, what caused it?* You hand it a set of records, and it checks **every** variable in each one against what the [Digital Twin](/more-details/digital-twin) expects, flags the records that don't fit, and — with one setting enabled — automatically runs [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) on each one it flags.

For the workflow that produces a Digital Twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

> **Anomaly Scan vs. Root Cause Analysis.** They are two halves of the same idea. [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) is deliberate: you already know a value looks wrong, name it, and ask for the cause. **Anomaly Scan & Diagnosis** is the discovery step before that: it watches every variable for you, surfaces the records that don't fit, and then diagnoses each one — so you don't have to know what is wrong to begin with.

***

## How it works: every variable, every record

A trained Digital Twin learns the expected relationships among *all* the variables, so for any record it can say, for each value: *given everything else I know about this record, here is the value I'd expect, and the range it should fall in.* The gap between observed and expected is a **deviation**, measured as a **z-score** — the number of standard deviations the observation sits from expectation:

* A z-score near **0** is in line with expectation.
* `|z| ≥ 2` is uncommon (≈1 in 20), `|z| ≥ 3` is rare (≈1 in 370), `|z| ≥ 4` is extreme (≈1 in 16,000).

Root Cause Analysis scores deviations along the path upstream from *one* variable you name. Anomaly Scan does the wider job first: it scores **every** variable in **every** record you give it, and flags any sample that carries a deviation large enough to clear your sensitivity threshold. Where Auto-RCA is enabled, each flagged sample is then handed to Root Cause Analysis automatically, so the scan returns not just *which* records are anomalous but *why*.

***

## Starting a simulation

Open your trained Digital Twin from the Digital Twins list.

<figure><img src="/files/UiGWiDKs2APPlBe2QsTi" alt="A trained Digital Twin open in the platform, showing its causal graph with the Model trained &#x26; ready banner and the Configuration, Versions, Simulations, and Model evaluation cards"><figcaption><p>Anomaly Scan runs against a trained Digital Twin — the same causal model that powers every other simulation type.</p></figcaption></figure>

Open the **Simulations** tab, click **New Simulation**, and choose **Anomaly Scan & Diagnosis** from the type picker.

<figure><img src="/files/iGQySRf9h65uEMfovySl" alt="The empty Anomaly Scan &#x26; Diagnosis setup form: Step 1 Observed data with one blank record on the Field Input tab, listing every variable in the twin"><figcaption><p>The Anomaly Scan setup as it opens. There is no variable to name — the scan checks every variable in every record you provide.</p></figcaption></figure>

***

## Step 1: Provide the observed data

Supply the records you want to scan. Each row is one independent sample; the system checks every variable in every row. As with [Prediction](/more-details/digital-twin/simulation-types/prediction), you can enter records by hand (**Field Input**), upload a **File**, or pull rows from a **Dataset**.

Each record carries the full profile — services, contract, charges, tenure, and the observed outcome. The platform validates required fields before it will run.

<figure><img src="/files/64Qd5QfClm9nOVjSAnI6" alt="The Observed data step on the Dataset tab, listing three datasets to load records from (View of Customer Details, View of Customer Subscription info, and the Customer Subscription info × Customer Details star join), each with 4,998 rows, above the Detection settings step"><figcaption><p>Observed data on the Dataset tab: pick a dataset and its records load as the samples to scan; here each of the three carries 4,998 rows. Only columns matching the twin's variables are imported. The detection settings follow below.</p></figcaption></figure>

***

## Step 2: Detection settings *(optional)*

These tune how sensitive the scan is, and whether it diagnoses on its own.

* **Target false-positive rate** — the slider runs from 0.1% (strict) to 5% (loose). A lower rate flags fewer records and reduces false positives; a higher rate flags more. The default is 0.50%.
* **Automatically run root cause analysis on anomalous samples** — when ticked, every record the scan flags is passed straight to [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis). This is the *Diagnosis* in the name: the scan finds the anomaly, the diagnosis explains it. Leave it on unless you only want the flag.

Pick the twin version to run on, review the **Configuration Summary**, and click **Run Simulation**.

***

## Running the scan

Scanning every variable across every record — and diagnosing each flagged one — is heavier than a single prediction. Expect a run to take minutes rather than seconds.

<figure><img src="/files/Wvel67bUOy8CaDQ7vuGN" alt="The Anomaly Scan run page mid-run, with a Simulation Running progress bar at the Initializing stage and the run list on the right showing only completed runs"><figcaption><p>The scan in progress — this run scans every variable across 4,998 samples at a 1.00% target FPR with Auto-RCA enabled. Expect minutes, not seconds.</p></figcaption></figure>

***

## Reading the result

The result opens with the headline verdict — how many anomalies were found across how many samples — followed by the z-score legend and a **Samples** table. Each anomalous sample is one row, carrying its severity, the variables that were flagged, and (with Auto-RCA on) its diagnosed root cause. Click any row to open its full Root Cause Analysis. Clean samples are hidden by default; toggle **Show normal samples** to see them.

<figure><img src="/files/X6cPrN1jE2U12A9HZUIO" alt="A completed Anomaly Scan reporting 28 of 4998 samples anomalous, with the z-score legend, the anomaly score distribution, and a chart of the most frequently flagged variables led by TotalCharges and MonthlyCharges"><figcaption><p>A completed scan. The headline states the count, the charts show where the anomalies sit, and the samples table below lists each flagged record with its diagnosed cause.</p></figcaption></figure>

In this run, the verdict was **28 of 4,998 samples anomalous**:

> 28 of 4998 samples anomalous. 4998 samples scanned · target FPR: 0.50%.

The two charts unpack that count. The score distribution shows the overwhelming majority of records sitting far below the anomaly threshold, and the most frequently flagged variables chart shows the anomalies concentrating in **TotalCharges** and **MonthlyCharges**. With Auto-RCA on, the diagnosis goes a step further: it points to MonthlyCharges as the top cause behind the worst TotalCharges anomalies, so the issue is concentrated around those two variables rather than scattered across the model.

That grounding is the point, and it mirrors [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis): the answer comes from the causal model and the evidence in front of it. When a record genuinely deviates, the scan flags it and, with Auto-RCA, traces the cause. When nothing deviates, it says so. The answer is always defensible, because it never invents one.

***

## Other Simulation Types

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — the most likely outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a single variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that best meets a goal.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — the minimum change needed to reach a target outcome.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — the drivers and impacts behind an outcome.
* [Root Cause Analysis](/more-details/digital-twin/simulation-types/root-cause-analysis) — diagnose a specific outcome you already know is wrong.

See [Simulation Types](/more-details/digital-twin/simulation-types) for the full picture and [Step 6: Run Simulations](/user-guide/simulations) for the general overview.


# Temporal Simulations

A **temporal** Digital Twin — one built on time-series data — supports its own family of simulations, parallel to the [static simulation types](/more-details/digital-twin/simulation-types) but aware of time. Where a static simulation answers a question about a single moment, a temporal simulation answers it across a horizon: not "what is the outcome?" but "how does the outcome evolve, step by step?"

The system sets a twin's type to Temporal automatically when it detects a time column during [twin creation](/user-guide/creating-digital-twin). On a temporal twin, the **New Simulation** picker shows the temporal family in place of the static one.

## The temporal family

| Type                                                                 | Question it answers                                                        | Static counterpart       |
| -------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------ |
| [Forecast](/more-details/digital-twin/temporal-simulations/forecast) | How will these variables evolve over the next *n* steps?                   | Prediction               |
| **Temporal Intervention**                                            | How does a time-bounded change affect outcomes over time?                  | Intervention             |
| **Temporal Optimization**                                            | What actions over time best meet a goal, given constraints?                | Optimization             |
| **Temporal Best Action**                                             | What is the minimum change over time needed to reach a target?             | Best Action              |
| **Temporal Explanation**                                             | What time-dependent relationships drive an outcome?                        | Explanation              |
| **Time-Series Root Cause Analysis**                                  | How did a variable drift from its expected trajectory, and what caused it? | Root Cause Analysis      |
| **Time-Series Anomaly Scan & Diagnosis**                             | Which timesteps are anomalous, and why?                                    | Anomaly Scan & Diagnosis |
| **Causal Health Monitor**                                            | What emerging issues should I be alerted to before they escalate?          | *(temporal only)*        |

The types shipping today are [**Forecast**](/more-details/digital-twin/temporal-simulations/forecast) (which has a dedicated page), **Temporal Intervention**, and the **Causal Health Monitor** — both covered in [Step 6: Run Simulations](/user-guide/simulations). The remaining counterparts in the table are rolling out and appear in the **New Simulation** picker as they ship. Panel time-series twins get the available types as per-environment **Panel** variants.


# Forecast

Forecast projects selected variables forward in time, returning a trajectory for each with a confidence band that widens further into the future. It is the temporal counterpart of [Prediction](/more-details/digital-twin/simulation-types/prediction): where Prediction answers "what outcome is most likely for this input?", Forecast answers "how will these variables evolve over the next *n* steps?"

Forecast is available on **temporal** Digital Twins — those built on time-series data. The system auto-detects a time column and sets the twin's type to Temporal when you [create it](/user-guide/creating-digital-twin); no separate setup is needed. For the workflow that produces a twin in the first place, see [Step 5: Build Digital Twin](/user-guide/creating-digital-twin).

***

## Starting a simulation

Open a temporal Digital Twin, open the **Simulations** tab, then click **New Simulation**. The type picker for a temporal twin differs from the static one: it offers time-aware simulations, with **Forecast**, **Temporal Intervention**, and **Causal Health Monitor** available today and the rest of the temporal family rolling out (see [Temporal Simulations](/more-details/digital-twin/temporal-simulations)).

<figure><img src="/files/zgIrv08ehK09gfGmiNbG" alt="The New Simulation screen for a temporal Digital Twin, with Quick Start suggestions and the temporal type cards — Forecast, Temporal Intervention, Temporal Optimization"><figcaption><p>The temporal twin's simulation menu, with generated Quick Start suggestions above the type cards. Choose <strong>Forecast</strong> to project variables forward in time.</p></figcaption></figure>

Choose **Forecast** to open the setup.

***

## Step 1: Select forecast targets

The forecast targets are the time-series variables you want projected forward. Each selected target is forecast independently across the horizon. Pick as many as you need — every target appears as its own chart in the result.

***

## Step 2: Forecast horizon

The horizon sets how many time steps ahead the simulation covers. The bar shows your training range against the forecast range, so you can see how far past the data you are projecting. A horizon of 60 days on a model trained over 364 days, for example, extends two months beyond the last observation.

Forecasting far beyond the training range is possible, but the confidence band widens the further out you go — the model is honest about growing uncertainty.

***

## Step 3: Forecast from *(optional)*

By default the forecast begins at the last date in the training data. Set a start time here — relative to the last training date, or a custom date — to begin the projection earlier or later.

***

## Step 4: Confidence level

The default of 0.95 means the model is 95% confident the actual value will fall within the shown band. Higher confidence widens the band; lower narrows it. Leave the default unless you have a specific reason to change it.

<figure><img src="/files/CvToz9ukwauGxUdISoJz" alt="The Forecast setup: selecting forecast targets from the twin&#x27;s time-series variables, with the optional Forecast from section below"><figcaption><p>The start of the Forecast setup: pick the targets to project — each selected target becomes its own chart in the result.</p></figcaption></figure>

***

## Running the forecast

Select the twin versions to run on, review the configuration summary, and click **Run Simulation**. **Validate** checks the setup without running it.

<figure><img src="/files/5QmPiinhElt9j8u4b1xr" alt="The end of the Forecast setup: confidence level 0.95, the version selector, the Configuration Summary, and the Run Simulation button"><figcaption><p>The configuration summary confirms what is being forecast, over what horizon, at what confidence — the last check before running.</p></figcaption></figure>

***

## Reading the result

The result page opens with an AI summary of the forecast, a per-target summary of net change, and one chart per target.

<figure><img src="/files/OH2Ioq6aad10FoGgExTq" alt="A completed Forecast run over a 1-week horizon at 95% confidence: AI summary, forecast summary table, and a confidence-banded chart for the target variable"><figcaption><p>A completed Forecast. Each target gets its own chart with the projected trajectory and its confidence band; the summary table reports the net change over the horizon.</p></figcaption></figure>

Each chart plots the variable's history up to the forecast start, then the projected trajectory with its confidence band shaded around it. The band widens with the horizon, reflecting accumulating uncertainty. Per-chart controls surface the underlying reasoning:

* **Changepoints** — the points where the trajectory shifts direction or slope.
* **Why** — the causal drivers behind the projected movement.
* **Bounds** — toggle the confidence band on and off.

The **Forecast Summary** reports the net change for each target over the horizon, and the **Forecast Results Table** holds the underlying values for export. The whole run exports as PDF.

***

## Other Simulation Types

Forecast is the temporal analogue of [Prediction](/more-details/digital-twin/simulation-types/prediction); a temporal twin's menu offers time-aware versions of the other types too — see [Temporal Simulations](/more-details/digital-twin/temporal-simulations). The static types are:

* [Prediction](/more-details/digital-twin/simulation-types/prediction) — the most likely outcome for a specific input.
* [Intervention](/more-details/digital-twin/simulation-types/intervention) — change a variable and observe propagation.
* [Optimization](/more-details/digital-twin/simulation-types/optimization) — find the input combination that best meets a goal.
* [Best Action](/more-details/digital-twin/simulation-types/best-action) — the minimum change needed to reach a target.
* [Explanation](/more-details/digital-twin/simulation-types/explanation) — the drivers and impacts behind an outcome.

See [Simulation Types](/more-details/digital-twin/simulation-types) for the full picture and [Step 6: Run Simulations](/user-guide/simulations) for the general overview.


# RootCause Assistant (BETA)

The RootCause Assistant lets you interact with your data, Digital Twins, and analyses through natural language. Ask questions, run simulations, and explore causal relationships — all through conversation.

Unlike typical AI chat tools, the Assistant doesn't try to reason about your data directly. It orchestrates RootCause's analytical engines — causal discovery, counterfactual simulation, data queries — and reports what those engines compute. The AI handles the conversation; the math comes from purpose-built algorithms.

<figure><img src="/files/NOtObeZqKaVfPo6atQcr" alt="Four-stage diagram showing how RootCause Assistant works: You Ask, Assistant Orchestrates, Engines Compute, Result plus Evidence"><figcaption><p>The Assistant is an orchestration layer. Your question triggers precise tool calls to causal engines — the numbers come from the math, not from AI pattern-matching.</p></figcaption></figure>

***

### Accessing the Assistant

Click the chat button in the platform toolbar, or press `⌘⇧J`. The Assistant panel docks on the right side of the screen and is available throughout the platform — whether you are viewing a Data View, exploring a Digital Twin, or writing a report. It adapts to your current context: on a Digital Twin page it can run simulations directly; on a Report page it can help add content. The panel opens with suggested prompts drawn from the workspace, and its controls include **New chat** to start over and **Full screen** to expand the conversation.

***

### What you can do

**Ask questions about your data**

> "What's the average churn rate across all customers?" "Show me the distribution of customer tenure" "What columns are in the Sales dataset?"

The Assistant executes queries against your data and returns results as tables, charts, or summary statistics — each with an evidence reference you can verify.

**Run causal simulations**

> "What happens to churn if we offer free tech support?" "Find the optimal marketing spend to maximize conversions" "What's driving customer churn?" "What would it take to reduce churn by 20%?"

The Assistant calls the appropriate simulation type — prediction, intervention, optimization, best action, explanation, root cause analysis, anomaly scan, or forecast — runs it against your Digital Twin, and presents computed results with full traceability.

**Navigate the platform**

> "Open the Revenue Digital Twin" "Show me the customer 360 Data View" "Take me to last month's board report"

**Get help**

> "How do I upload a file?" "What's the difference between intervention and counterfactual?" "Explain what the causal graph is showing me"

<figure><img src="/files/Pc6Km5eO6U8VTEzOHQAk" alt="RootCause Assistant conversation answering What&#x27;s the average churn rate — 26.3%, from 1,313 churned out of 4,998 total customers — with a query results table attached as evidence"><figcaption><p>A data query in the Assistant: the average churn rate is 26.3% — 1,313 of 4,998 customers churned — with the query results table attached as clickable evidence.</p></figcaption></figure>

***

### Evidence and traceability

Every result from the Assistant carries an evidence reference. Click it to see the query or computation that produced the result, the source data used, the Digital Twin version, and the simulation parameters.

**Example:**

> **You:** What's the predicted impact of a 10% price increase on revenue?
>
> **Assistant:** Based on the Revenue Twin, a 10% price increase is predicted to reduce revenue by 4.2% (95% CI: 3.1%–5.3%). \[Evidence: SIM-2847]

For important decisions, click through to the evidence. Verify the query was correct, the data was appropriate, and the computation makes sense.

***

### Context mentions

Use `@` to reference specific objects in your workspace:

* `@Customer_360` — a Data View
* `@Revenue_Twin` — a Digital Twin
* `@Q4_Report` — a report

> "Run an intervention on @Revenue\_Twin to see what happens if we increase marketing spend by 20%"

Context mentions eliminate ambiguity about which object to use for a query or simulation.

***

### Rich responses

The Assistant returns structured results, not just text: data previews, charts, KPI cards, causal graphs, simulation results, and tables. Each includes an evidence link back to the underlying data or computation.

***

### Session context

Within a session, the Assistant remembers what you have discussed — follow-up questions can reference earlier results without repeating yourself. Conversation history is also preserved across sessions: the Assistant can search your past conversations in the workspace and retrieve their details, so you can pick up where an earlier session left off.

***

### Tips

* **Be specific** — "What's the average revenue per customer in Q4 from @Sales\_Data?" gets a better result than "Tell me about revenue"
* **Use `@` mentions** — reference specific objects to avoid ambiguity
* **Ask one thing at a time** — break complex requests into steps
* **Check the evidence** — for decisions that matter, click through and verify

***

> **BETA:** The RootCause Assistant is in active development. Capabilities are expanding and some responses may require verification.


# Applications

Applications are how analytical work leaves the workshop. The rest of the platform is where you build and validate models; **Applications** is where you package them into something an audience can consume: dashboards for humans, endpoints for other systems, scheduled automations, and AI assistants. Applications run on the workspace's data, Data Views, and Digital Twins, and their audience never needs to understand the models underneath.

Open **Applications** in the workspace's top navigation bar. The list shows every application with its type, owner, status, and last update. Click **New application** to start the builder.

<figure><img src="/files/wqRwX2WqcAV7avVFWSZZ" alt="The Applications page of a workspace with an empty list reading No applications yet — build one from your data — and a New application button"><figcaption><p>The Applications list. <strong>New application</strong> opens the builder.</p></figcaption></figure>

***

## Application types

The first step of the builder asks what kind of application you are creating. The core flow underneath is the same; only the wrapper changes, and you can change everything later.

| Type                       | What it is                                                                                                                                                                      | Examples                                                                                        |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| **Dashboard Application**  | Curated answers for humans to read. Compose tiles, charts, and tables on a layout people can open, share, and explore, powered by a live data flow underneath.                  | Operations health for the on-call team; a weekly revenue snapshot                               |
| **API Application**        | A programmable endpoint other systems can call. Define a request, run a flow, return a typed response; other services, scripts, and AI tools can hit it like any REST endpoint. | Score a transaction for fraud risk; resolve a customer ID to a profile bundle                   |
| **Automation Application** | A scheduled or event-driven flow. Run on a cron, webhook, or event, and land outputs in datasets, datastores, or downstream systems. No UI required.                            | Nightly data quality check; hourly model retrain pipeline                                       |
| **AI Application**         | An LLM-driven app with scoped tools. Define a goal, a scope, and a toolbelt; the AI reasons over your data, calls only the tools you allow, and produces structured answers.    | A customer-support copilot scoped to one team; an investigation agent that queries the ontology |

<figure><img src="/files/CIUC06wLZaEVoQoUxBbx" alt="Step 1 of the application builder, What kind of application?, showing the four type cards — Dashboard, API, Automation, and AI Application — each with a description and example uses"><figcaption><p>The builder's first step: pick the surface your audience will consume. Each card lists example uses of that type.</p></figcaption></figure>

{% hint style="info" %}
An **API Application** is an endpoint you build on your workspace's data. It is distinct from the platform's own REST API (see [API Access](/api-and-integrations/api-access)) and from [OAuth Apps](/api-and-integrations/api-access/oauth-apps), which are third-party clients that authenticate against RootCause.
{% endhint %}

{% hint style="warning" %}
The **AI Application** type is the newest of the four and still maturing: its preview chat and toolbelt are being wired up. Expect it to evolve faster than the other three.
{% endhint %}

***

## Creating an application

The builder walks through four steps: **Type**, **Start**, **Configure**, and **Launch**.

1. **What kind of application?** Pick one of the four types above.
2. **How do you want to start?** Three paths:
   * **Blank canvas** — open an empty editor and build from scratch.
   * **Start from a prompt** — describe what you want and let AI scaffold the flow.
   * **Pick a template** — start from a curated example for the chosen type.
3. **Configure basics** — a short, recognizable name, a one-line description ("what it does and who it's for"), and optional tags.
4. **Review & launch** — a recap of exactly what will be created. Click **Create application**.

<figure><img src="/files/wQhp11bmbfOUJng3p3Bh" alt="Steps 2 and 3 of the application builder: How do you want to start? with Blank canvas, Start from a prompt, and Pick a template cards, above Configure basics with Name, Description, and Tags fields"><figcaption><p>The start path and the basics: a blank canvas, an AI-scaffolded flow, or a template, then a name and one-line description.</p></figcaption></figure>

Creating the application makes a **draft** and opens it in the editor.

***

## The editor and the flow

Every application is powered by a **flow**: a graph of modules (data sources, transforms, simulations, outputs) wired together on a canvas. The editor's tabs depend on the type:

| Type       | Editor tabs                                                                              |
| ---------- | ---------------------------------------------------------------------------------------- |
| Dashboard  | **Preview** (what viewers see) and **Build** (the flow of modules and wiring underneath) |
| API        | **Flow** and **Test** (an API app gets pinned request-in and response-out modules)       |
| Automation | **Trigger** and **Flow**                                                                 |
| AI         | **Scope**, **Tools**, and **Preview**                                                    |

Automations are started by a **trigger**, configured on the Trigger tab: run manually, on a **schedule** (cron expression plus timezone), from a **webhook** (a secret URL you can rotate), or on a platform **event** (a topic plus filters, e.g. on new uploads).

***

## Application lifecycle

The Status column on the Applications list tracks the lifecycle: **Draft** (still being built), **Published** (live and consumable), or **Archived** (retired).

Publishing is a separate act from creating. Click **Publish** in the editor; a short wizard walks through **Version**, **Access**, **Surfaces**, and **Review**:

* Each publish **snapshots an immutable version** with a version number, so later edits to the draft never disturb what consumers are using. Published versions can be listed, archived, and reactivated, and an application can be unpublished back to draft.
* The platform validates before publishing: a dashboard needs at least one widget bound to a data source, an API app needs its request and response modules, an automation needs a valid trigger.
* **Surfaces** are derived from the type: a dashboard publishes to the UI, an API app to REST, and schedule or webhook triggers add their own surface.

Where a published application runs:

* **Dashboards** with public access get a shareable URL at `/p/<slug>` (with an embeddable variant), branded with the organization's logo — the "public apps" the [organization branding settings](/more-details/organisation-administration#organisation-details) refer to.
* **API applications** are callable at `POST /api/v1/apps/<slug>`, authenticated with per-app API keys issued from the publish panel.
* **Automations** run on their schedule, or on calls to their webhook URL. Event triggers only fire for published applications.

***

## Applications and the rest of the workspace

Applications are first-class actors in the workspace:

* Simulations run by an application appear in the twin's simulation history; the **Ran by** filter separates runs by **People** from runs by **Apps**.
* The organization's roles carry a dedicated **Applications** permission area that controls who can build and manage applications. See [Organisation Administration](/more-details/organisation-administration).
* An application's lineage is visible from the data side: a Data View's lineage bar traces through the Digital Twin to the reports and apps built on it.


# Organisation Administration

The **Organisation settings** page manages everything about the organization itself: its identity, its roles and their permissions, its members, and how new people join. Open it from the Organization home under Manage, or from the account menu in the top-right corner.

For the container model (organizations and workspaces), see [Setup Org and Workspace](/start-here/navigation).

***

## Organisation Details

The organization's basic identity. Click **Edit Details** to change the name.

Two brand assets can be uploaded (SVG, PNG, JPEG, or WEBP):

* **Logo** — the full wordmark, displayed in the header of public apps. Cropped to a wide 3:1 frame; SVGs are kept as-is.
* **Icon** — a square mark used where a full logo doesn't fit. Cropped to a 1:1 frame.

Use **Replace** or **Remove** on each, or drag and drop an image file.

<figure><img src="/files/VbanISDo7B8Tr3USSfGy" alt="The Organisation settings page with the Organisation Details section: the organisation name Acme Corp, the uploaded logo wordmark and square icon each with Replace and Remove buttons, and the Organisation Roles section starting below"><figcaption><p>Organisation Details: the name, the wide logo, and the square icon, each replaceable in place.</p></figcaption></figure>

***

## Organisation Roles

The **Organisation Roles** section lists every role with the permissions it grants. Three default roles ship with the organization:

| Role      | Intent                                                                                                                        |
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Owner** | Full control of everything, including invites, settings, and billing                                                          |
| **Admin** | Full control of data, workspaces, connectors, applications, and reports; write-level access to invites, settings, and billing |
| **User**  | No standing permissions; grant access per workspace or with a custom role                                                     |

Permissions are grouped by area: **Data**, **Workspaces**, **Connectors**, **Applications**, **Organisation Invites**, **Organisation Settings**, **Organisation Billing**, and **Reports**. Each area is granted at one of four levels:

| Level     | What it allows                                                          |
| --------- | ----------------------------------------------------------------------- |
| **none**  | No access to the area                                                   |
| **read**  | View only: no modification and no executing things                      |
| **write** | Create, view, and update: upload and build, but not delete others' work |
| **full**  | Everything, including deletion                                          |

<figure><img src="/files/bGLK4Z9XyiPG9LhD0sap" alt="The Organisation Roles section listing the three default roles — Admin, Owner, and User — each with its per-area permission levels shown as coloured pills, and a Create Role button"><figcaption><p>The three default roles and their per-area levels. <strong>Create Role</strong> defines a custom one.</p></figcaption></figure>

Click **Create Role** to define a custom role when the defaults don't fit, for example a role that can manage data and connectors but never touch workspaces or billing.

***

## Workspace access

Organization roles set a member's baseline. Access to a specific workspace is granted on the workspace itself:

* **Share a workspace** from the workspaces list (or the Organization home) via its **Share** action. Add individual users or whole roles at **read**, **write**, or **full** access, exactly like sharing a report.
* Sharing with someone who is not yet in the organization sends them an **invite** as part of the share (this requires invite permission).
* A member who opens a workspace they have no access to sees a **request access** screen; the workspace owner approves or rejects the request.

<figure><img src="/files/mEds2SQVDJJ2DOildC3K" alt="The Share Customer Analytics dialog: an Add people or roles section with User and Role tabs, a Choose user dropdown, Read, Write, and Full access pills, and a People with access list showing the workspace owner"><figcaption><p>Sharing a workspace: add users or whole roles at Read, Write, or Full access. The owner is always listed.</p></figcaption></figure>

This is how a member with the default **User** role (no standing permissions) gets to work: share the workspaces they need with them, at the level they need.

***

## Team Members

The **Team Members** section lists everyone in the organization with their role. Click **Invite User** to send an invitation and assign the new member's role.

**Domain-based joining** can be enabled below the member list: it allows users with matching email domains to automatically join your organization without an individual invite. It is disabled by default.

<figure><img src="/files/FTCfpv18nK9R3AtmMV1P" alt="The Team Members section listing one member with the Owner role and an Invite User button, above the Domain-based joining toggle (disabled) and the top of the Danger Zone"><figcaption><p>Team Members with the Invite User action, and Domain-based joining below it.</p></figcaption></figure>

***

## Danger Zone

**Delete Organisation** permanently deletes the organization and everything in it: all workspaces, datasets, reports, roles, and invitations. This cannot be undone, and it is only available in multi-tenant deployments.


# API Access

The RootCause REST API lets you programmatically manage workspaces, datasets, ontology, Digital Twins, simulations, and reports. The **API** page is the hub for all programmatic access. It is where you create and manage API keys, explore the API reference, connect MCP clients, and register OAuth apps.

To open it, go to the Organization home and click the **API** card under Manage.

<figure><img src="/files/FXP82TCkNrHPBqOjhO8T" alt="The Organization home with the API card highlighted under the Manage section"><figcaption><p>The API page lives on the Organization home, under Manage.</p></figcaption></figure>

The page is organized into six sections:

| Section             | Purpose                                                                                                                                 |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Getting Started** | Authentication, code examples, and links to the full API reference                                                                      |
| **MCP Integration** | Connect Claude Code, Claude Desktop, Cursor, or any MCP client. See [MCP Integration](/api-and-integrations/api-access/mcp-integration) |
| **Connected Apps**  | Assistants and apps you have authorized to reach the organisation — revoke any of them here                                             |
| **OAuth Apps**      | Register confidential OAuth clients for third-party apps. See [OAuth Apps](/api-and-integrations/api-access/oauth-apps)                 |
| **Create API Key**  | Generate a new key with fine-grained permission scopes and optional expiry                                                              |
| **Manage Keys**     | View, copy, and revoke your existing API keys                                                                                           |

***

## Authentication

All API endpoints live under `/api/v1/` on your platform domain. Every request requires a **Bearer token** in the `Authorization` header:

```bash
curl -X GET "https://<your-platform-domain>/api/v1/workspaces" \
  -H "Authorization: Bearer pk_your_api_key_here" \
  -H "Content-Type: application/json"
```

The Getting Started section shows the same example in Python and JavaScript, with your platform's real URL filled in.

<figure><img src="/files/dHFKfScMGb8p2RL0s0xm" alt="The API page with the Getting Started section expanded: the authentication cURL example with Python and JavaScript tabs, and Resources links to the Interactive API Reference and the OpenAPI Specification, above the collapsed MCP Integration, Connected Apps, OAuth Apps, Create API Key, and Manage Keys sections"><figcaption><p>The API page opens on Getting Started: the authentication example in cURL, Python, or JavaScript, with the API reference links below and the other sections stacked underneath.</p></figcaption></figure>

***

## API reference

Two resources are linked from the Getting Started section:

* **Interactive API Reference** (`/api/v1/docs`) explores every endpoint, lets you try requests against your data, and shows request and response schemas.
* **OpenAPI Specification** (`/api/v1/openapi.json`) is the OpenAPI 3.1 spec, which you can feed to a code generator to produce a typed client in your language of choice.

***

## Creating an API key

Open the **Create API Key** section and fill in:

* **Key name** — a label you will recognize later, such as "Production MCP" or "CI Pipeline".
* **Workspace scope** — either **Org-wide** (the key can list and access all workspaces) or a single workspace. Prefer workspace-scoped keys for integrations that only need one project.
* **Permission scopes** — the individual permissions the key carries, grouped by area. Select only what the integration needs; **Select all** exists but should be the exception.

  | Scope area    | Grants                                                | Actions                      |
  | ------------- | ----------------------------------------------------- | ---------------------------- |
  | Sources       | Access and manage uploaded data sources               | read, write, delete          |
  | Datasets      | Read and modify datasets derived from your sources    | read, write, delete          |
  | Ontology      | Browse and edit concepts, relationships, and metadata | read, write, delete          |
  | Digital Twins | Manage causal models and run structural learning      | read, write, delete, execute |
  | Simulations   | View and run what-if simulations on digital twins     | read, execute                |
  | Connectors    | Configure and manage external data connectors         | read, write                  |
  | Catalog       | Browse the workspace data catalog                     | read                         |
  | Jobs          | Monitor background jobs and pipeline runs             | read                         |
  | Exports       | Download generated reports and data exports           | read                         |
  | Agent         | Interact with the AI assistant and MCP tools          | read, write                  |
  | Reports       | Create and view analysis reports                      | read, write                  |

  There is no separate Workspaces scope: listing workspaces is covered by the Sources **read** scope.
* **Expiry** *(optional)* — an end date after which the key stops working. Set one for keys used in CI/CD or temporary scripts.
* **IP allowlist** *(optional)* — a comma-separated list of IPs allowed to use the key. Leave empty to allow all.

<figure><img src="/files/eiNQMPRZhENkmi2obOEa" alt="The Create API Key section with the key name CI Pipeline, workspace scope Org-wide, and the permission scope groups — Sources, Datasets, Ontology, Digital Twins, Simulations, Connectors — with Digital Twins and Connectors ticked, reading 6/24 scopes selected"><figcaption><p>Creating a key: a recognisable name, a workspace scope, and only the permission scopes the integration needs — here 6 of the 24.</p></figcaption></figure>

Click **Create API key**. The new key is displayed after creation; copy it and store it somewhere safe.

***

## Managing keys

The **Manage Keys** section lists every key you have created, filterable by **Org-wide** or **Workspace** scope. From here you can view, copy, and revoke keys.

<figure><img src="/files/S4NFzPmepTLmBsCg07ju" alt="The Manage Keys section listing one key named CI Pipeline with digital-twins:all and connectors:all scopes, Org-wide scope, no expiry, and copy and delete actions, above a Keep your API keys safe callout"><figcaption><p>Manage Keys: every key with its scopes, expiry, last use, and the copy and revoke actions.</p></figcaption></figure>

{% hint style="warning" %}
**Keep your API keys safe.** Never share keys in public channels, repos, or client-side code. Use the narrowest scopes needed for each integration, set an expiry for temporary keys, and rotate keys regularly, deleting any that are no longer needed.
{% endhint %}


# MCP Integration

RootCause exposes its tools over the **Model Context Protocol (MCP)**, so AI clients like Claude Code, Claude Desktop, and Cursor can query your data, inspect ontology, and run simulations conversationally. Setup instructions with your platform's real URLs are on the **API** page, in the **MCP Integration** section (see [API Access](/api-and-integrations/api-access)).

There are two connection methods. The recommended path is a **remote OAuth connection**: clients register themselves automatically and you sign in through your browser. No API key to copy or leak. The client sees only the tools its scopes allow, and destructive or long-running actions ask for confirmation before they run; platform procedures — building a twin, composing a causal dataset — arrive as slash commands in clients that support prompts.

***

## OAuth connection (recommended)

With the OAuth method, the config contains no secrets. Authorization happens in your browser, tokens are stored by the client, and access is scoped to the organization or workspace you approve. Every client you authorize appears in the **Connected Apps** section of the API page, where you can revoke it at any time — revoking deletes the grant and kills its refresh tokens immediately, so the app has to sign in again.

<figure><img src="/files/eK5oa9EqmhqlNzVufDvP" alt="The MCP Integration section of the API page on the OAuth method with the Claude Code tab selected: three setup steps, a terminal command reading claude mcp add --transport http rootcause followed by the platform MCP URL, and a note that no secrets are stored"><figcaption><p>The MCP Integration section generates the setup for each client with your platform's real URL — here the one-command Claude Code path.</p></figcaption></figure>

### Claude Code

Claude Code is the quickest path: one command, no config file to edit, and it speaks HTTP to the server directly instead of running a local proxy.

1. Open a terminal and run:

   ```bash
   claude mcp add --transport http rootcause https://<your-platform-domain>/api/v1/mcp
   ```
2. Type `/mcp` in the chat panel and authenticate: a browser window opens to sign in and authorize.
3. Pick the organization or workspace to grant. The same `/mcp` dialog also enables, disables, and reconnects servers later.

### Cursor

1. Open **Cursor Settings → MCP**, or add to your project's `.cursor/mcp.json`.
2. Paste the config:

   ```json
   {
     "mcpServers": {
       "rootcause": {
         "url": "https://<your-platform-domain>/api/v1/mcp"
       }
     }
   }
   ```
3. Cursor prompts you to **authenticate**: a browser window opens to sign in and authorize.
4. Pick the organization or workspace to grant, and the RootCause tools appear in Agent mode.

### Claude Desktop

1. Open your Claude Desktop config file:
   * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
   * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
2. Paste the config. It uses `mcp-remote`, which bridges Claude to the remote server and runs the OAuth sign-in for you (this requires Node.js, since the bridge runs via `npx`):

   ```json
   {
     "mcpServers": {
       "rootcause": {
         "command": "npx",
         "args": ["mcp-remote", "https://<your-platform-domain>/api/v1/mcp"]
       }
     }
   }
   ```
3. Restart Claude Desktop. A browser window opens the first time to authorize.

***

## API key connection (legacy)

The legacy method runs the [`@rootcause/rootcause-mcp`](https://www.npmjs.com/package/@rootcause/rootcause-mcp) stdio bridge locally, authenticated by a static API key. On the API page, select one of your keys in the MCP Integration section and it generates the connection config for you.

Org-wide keys are recommended for this method, so the assistant can list and switch between workspaces; if the integration only ever needs one workspace, scope the key to it instead. See [API Access](/api-and-integrations/api-access) for creating keys.

Prefer the OAuth method for new setups: it avoids storing a long-lived secret in a config file.


# OAuth Apps

If you are building a third-party application that authenticates users against RootCause, register it as a **confidential OAuth client** on the **API** page, in the **OAuth Apps** section (see [API Access](/api-and-integrations/api-access)).

Each registered app receives a **client ID** and a **one-time client secret**. The secret is shown once at registration: store it securely, because it cannot be retrieved later.

{% hint style="info" %}
Public MCP clients (Claude Code, Claude Desktop, Cursor, and similar) register themselves automatically through the OAuth flow and are **not** listed here — the connections you have personally authorized appear in the **Connected Apps** section of the API page instead, where they can be revoked. This section is only for confidential clients you build and operate yourself.
{% endhint %}

***

## Registering an app

In **Register new app**, fill in:

* **App name** — the name users see on the consent screen, for example "Acme Analytics".
* **Redirect URIs** — one per line. These must match **exactly** at authorization time; a mismatch rejects the request.
* **Workspace lock** *(optional)* — pin the app to a single workspace. The default is org-wide, where the user picks the workspace at consent time.
* **Allowed scopes** — restrict which permission areas the app may request: Sources, Datasets, Ontology, Digital Twins, Simulations, Connectors, Catalog, Jobs, Exports, Agent, and Reports. Leave empty to allow all.

<figure><img src="/files/9QCtjMLQ24Ozl7vVhrgY" alt="The OAuth Apps section of the API page with the Register new app form filled in: app name Acme Analytics, one redirect URI, workspace lock set to org-wide, and the eleven allowed-scope pills, above a Register app button"><figcaption><p>Registering a confidential client: name, exact redirect URIs, an optional workspace lock, and the scopes the app may request.</p></figcaption></figure>

Click **Register app** to receive the client ID and secret.

***

## How access works

Your app sends users through the standard OAuth authorization flow against your platform domain. At consent, the user sees the app name and requested scopes, picks the workspace (unless the app is workspace-locked), and approves. Tokens issued to the app are limited to the approved scopes and workspace.

The API surface available to an OAuth app is the same REST API documented in the [Interactive API Reference](/api-and-integrations/api-access#api-reference).

***

## Endpoints and protocol details

The authorization server publishes its metadata at `/.well-known/oauth-authorization-server`, which is the authoritative source. The endpoints:

| Endpoint                    | Path                |
| --------------------------- | ------------------- |
| Authorization               | `/oauth/authorize`  |
| Token                       | `/oauth/token`      |
| Dynamic client registration | `/oauth/register`   |
| Revocation                  | `/oauth/revoke`     |
| Introspection               | `/oauth/introspect` |

Protocol facts your implementation needs:

* **Grant types:** `authorization_code`, `refresh_token`, and `client_credentials`. Client credentials is only available to confidential clients bound to an organization.
* **PKCE is mandatory** on every authorization-code exchange, confidential clients included, and only the `S256` challenge method is accepted.
* **Redirect URIs are matched by exact string equality.** No wildcards, no prefix matching.
* **Access tokens** are JWTs valid for **1 hour** (configurable per deployment). **Refresh tokens** last **30 days** and rotate on every use: each refresh invalidates the old token and issues a new one. A scope can be narrowed, never widened, at refresh time.
* **Client authentication** for confidential clients is `client_secret_basic` or `client_secret_post`.

Consent is remembered: once a user has approved an app for a given scope set, later authorizations with the same or narrower scopes auto-approve.


# PostgreSQL

Connect RootCause to your PostgreSQL database to import tables or run custom queries.

***

### Prerequisites

Before connecting, ensure you have:

* PostgreSQL database hostname or IP address
* Port number (default: 5432)
* Database name
* Schema name (default: public)
* Username and password with read access to the tables you want to import
* Network access from RootCause to your database (firewall rules, VPN, etc.)

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **PostgreSQL** and click **Setup**
3. Enter your connection details:

| Field      | Description                    | Example          |
| ---------- | ------------------------------ | ---------------- |
| Host       | Database server hostname or IP | `db.example.com` |
| Port       | PostgreSQL port                | `5432`           |
| Database   | Database name                  | `analytics`      |
| Schema     | Schema to connect to           | `public`         |
| Username   | Database user                  | `readonly_user`  |
| Password   | User password                  | `••••••••`       |
| Enable SSL | Use encrypted connection       | ✓ Recommended    |

4. Click **Test Connection** to verify your credentials
5. Click **Save** to create the connector

***

### Importing Data

Once your connector is saved, you can import data in two ways:

**Import a Table**

Select "Table" as the import type and enter the table name. RootCause will import all columns and rows from that table.

**Custom SQL Query**

Select "Custom Query" to write your own SQL. This is useful for:

* Joining multiple tables
* Filtering rows before import
* Selecting specific columns
* Aggregating data

Example:

```sql
SELECT 
  customer_id,
  order_date,
  total_amount
FROM orders
WHERE order_date >= '2024-01-01'
```

***

### What Happens When You Import

1. RootCause executes your query against the database
2. Results are stored securely in your workspace's data lake
3. Schema is automatically detected (column names, data types)
4. A preview is generated so you can verify the data

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the entire dataset is replaced with fresh data from the source.

***

### Security Recommendations

* Use a dedicated read-only database user for RootCause
* Enable SSL for encrypted connections
* Restrict the user's access to only the tables needed
* Use IP allowlisting if your database supports it

***

### Troubleshooting

**Connection timeout**

* Verify the hostname and port are correct
* Check that your firewall allows connections from RootCause
* Ensure the database is running and accepting connections

**Authentication failed**

* Verify username and password
* Check that the user has CONNECT permission on the database
* Ensure the user can access the specified schema

**Permission denied on table**

* Grant SELECT permission to the user on the required tables
* Verify the schema name is correct


# MySQL

Connect RootCause to your MySQL database to import tables or run custom queries.

***

### Prerequisites

Before connecting, ensure you have:

* MySQL database hostname or IP address
* Port number (default: 3306)
* Database name
* Username and password with read access to the tables you want to import
* Network access from RootCause to your database (firewall rules, VPN, etc.)

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **MySQL** and click **Setup**
3. Enter your connection details:

| Field      | Description                    | Example          |
| ---------- | ------------------------------ | ---------------- |
| Host       | Database server hostname or IP | `db.example.com` |
| Port       | MySQL port                     | `3306`           |
| Database   | Database name                  | `analytics`      |
| Username   | Database user                  | `readonly_user`  |
| Password   | User password                  | `••••••••`       |
| Enable SSL | Use encrypted connection       | ✓ Recommended    |

4. Click **Test Connection** to verify your credentials
5. Click **Save** to create the connector

***

### Importing Data

Once your connector is saved, you can import data in two ways:

**Import a Table**

Select "Table" as the import type and enter the table name. RootCause will import all columns and rows from that table.

**Custom SQL Query**

Select "Custom Query" to write your own SQL. This is useful for:

* Joining multiple tables
* Filtering rows before import
* Selecting specific columns
* Aggregating data

Example:

```sql
SELECT 
  customer_id,
  order_date,
  total_amount
FROM orders
WHERE order_date >= '2024-01-01'
```

***

### What Happens When You Import

1. RootCause executes your query against the database
2. Results are stored securely in your workspace's data lake
3. Schema is automatically detected (column names, data types)
4. A preview is generated so you can verify the data

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the entire dataset is replaced with fresh data from the source.

***

### Security Recommendations

* Use a dedicated read-only database user for RootCause
* Enable SSL for encrypted connections
* Restrict the user's access to only the tables needed
* Use IP allowlisting if your database supports it

***

### Troubleshooting

**Connection timeout**

* Verify the hostname and port are correct
* Check that your firewall allows connections from RootCause
* Ensure the database is running and accepting connections

**Authentication failed**

* Verify username and password
* Check that the user has the necessary privileges
* For MySQL 8+, ensure the user uses a compatible authentication method

**Permission denied on table**

* Grant SELECT permission to the user on the required tables
* Run: `GRANT SELECT ON database.table TO 'user'@'host';`


# MongoDB

Connect RootCause to your MongoDB database to import collections with optional query filters.

***

### Prerequisites

Before connecting, ensure you have:

* MongoDB connection string (including authentication if required)
* Network access from RootCause to your MongoDB instance
* Read access to the databases and collections you want to import

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **MongoDB** and click **Setup**
3. Enter your connection string:

| Field             | Description      | Example                                       |
| ----------------- | ---------------- | --------------------------------------------- |
| Connection String | Full MongoDB URI | `mongodb+srv://user:pass@cluster.mongodb.net` |

**Connection String Formats:**

* **Standard:** `mongodb://username:password@host:27017`
* **Atlas (SRV):** `mongodb+srv://username:password@cluster.mongodb.net`
* **Replica Set:** `mongodb://host1:27017,host2:27017/?replicaSet=mySet`

4. Click **Test Connection** to verify your credentials
5. Click **Save** to create the connector

***

### Importing Data

Once your connector is saved:

1. Click **Import Data** on the connector
2. Select a **Database** from the dropdown (RootCause will list available databases)
3. Select a **Collection** from the dropdown
4. Optionally, add a **Query Filter** to import only matching documents

**Query Filter Example:**

```json
{
  "status": "active",
  "createdAt": { "$gte": { "$date": "2024-01-01T00:00:00Z" } }
}
```

The query filter uses standard MongoDB query syntax.

**Import Options**

Under **Advanced Options**, you can control how documents are converted into a table:

| Option           | Default | Description                                                                 |
| ---------------- | ------- | --------------------------------------------------------------------------- |
| Flatten Depth    | `2`     | How many levels of nested objects are flattened into separate columns (1–5) |
| Stringify Arrays | On      | Convert arrays to JSON strings for tabular compatibility                    |

***

### What Happens When You Import

1. RootCause connects to your MongoDB instance
2. Documents from the selected collection are retrieved (with optional filter)
3. Nested documents are flattened into a tabular format (up to the configured flatten depth; arrays are stringified if enabled)
4. Schema is automatically detected from the document structure
5. Data is stored securely in your workspace's data lake

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the entire dataset is replaced with fresh data from the source.

***

### Security Recommendations

* Use a dedicated read-only user for RootCause
* Include authentication in your connection string
* Use TLS/SSL connections (append `?tls=true` if needed)
* For Atlas, use IP allowlisting to restrict access

***

### Troubleshooting

**Connection timeout**

* Verify the connection string is correct
* Check that your MongoDB instance is accessible from RootCause
* For Atlas, ensure the IP address is in your allowlist

**Authentication failed**

* Verify username and password in the connection string
* Ensure the user exists in the `admin` database or the target database
* Check authentication mechanism compatibility

**Database or collection not showing**

* Verify the user has `listDatabases` and `listCollections` permissions
* Check that the database/collection exists and contains documents


# Snowflake

Connect RootCause to your Snowflake data warehouse to import tables or run custom queries. This connector is currently in **Beta**.

***

### Prerequisites

Before connecting, ensure you have:

* Snowflake account identifier (e.g., `org-account` or `account.region`)
* Username with access to the data you want to import
* Authentication credentials (password or RSA key pair)
* Warehouse, database, and schema names
* Network access from RootCause to Snowflake

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **Snowflake** and click **Setup**
3. Enter your connection details:

| Field              | Description            | Example           |
| ------------------ | ---------------------- | ----------------- |
| Account Identifier | Your Snowflake account | `myorg-myaccount` |
| Username           | Snowflake user         | `ANALYTICS_USER`  |
| Role (Optional)    | Role to assume         | `ANALYST_ROLE`    |

4. Choose an authentication method (see below)
5. Click **Test Connection** to verify your credentials
6. Click **Save** to create the connector

***

### Authentication Methods

**Password Authentication**

Enter your Snowflake password directly. This is the simplest method but may not be suitable for all security policies.

**Key Pair Authentication** (Recommended)

RSA key pair authentication is more secure and often required by enterprise security policies.

1. Select "Key Pair Authentication"
2. Click **Generate New Keys** – RootCause will create an RSA key pair
3. Copy the **Public Key** displayed
4. Add the public key to your Snowflake user:

```sql
ALTER USER your_username SET RSA_PUBLIC_KEY='MIIBIjANBgkqh...';
```

The private key is securely stored by RootCause and never exposed.

***

### Importing Data

Once your connector is saved, configure your import:

| Field     | Description            | Example        |
| --------- | ---------------------- | -------------- |
| Database  | Snowflake database     | `ANALYTICS_DB` |
| Schema    | Schema within database | `PUBLIC`       |
| Warehouse | Compute warehouse      | `COMPUTE_WH`   |

Then choose an import method:

**Import a Table**

Select "Table" and enter the table name. RootCause will import all columns and rows.

**Custom SQL Query**

Select "Custom Query" to write your own SQL:

```sql
SELECT 
  customer_id,
  order_date,
  total_amount
FROM ORDERS
WHERE order_date >= '2024-01-01'
```

***

### What Happens When You Import

1. RootCause connects to Snowflake using your credentials
2. The specified warehouse is used to execute the query
3. Results are streamed and stored in your workspace's data lake
4. Schema is automatically detected (column names, data types)
5. A preview is generated for verification

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the entire dataset is replaced with fresh data from Snowflake.

***

### Security Recommendations

* Use key pair authentication for production environments
* Create a dedicated user and role for RootCause
* Grant only SELECT permissions on required objects
* Use a small warehouse size appropriate for your data volumes
* Consider using Snowflake's network policies if available

***

### Troubleshooting

**Connection failed**

* Verify the account identifier format (e.g., `org-account` not full URL)
* Check that the user exists and is not locked
* Ensure network connectivity to Snowflake

**Authentication error with key pair**

* Verify the public key was correctly added to the Snowflake user
* Ensure no extra whitespace in the key
* Check that the key hasn't been rotated or replaced

**Warehouse not found / suspended**

* Verify the warehouse name is correct
* Check that the user has USAGE permission on the warehouse
* Ensure the warehouse is not suspended (or has auto-resume enabled)

**Permission denied**

* Grant USAGE on the database and schema
* Grant SELECT on the required tables or views
* Verify the role has the necessary privileges


# Google Cloud Storage

Connect RootCause to Google Cloud Storage to import files from your GCS buckets. This connector is currently in **Beta**.

***

### Prerequisites

Before connecting, ensure you have:

* Google Cloud project ID
* A service account with read access to the buckets and objects you want to import
* The service account's JSON key file (or its private key PEM and email)

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **Google Cloud Storage** and click **Setup**
3. Enter your connection details:

| Field                     | Description                                                                         | Example                                   |
| ------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------- |
| Project ID                | Google Cloud project ID                                                             | `my-project-123`                          |
| Service Account Email     | Service account email address                                                       | `service@project.iam.gserviceaccount.com` |
| Private Key               | Private key (PEM) from the service account JSON — or paste the entire JSON key file | `-----BEGIN PRIVATE KEY-----...`          |
| Default Bucket (Optional) | Bucket to use when imports don't specify one                                        | `my-data-bucket`                          |

If you paste the entire JSON key file into **Private Key**, the service account email is read from it automatically.

4. Click **Test Connection** to verify your credentials
5. Click **Save** to create the connector

***

### Importing Data

Once your connector is saved:

1. Click **Import Data** on the connector
2. Select a **Bucket** (RootCause lists the buckets your service account can see, or uses the default bucket)
3. Enter the **Object Path** within the bucket:
   * Specific file: `data/sales.parquet`
   * Directory prefix: `data/2024/`
   * Full GCS URI: `gs://bucket/data/`
4. Enable **Recursive** to include files in subdirectories
5. Select **Formats** to import (Parquet, CSV, JSON)

**Supported File Formats:**

| Format  | Description                                             |
| ------- | ------------------------------------------------------- |
| Parquet | Columnar storage format, recommended for large datasets |
| CSV     | Comma-separated values                                  |
| JSON    | Newline-delimited JSON (`.jsonl`, `.ndjson`)            |

***

### What Happens When You Import

1. RootCause connects to your GCS bucket
2. Objects matching your path and format criteria are listed
3. Files are downloaded and parsed
4. Multiple files are combined into a single dataset
5. Schema is automatically detected from the file content
6. Data is stored in your workspace's data lake

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the GCS path is re-scanned and data is refreshed.

***

### Service Account Permissions

Create a dedicated service account for RootCause with minimum required permissions:

1. In the Google Cloud Console, go to **IAM & Admin** → **Service Accounts** → **Create Service Account**
2. Grant the **Storage Object Viewer** role (`roles/storage.objectViewer`) on the buckets you want to import from
3. If you don't set a default bucket, the connector lists buckets in the project — this additionally requires the `storage.buckets.list` permission at the project level
4. Create a key for the service account (**Keys** → **Add key** → **JSON**) and paste it into the connector

***

### Troubleshooting

**Access Denied / 403**

* Verify the service account has the Storage Object Viewer role on the bucket
* Check that the project ID matches the project that owns the service account
* Ensure the key hasn't been deleted or disabled

**Bucket not found**

* Verify the bucket name is spelled correctly
* Check that the bucket belongs to a project the service account can access

**No files found**

* Verify the object path prefix is correct
* Check that files exist in the specified location
* Ensure the selected formats match your file types

**Invalid credentials**

* Paste the entire service account JSON key file, or the private key PEM together with the service account email
* Check for missing line breaks or truncation in the pasted key


# REST API

Connect RootCause to any REST API to import data from external services.

***

### Prerequisites

Before connecting, ensure you have:

* API base URL — or better, a machine-readable spec URL (OpenAPI, Swagger, Google Discovery, OData, or CKAN)
* Authentication credentials (if required)
* Network access from RootCause to the API

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **REST API** and click **Setup**
3. Paste a URL into the **API URL** field and click **Parse**

You can paste an OpenAPI, Swagger, Google Discovery, OData, or CKAN URL — or any working data URL — and RootCause will figure out the base URL, authentication, endpoints, pagination, and where the records live. After parsing, review the detected **Base URL** and endpoint list.

If the API has no spec, click **No spec? Configure manually** and fill in:

| Field               | Description                                           | Example                   |
| ------------------- | ----------------------------------------------------- | ------------------------- |
| Base URL            | Base API endpoint                                     | `https://api.example.com` |
| Authentication Type | None, API Key, Bearer Token, Basic Auth, or OAuth 2.0 | `API Key`                 |

4. Configure authentication (see below)
5. Test an endpoint with real values to verify the connection
6. Click **Save** to create the connector

All requests are sent as `GET` — the connector reads data from your API and never writes to it.

***

### Authentication Methods

**None**

For public APIs that don't require authentication.

**API Key**

For APIs that authenticate via API key:

| Field            | Description              | Example                   |
| ---------------- | ------------------------ | ------------------------- |
| API Key Name     | Header or parameter name | `X-API-Key`, `api_key`    |
| API Key Location | Where to send the key    | Header or Query Parameter |
| API Key          | Your API key value       | `••••••••`                |

**Bearer Token**

For APIs using Bearer token authentication:

| Field        | Description              |
| ------------ | ------------------------ |
| Bearer Token | Your JWT or access token |

**Basic Auth**

For APIs using HTTP Basic Authentication:

| Field    | Description  |
| -------- | ------------ |
| Username | API username |
| Password | API password |

**OAuth 2.0**

For OAuth 2.0 APIs, paste an access token — it is sent as an `Authorization: Bearer` header. Automatic token refresh isn't supported yet, so long-lived tokens work best.

Credentials are encrypted and never leave the backend.

***

### Headers and Query Parameters

You can add default headers and query parameters that will be sent with every request:

**Headers**

Add custom HTTP headers:

```
Accept: application/json
X-Custom-Header: value
```

**Query Parameters**

Add default query string parameters:

```json
{
  "format": "json",
  "limit": "1000"
}
```

Import-specific parameters are merged on top of these defaults.

***

### Importing Data

Once your connector is saved:

1. Click **Import Data** on the connector
2. If a spec was parsed, pick an endpoint from the endpoint list and fill in its **Parameters** — otherwise enter the **Endpoint path** (appended to the base URL)
3. Add import-specific **Query parameters** (merged with defaults)
4. Configure **Pagination** and **Records location** (see below)
5. Click **Test & preview** to fetch a sample page and verify the records before importing

**Pagination**

RootCause follows the API's pagination automatically. When a spec is parsed, the pagination style and parameters are pre-filled. The available styles:

| Style          | How it works                                                             |
| -------------- | ------------------------------------------------------------------------ |
| Single request | One request, no paging (default)                                         |
| Page number    | Increments a page parameter (`page=1`, `page=2`, …)                      |
| Offset / limit | Increments an offset parameter by the page size                          |
| Cursor         | Reads the next cursor from a response field and passes it as a parameter |
| Link header    | Follows the `rel="next"` URL from the `Link` response header             |

Depending on the style, you configure the **Page param**, **Size param**, **Offset param**, or **Cursor param** and **Next cursor path**, plus a **Page size** and an optional **Max pages** cap. Fetching stops when a page comes back empty, when **Max pages** is reached, or at a built-in safety cap of 1,000 pages.

**Records location**

Responses are parsed (JSON, XML, or CSV) and flattened into a table. Use **Records location** to point at the array of records with a dotted path (e.g. `data.items`) — leave it blank to use the whole response. After **Test & preview**, the detected array paths in the actual response are offered as options.

For APIs that return an object of parallel arrays (e.g. `{"time": [...], "temp_max": [...]}`), enable the columnar toggle so the arrays are transposed into rows. RootCause also auto-detects this shape in most cases.

**Column renaming**

An optional response mapping renames columns after the records are flattened:

```json
{
  "userName": "customer_name",
  "createdAt": "signup_date"
}
```

Keys are column names from the flattened response; values are the new column names. This is a plain rename — to pull records out of a nested response, use **Records location** instead.

***

### What Happens When You Import

1. RootCause makes GET requests to the configured endpoint, following pagination
2. Each response is parsed (JSON, XML, or CSV)
3. Records are extracted at the configured records location; columnar responses are transposed into rows
4. Records are flattened into tabular format and any column renames are applied
5. Schema is automatically detected
6. Data is stored in your workspace's data lake

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can keep the dataset current in two ways:

**Full refresh** (default) — the endpoint is fetched again and the dataset is replaced:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

**Incremental append** — enable **Keep in sync (append new rows)** when configuring the import. Choose how often to sync (**Sync every** Hour, Day, Week, or Month) and, if the endpoint has a date/time parameter, a **Watermark param**. On each sync, RootCause passes the last sync time as the watermark parameter so only new records are fetched, and appends them to the dataset instead of replacing it.

***

### Common Use Cases

**Importing from a CRM**

```
Base URL: https://api.crm.com/v1
Endpoint path: /contacts
Auth: API Key (Header)
Query Params: { "status": "active" }
Pagination: Page number, page size 100
```

**Pulling from an open-data portal**

```
API URL: https://data.gov.uk (CKAN — parsed automatically)
Endpoint: datastore_search
Records location: result.records
```

**Pulling IoT sensor data**

```
Base URL: https://iot.platform.com/api
Endpoint path: /readings
Auth: Basic Auth
Query Params: { "sensor_ids": "1,2,3", "interval": "hourly" }
Sync: Keep in sync (append new rows), watermark on the "since" parameter
```

***

### Troubleshooting

**Connection failed / timeout**

* Verify the URL is correct and accessible
* Check firewall rules and network connectivity
* Ensure the API server is responding

**401 Unauthorized**

* Verify your authentication credentials
* Check that the API key or token hasn't expired
* Ensure you're using the correct authentication method

**Response not recognized**

* Verify the API returns JSON, XML, or CSV (HTML landing pages are rejected)
* Use **Test & preview** to inspect the raw response
* Point **Records location** at the array that holds your records

**Empty data**

* Verify your query parameters return results
* Check that you have access to the requested resources
* Use **Test & preview** to confirm records appear at the selected records location


# Amazon S3

Connect RootCause to Amazon S3 to import files from your S3 buckets.

***

### Prerequisites

Before connecting, ensure you have:

* AWS Access Key ID and Secret Access Key
* S3 bucket name
* AWS region where the bucket is located
* Read access to the bucket and objects you want to import

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **Amazon S3** and click **Setup**
3. Enter your connection details:

| Field                   | Description                               | Example                              |
| ----------------------- | ----------------------------------------- | ------------------------------------ |
| Access Key ID           | AWS access key                            | `AKIAIOSFODNN7EXAMPLE`               |
| Secret Access Key       | AWS secret key                            | `wJalrXUtnFEMI/K7MDENG/...`          |
| Bucket Name             | S3 bucket name                            | `my-data-bucket`                     |
| Region                  | AWS region                                | `us-east-1`                          |
| Endpoint URL (Optional) | Custom endpoint for S3-compatible storage | `https://s3.us-east-1.amazonaws.com` |

4. Click **Test Connection** to verify your credentials
5. Click **Save** to create the connector

***

### Importing Data

Once your connector is saved:

1. Click **Import Data** on the connector
2. Enter the **Path** to your files:
   * Specific file: `/data/sales.parquet`
   * Directory prefix: `/data/2024/`
   * Full S3 URI: `s3://bucket/data/`
3. Enable **Recursive** to include files in subdirectories
4. Select **Formats** to import (Parquet, CSV, JSON)

**Supported File Formats:**

| Format  | Description                                             |
| ------- | ------------------------------------------------------- |
| Parquet | Columnar storage format, recommended for large datasets |
| CSV     | Comma-separated values                                  |
| JSON    | JSON or newline-delimited JSON                          |

***

### What Happens When You Import

1. RootCause connects to your S3 bucket
2. Files matching your path and format criteria are listed
3. Files are downloaded and parsed
4. Multiple files are combined into a single dataset
5. Schema is automatically detected from the file content
6. Data is stored in your workspace's data lake

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the S3 path is re-scanned and data is refreshed.

***

### IAM Policy

Create an IAM policy with minimum required permissions:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    }
  ]
}
```

Attach this policy to a dedicated IAM user for RootCause.

***

### S3-Compatible Storage

The S3 connector also works with S3-compatible storage services:

* **MinIO** – Set Endpoint URL to your MinIO server
* **DigitalOcean Spaces** – Use Spaces endpoint (e.g., `https://nyc3.digitaloceanspaces.com`)
* **Backblaze B2** – Use B2 S3-compatible endpoint

Set the **Endpoint URL** to your storage provider's S3-compatible endpoint.

***

### Troubleshooting

**Access Denied**

* Verify the IAM user has `s3:GetObject` and `s3:ListBucket` permissions
* Check that the bucket policy doesn't explicitly deny access
* Ensure the bucket name and region are correct

**Bucket not found**

* Verify the bucket name is spelled correctly
* Check the region matches where the bucket was created

**No files found**

* Verify the path prefix is correct
* Check that files exist in the specified location
* Ensure the selected formats match your file types

**Connection timeout**

* Verify network connectivity to AWS
* Check that any firewall or VPC settings allow outbound HTTPS
* Try a different AWS region endpoint


# Azure Data Lake

Connect RootCause to Azure Data Lake Storage Gen2 to import files from your storage containers.

***

### Prerequisites

Before connecting, ensure you have:

* Azure Storage account with Data Lake Storage Gen2 enabled
* Container name within the storage account
* Authentication credentials (see options below)
* Read access to the container and blobs you want to import

***

### Setting Up the Connection

1. Navigate to **Sources** in your workspace and click **Import data**
2. In the Import Manager, find **Azure Data Lake** and click **Setup**
3. Enter your **Container Name**
4. Select an authentication method (see below)
5. Click **Test Connection** to verify your credentials
6. Click **Save** to create the connector

***

### Authentication Methods

**Connection String** (Simplest)

Copy the connection string from the Azure Portal:

1. Go to your Storage Account → **Access keys**
2. Copy the **Connection string**

| Field             | Description                              |
| ----------------- | ---------------------------------------- |
| Connection String | Full connection string from Azure Portal |

**Account Key**

Use storage account name and key:

| Field                      | Description                  | Example            |
| -------------------------- | ---------------------------- | ------------------ |
| Account Name               | Storage account name         | `mystorageaccount` |
| Account Key                | Access key from Azure Portal | `abc123...`        |
| Endpoint Suffix (Optional) | Custom endpoint              | `core.windows.net` |

**Service Principal (RBAC)** – Recommended for production

Use Azure AD service principal with role-based access:

| Field                      | Description                       |
| -------------------------- | --------------------------------- |
| Account Name               | Storage account name              |
| Tenant ID                  | Azure AD tenant ID (GUID)         |
| Client ID                  | App registration client ID (GUID) |
| Client Secret              | App registration client secret    |
| Endpoint Suffix (Optional) | Custom endpoint                   |

For Service Principal authentication, ensure the service principal has **Storage Blob Data Reader** or **Storage Blob Data Contributor** role assigned on the storage account in Azure Portal.

***

### Importing Data

Once your connector is saved:

1. Click **Import Data** on the connector
2. Enter the **Path** to your files:
   * Specific file: `data/sales.parquet`
   * Directory: `data/2024/`
3. Enable **Recursive** to include files in subdirectories
4. Select **Formats** to import (Parquet, CSV, JSON)

**Supported File Formats:**

| Format  | Description                                             |
| ------- | ------------------------------------------------------- |
| Parquet | Columnar storage format, recommended for large datasets |
| CSV     | Comma-separated values                                  |
| JSON    | JSON or newline-delimited JSON                          |

***

### What Happens When You Import

1. RootCause connects to your Azure Storage container
2. Files matching your path and format criteria are listed
3. Files are downloaded and parsed
4. Multiple files are combined into a single dataset
5. Schema is automatically detected from the file content
6. Data is stored in your workspace's data lake

The imported dataset becomes available for use in [Data Views](/user-guide/data-views) and [Ontology](/core-technologies/ontology) mapping.

***

### Live Data Sync

You can configure automatic syncing to keep your dataset current:

* **Manual** – Only sync when you click "Sync Now"
* **Hourly** – Refresh every hour
* **Daily** – Refresh once per day
* **Weekly** – Refresh once per week
* **Monthly** – Refresh once per month

When a sync runs, the container path is re-scanned and data is refreshed.

***

### Setting Up Service Principal

To create a service principal for RootCause:

1. **Create an App Registration** in Azure AD:
   * Go to Azure Active Directory → App registrations → New registration
   * Name it (e.g., "RootCause Integration")
   * Note the **Application (client) ID** and **Directory (tenant) ID**
2. **Create a Client Secret**:
   * Go to Certificates & secrets → New client secret
   * Copy the **Value** immediately (it won't be shown again)
3. **Assign Storage Role**:
   * Go to your Storage Account → Access control (IAM)
   * Add role assignment → **Storage Blob Data Reader**
   * Select your app registration as the member

***

### Troubleshooting

**Access Denied / AuthorizationPermissionMismatch**

* Verify authentication credentials are correct
* For Service Principal: ensure the app has Storage Blob Data Reader role
* Check that the container name is correct

**Container not found**

* Verify the container name is spelled correctly
* Ensure the storage account has Data Lake Gen2 enabled

**No files found**

* Verify the path prefix is correct
* Check that files exist in the specified location
* Ensure the selected formats match your file types

**Connection timeout**

* Verify network connectivity to Azure
* Check any firewall or virtual network settings
* Ensure the storage account allows access from your network


# Ontology

The ontology is the foundation of RootCause. It provides a structured map of your enterprise data, aligning columns to **entity**, **time**, and **location** concepts. By standardizing how data from different sources connects, it removes ambiguity and makes downstream causal analysis reliable and explainable.

***

### Definition & Purpose

An ontology is more than just a schema. It is a unified model of your data that organizes columns from many datasets into consistent, shared concepts.

Different datasets rarely use the same schema or naming conventions. RootCause scans every dataset and detects when columns in different datasets represent the same concept — for example, `customer_id` in a sales table and `cust_id` in a support table both mapping to a single shared Customer ID concept. Datasets that share an identifier concept can then be joined on the matching values of that concept. Joins operate on aligned values (exact matching by default, with tolerance options for numeric and time keys), so two datasets link when they record the same identifier scheme.

The purpose of the ontology is to create a shared foundation across disparate systems so RootCause can reason about cause and effect in a consistent way.

***

### How Data Links Together (Entity / Time / Location)

RootCause aligns columns to common anchors:

* Entity: Identifier concepts detected across datasets (e.g. Customer ID, Product SKU, Order Number) serve as join keys that link records referring to the same real-world object.
* Time: Temporal columns (timestamps, dates, periods) are classified as Time concepts so events can be ordered and aligned for time-series analysis.
* Location: Geographic columns (e.g. city, region, postal code) are classified as Location concepts, enabling location-based grouping and filtering.

By mapping columns into shared concepts, RootCause brings heterogeneous datasets into one coherent representation. Related concepts can also be organized into ontology groups — comparable measurements that share a unit, categorical variants of the same field, or replicas of the same source column — so they are treated consistently in analysis.

***

### Editing & Oversight

Ontologies aren't static. RootCause gives you tools to:

* Review and adjust concept mappings and classifications.
* Validate detected joins to catch errors or ambiguities early.
* Apply relationship rules — value constraints attached to concepts, sourced from domain knowledge, statistical detection, schema structure, user input, or calendar logic — so business-critical relationships stay correct.

This layer of oversight ensures data quality before it flows into causal graphs or simulations. For a hands-on walkthrough, see [Build Ontology](/user-guide/ontology-concepts).

***

### Data Views

RootCause generates Data Views — combined tables that reflect the joins across entities, times, and locations. A view that consolidates everything known about one identifier concept is called a 360 Table (e.g. a Customer 360 Table).

* Each view consolidates records into a single table that can be exported as CSV, JSON, or Parquet.
* Views are resolved dynamically from the ontology at query time — they are definitions, not materialized pipelines.

These Data Views form the structured inputs for causal analysis and Digital Twin simulations.


# Causal Discovery

Causal Discovery finds the inbound causes and outbound effects behind core concepts across your data. It builds a causal graph from unified Data Views generated by the ontology, combining domain rules with statistical evidence. The result is a directed acyclic graph (DAG) — or, where some directions remain ambiguous, a CPDAG (completed partially directed acyclic graph). This graph is then explored, adjusted, and validated before serving as the foundation for simulations in the Digital Twin.

Put simply, RootCause automatically builds a chart of what things impact others. This is the basis for running detailed and fully explainable simulations.

To begin, open **Digital Twins**, click **New Digital Twin**, pick your Data View, and run **Discover & train** — discovery runs as part of building the twin. See [Causal Graph](/user-guide/causal-graph).

***

#### Definition & Purpose

Causal Discovery goes beyond correlation. It identifies which factors truly cause outcomes to change, helping you:

* Prioritize interventions on drivers that move the needle
* Filter out noise and redundant relationships
* Keep results explainable and auditable for business and technical users

***

#### How Causal Discovery Works

The default discovery pipeline is a staged filtering cascade:

1. Screening – A cascade of fast statistical filters (distance correlation and partial distance correlation, executed in native C++ and Rust kernels) eliminates variable pairs with no meaningful dependence, so expensive tests only run on plausible candidates. Domain rules like "time moves forward" constrain the search from the start.
2. Independence testing – Surviving pairs go through kernel conditional-independence tests to prune links that are explained away by other variables.
3. Edge classification – A machine-learning classifier scores the remaining candidate edges, confirming the skeleton and proposing directions from the statistical evidence.
4. Direction resolution – Where statistics alone cannot settle a direction, an LLM stage proposes an orientation based on variable names and domain semantics. Every edge in the result records its direction provenance — `llm`, `ml`, `forced`, `constraint`, or `compelled` — so you can always see why an edge points the way it does.
5. DAG assembly – User constraints (known and blocked edges), temporal ordering, and the accumulated evidence are combined into an acyclic graph. Edges whose direction remains genuinely ambiguous stay bidirectional, and the result is flagged as a CPDAG (completed partially directed acyclic graph) rather than a fully directed DAG.

An alternative evolutionary-search algorithm, CausalACO (ant-colony optimization), can be selected instead of the default pipeline. For time-series data, the pipeline can automatically discover lag structure between variables, and an optional equation-discovery step can fit symbolic equations for deterministic relationships.

***

#### Editing & Oversight

Causal graphs aren't static. RootCause provides controls to incorporate domain knowledge:

* Edit assumptions: Add dependencies or break them to test scenarios
* Known relationships: Declare edges that must exist
* Blocked relationships: Forbid edges that should never exist

Edits are saved as a new version of the model, preserving the original as history. When you are satisfied with the graph, retrain the model to apply the changes — this ensures the causal model reflects both statistical evidence and expert judgment. See [Causal Graph](/user-guide/causal-graph) for how to explore and edit the graph in the UI.

***

#### Outputs & Views

When discovery is complete, the causal graph can be explored and evaluated:

**Explore**

* Flow Chart or DAG View for interactive navigation
* Path Analysis: Sankey diagrams showing incoming and outgoing causal paths with contribution weights
* Model Probabilities: Learned distributions or parameters for each node

**Evaluate**

* Graph- and node-level metrics
* Categorical targets: Accuracy, AUC
* Numeric targets: MSE, MAE, R², log-likelihood
* Highlights strong and weak areas to guide refinement (e.g. adding priors, blocking edges)


# Digital Twin & Simulations

Once a causal graph has been discovered and validated, RootCause creates a Digital Twin: a live, data-driven model of your system. The twin acts as a sandbox where interventions, counterfactuals, and optimizations can be tested out, and their impacts evaluated, before being applied in real life.

***

#### Definition & Purpose

The Digital Twin is the execution layer of RootCause. It translates causal structure into decision support by:

* Simulating the effects of interventions in a controlled environment
* Providing explainable reasoning behind KPI changes
* Balancing trade-offs across multiple outcomes

This makes it possible to move beyond descriptive analytics and into prescriptive, causally sound decision-making.

***

#### How It Works

1. Baseline World – The twin samples outcomes from the learned causal model.
2. Intervention – One or more variables are modified (hard values, relative changes, or segment-specific).
3. Propagation – Effects flow through the causal graph, updating downstream nodes according to their dependencies.
4. Simulation Runs – Monte Carlo sampling produces distributions of possible futures.
5. Comparison – Baseline and intervention scenarios are compared, with uncertainty intervals provided.

***

#### Advanced Capabilities

* Bayesian Foundations – The twin runs on a causal Bayesian network whose conditional distributions are learned with Bayesian additive regression tree (BART) ensembles and sampled via Monte Carlo. In temporal causal discovery, Gaussian-process decomposition separates trend and seasonal structure before dependencies are tested.
* Ontology Integration – Variable dependencies are inferred from the ontology, ensuring simulations respect real-world structure.
* Scalability – A staged filter cascade prunes the pairwise search space before expensive independence tests run, keeping discovery tractable on high-dimensional datasets.
* Segment Analysis – Simulations can run across sub-populations (regions, customer cohorts, product lines) to uncover heterogeneous effects.
* Optimization – The system can recommend levers that maximize or minimize a target while accounting for secondary impacts.
* Natural Language Interface – Simulations can be configured via structured UI or plain-language queries.

***

#### Deployment & Performance

* Enterprise-Ready – Runs self-hosted for sensitive environments, with optional cloud execution for evaluation.
* Built for Volume – Memory requirements are estimated up front before discovery starts, panel data is sharded across entities, and the heavy computation runs in native Rust and C++ kernels, including tiled distance-correlation computation for wide datasets.
* Efficiency – Designed to operate in high-dimensional feature spaces where traditional causal inference becomes infeasible.

***

#### Types of Simulations

* Predictions – Estimate the outcome of a specified input, with uncertainty.
* Interventions – Test the effect of changing a driver variable.
* Optimizations – Automatically search for the best intervention to reach a desired outcome.
* Best Action – Find the minimal change that reaches a target outcome.
* Explanations – Identify which drivers most influenced a KPI shift.
* Root Cause Analysis & Anomaly Scan – Diagnose why a value came out anomalous.

See [Simulation Types](/more-details/digital-twin/simulation-types) for a practical guide to each simulation.


# Handling Combinatorial Explosion

Causal inference often fails at scale because the number of possible graphs grows combinatorially with the number of variables. Traditional independence tests and search strategies quickly become intractable on real-world, high-dimensional datasets. RootCause is designed to overcome this bottleneck, making causal discovery practical on data sizes that are out of reach for academic or off-the-shelf tools.

***

#### Definition & Purpose

Combinatorial explosion occurs when the search space of possible causal structures grows faster than algorithms can handle. The number of variable pairs grows quadratically — 10 variables give 90 possible directed edges, 50 variables give 2,450 — but the real explosion is in graph structures: the number of possible DAGs grows super-exponentially with variable count, so exhaustive search is hopeless beyond a handful of variables.

RootCause addresses this directly, enabling:

* Causal discovery on hundreds of variables and millions of rows
* Practical execution times on enterprise-scale data
* Use of causal methods in enterprise contexts where data is large, messy, and siloed

***

#### How It Works

RootCause combines multiple strategies to keep causal discovery tractable:

1. Ontology Constraints – The search space is restricted by anchoring to entities, times, and locations. This ensures independence tests are applied only where relationships are plausible.
2. Filter Cascade – A staged cascade of pruning filters, executed in native C++ and Rust kernels, eliminates the vast majority of variable pairs early with cheap statistics, so expensive kernel conditional-independence tests only run on the survivors.
3. Fast Per-Pair Statistics – Distance correlation for each variable pair is computed in O(n log n) in the number of rows using Fenwick-tree kernels (instead of the naive O(n²)), and wide datasets are processed in tiles. This makes each individual test cheap; the cascade above is what keeps the number of tests manageable.
4. Learned Shortcuts – A machine-learning edge classifier scores surviving candidates instead of exhaustively enumerating structures; an alternative evolutionary search (CausalACO, ant-colony optimization) is available for focusing on promising graph regions.

***

#### Oversight & Reliability

Even with optimization, large-scale causal discovery must remain reliable. RootCause:

* Prunes spurious edges through successive statistical and conditional-independence filters
* Surfaces uncertain edges for human review before simulations — ambiguous directions remain bidirectional and the graph is flagged as a CPDAG (completed partially directed acyclic graph)
* Records a per-edge trace of the pipeline: which filter stage eliminated a pair, or how a surviving edge earned its direction

This combination balances speed with scientific rigor.

***

#### Outcomes & Performance

* Scalability – Memory needs are estimated before discovery starts, so a run that would blow past the budget is caught up front rather than mid-search.
* Enterprise Scale – Designed for domains like finance, healthcare, logistics, and telecom where datasets are wide, deep, and heterogeneous.
* Practical Timelines – Models that would be infeasible with standard conditional-independence testing become tractable through the cascade's aggressive early pruning.

***

#### Why It Matters

Without addressing combinatorial explosion, causal inference remains an academic exercise. By solving this problem, RootCause makes it possible to:

* Apply causal discovery to real-world, enterprise-scale datasets
* Generate results fast enough to guide operational decisions
* Build a reliable foundation for simulations and digital twins


# Addressing Domain Expertise

Most causal inference projects stall because they depend heavily on scarce human expertise. RootCause is designed to work in spite of limited expertise, while still letting experts shape and refine the model where it matters.

***

#### Definition & Purpose

Domain expertise is essential to make causal models meaningful, but most organizations can't encode all their knowledge upfront. RootCause addresses this gap by:

* Embedding domain-aware rules directly into the modeling process
* Allowing experts to refine results without acting as a bottleneck
* Keeping outputs explainable and auditable so both technical and business users can trust them

***

#### How It Works

1. Automatic Domain Constraints – Ontology anchors (entity, time, location) and temporal rules ensure only plausible relationships are tested.
2. Built-In Domain Semantics – Where statistical evidence alone cannot settle an edge's direction, an LLM stage proposes an orientation from variable names and real-world semantics, supplying a baseline of domain reasoning even when no expert is available. Each such decision is recorded on the edge itself.
3. Expert Input – Users can declare relationships as *Known* (must exist) or *Blocked* (forbidden). Dependencies can also be added or broken to reflect context.
4. Versioned Refinement – Expert edits are saved as a new version of the model, preserving history; retraining the model applies them, producing an updated causal model that integrates both data evidence and human knowledge.

***

#### Oversight & Flexibility

* Surfaces uncertain or ambiguous edges for review
* Supports relationship rules on ontology concepts — constraints an expert states directly, or accepts from statistical detection and schema structure
* Records per-edge direction provenance — whether an edge's orientation came from the ML classifier, the LLM stage, a user constraint, or was compelled by graph structure

***

#### Outcomes

* Resilient Modeling – Works effectively even when deep expertise is limited or unavailable
* Hybrid Knowledge – Blends statistical discovery with domain context to avoid "black box" results
* Trust & Adoption – Models are more likely to be accepted because they incorporate the reasoning of both machines and experts

***

#### Why It Matters

Causal inference without domain expertise risks producing results that are correct statistically but irrelevant operationally. RootCause bridges this gap, ensuring models are both data-driven and domain-aware, so they can be trusted to guide real decisions.


# Confounder Detection and Modeling

Confounders are hidden variables that influence both a cause and an effect, creating spurious relationships. If they are not accounted for, causal graphs can mislead, and interventions may fail. RootCause includes explicit mechanisms to detect, represent, and model confounders, ensuring causal discovery remains robust and trustworthy.

***

#### Definition & Purpose

A confounder is a variable that explains away an apparent cause-effect link. For example, both ice cream sales and drownings rise in summer — the confounder is temperature.

Traditional approaches often ignore or oversimplify confounding, leading to incorrect edges in causal graphs. RootCause is designed to:

* Detect when hidden variables may be influencing observed data
* Represent confounders explicitly in the causal model
* Keep causal graphs explainable, with confounder effects transparent to users

***

#### How It Works

1. Latent Variable Detection – After structure discovery completes, the system analyzes residual correlations and conditional-independence test violations to flag relationships that cannot be explained by observed variables alone. This is a dedicated post-discovery stage, not a penalty baked into the structure search.
2. Latent Clustering – Variable pairs showing unexplained shared dependence are grouped into latent clusters, each representing a candidate hidden driver.
3. Probabilistic Modeling – Each cluster can be fitted with a Hybrid Structural Autoencoder (HSAE), representing the hidden confounder as a probabilistic latent node that captures its influence without mislabeling it as a direct cause.
4. Graph Augmentation – Detected latent confounders are added to the causal graph as explicit nodes, so their downstream effects are visible and simulations account for them.

***

#### Oversight & Flexibility

* Users can inspect flagged latent clusters and validate or override them based on domain knowledge, editing the graph directly
* Confounders are visible in the graph, not hidden inside a black box
* Every edge records its direction provenance, so you can distinguish edges supported by statistical evidence from those set by expert review

***

#### Outcomes

* Cleaner Graphs – Reduces spurious edges caused by unobserved variables
* More Reliable Simulations – Interventions are tested against models that reflect hidden drivers
* Transparency – Users can see where uncertainty exists and why

***

#### Why It Matters

Without confounder detection, causal inference risks producing the same misleading results as correlation-based analytics. By explicitly modeling confounders, RootCause ensures that interventions are both scientifically valid and operationally reliable.


# Time-Series Causal Modeling

Most enterprise data is temporal — sales by quarter, sensor readings by second, churn events by month. Standard causal methods struggle with sequences because relationships evolve over time, dependencies shift, and forecasts must respect temporal order. RootCause includes dedicated methods for time-series causal modeling, making it possible to discover, simulate, and optimize causal drivers in dynamic environments.

***

#### Definition & Purpose

Time-series causal modeling extends causal discovery into sequential data. RootCause ensures that:

* Temporal rules (time flows forward, causes precede effects) are built into the model.
* Dependencies are represented dynamically, not as fixed static edges.
* Counterfactuals and interventions can be simulated across past, present, and future time horizons.

This allows organizations to move beyond trend analysis and into causal forecasting.

***

#### How It Works

1. Temporal Anchoring — Events are aligned to precise timestamps, date ranges, or rolling windows.
2. Bayesian Foundations — Conditional distributions are learned with Bayesian additive regression tree (BART) ensembles for time-dependent effects; during temporal discovery, Gaussian-process decomposition separates trend and seasonal structure before dependencies are tested.
3. Lag Discovery — The pipeline automatically screens for the lag at which one variable influences another, so cross-time dependencies are found without manual specification.
4. Monte Carlo Forecasting — Thousands of forward simulations generate distributions of possible futures under different scenarios.
5. Counterfactual Search — Explore which interventions, applied within constraints you define, would steer the trajectory toward a target outcome across sequential periods.
6. Dynamic Optimization — Identify interventions that not only improve a KPI now but sustain impact over future time horizons.

***

#### Oversight & Reliability

* Ontology rules ensure temporal logic is never violated (an effect can't precede a cause).
* Domain experts can define seasonal effects or lags explicitly, or let the model infer them.
* Assumptions are visible in the model, and each edge records how its direction was determined, so time-based drivers can be traced back.

***

#### Outcomes

* Causal Forecasting — Project not just what will happen, but why future changes will occur.
* Scenario Planning — Test strategies across quarters, weeks, or years without risk.
* Scalability — Long histories and wide panels stay tractable: each entity is sharded and processed independently, and the temporal discovery kernels run natively.
* Decision Support — Provides confidence intervals and trade-offs over time, not just point predictions.

***

#### Why It Matters

Without time-series modeling, causal inference is limited to static snapshots. RootCause enables causal reasoning across time, so organizations can plan interventions, anticipate side effects, and optimize outcomes with foresight.


# Requirements

Everything you need before deploying. Read this first, hand the checklist to your infrastructure team, and move on to the Deployment guide once everything is in place.

***

## How the platform is deployed

The RootCause Platform is deployed into your Kubernetes cluster via the **RootCause Operator**. The operator manages the full lifecycle — install, configure, upgrade — through an Admin UI.

The deployment flow is:

1. Your infra team installs the operator (one Helm command)
2. You open the Admin UI and fill in a bootstrap wizard
3. The operator deploys everything: databases, workflow engine, identity, LLM proxy, and the platform itself

Once installed, data scientists can check for updates and apply them through the Admin UI without involving the infra team.

### What the operator deploys

```
┌──────────────────────────────────────────────────────────────────┐
│                         Admin UI (:3000)                         │
│ Bootstrap │ Overview │ Secrets │ Users │ Releases │ LLM │ Cluster│
└────────────────────────────┬─────────────────────────────────────┘
                             │ writes CR
                             ▼
┌──────────────────────────────────────────────────────────────────┐
│                    RootCauseInstallation CR                      │
└────────────────────────────┬─────────────────────────────────────┘
                             │ reconciles
                             ▼
┌──────────────────────────────────────────────────────────────────┐
│                      Operator Controller                         │
└────────────────────────────┬─────────────────────────────────────┘
                             │ manages
             ┌───────────────┼───────────────┐
             ▼               ▼               ▼
      Dependencies       Platform         Secrets
      ├ PostgreSQL       ├ Platform       ├ Auth keys
      ├ MongoDB          ├ Data Service   ├ DB credentials
      │  └ Search        ├ Telemetry (opt) └ Storage credentials
      ├ Redis            └ Ingresses
      ├ Temporal              │
      ├ LiteLLM               │ spawns per task
      ├ FusionAuth            ▼
      └ Garage (opt)     ML Job pods (ephemeral, run on the
                         scale-to-zero compute node pool)
```

**Platform components:**

| Component    | What it does                                                                                                                                                                                                                    |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Platform     | UI and backend-for-frontend (Next.js + API)                                                                                                                                                                                     |
| Data Service | Core backend for data processing, orchestration, LLM integration, and the in-process query/compute engine (FastAPI)                                                                                                             |
| ML Job pods  | Ephemeral Kubernetes Jobs spawned per task by the Data Service for heavy compute (causal discovery, digital twins, simulation, ontology extraction). Not a long-running deployment — pods run to completion and are cleaned up. |
| Telemetry    | Optional local telemetry service, disabled by default                                                                                                                                                                           |

**Infrastructure dependencies** (deployed by the operator into your cluster):

| Dependency | Purpose                                                                                            | Minimum version     |
| ---------- | -------------------------------------------------------------------------------------------------- | ------------------- |
| PostgreSQL | Relational database for Temporal, FusionAuth, and LiteLLM                                          | 15.0+               |
| MongoDB    | Document database for application data, deployed with MongoDB Search (mongot) for full-text search | 8.0+                |
| Redis      | Sync layer                                                                                         | 7.2.4+              |
| Temporal   | Durable workflow execution                                                                         | 1.27.2+             |
| LiteLLM    | LLM API proxy and management                                                                       | Deployed by default |
| FusionAuth | Identity and access management (optional — see Identity below)                                     | Deployed on request |

> **MongoDB operator:** the in-cluster MongoDB replica set and MongoDB Search are managed by the unified MongoDB Kubernetes Operator (MCK, chart `mongodb-kubernetes`). The legacy MongoDB Community Operator cannot deploy MongoDB Search and is rejected by the operator's preflight checks. The Deployment guide covers installing MCK.

Every dependency can instead be connected as an external instance (existing PostgreSQL, MongoDB, Redis, Temporal, or LiteLLM) during the bootstrap wizard.

***

## Infrastructure requirements

### Kubernetes and tooling

| Requirement | Version                                   |
| ----------- | ----------------------------------------- |
| Kubernetes  | 1.26+ (tested on AKS, EKS, GKE, and kind) |
| Helm        | 3.12+                                     |
| kubectl     | Configured with cluster-admin access      |

### Cluster sizing

**Minimum** — supports datasets up to \~5GB, 50 columns, \~1M rows:

| Resource       | Spec                          |
| -------------- | ----------------------------- |
| Nodes          | 3-4                           |
| CPU per node   | 8 vCPU                        |
| RAM per node   | 64 GB                         |
| Storage        | SSD-backed persistent volumes |
| GPU (optional) | 48 GB VRAM (local LLMs only)  |

**Recommended for production** — supports datasets up to \~10GB, 100+ columns, \~20M rows:

| Resource       | Spec                          |
| -------------- | ----------------------------- |
| Nodes          | 4+                            |
| CPU per node   | 64 vCPU                       |
| RAM per node   | 128 GB                        |
| Storage        | SSD-backed persistent volumes |
| GPU (optional) | 96 GB VRAM (local LLMs only)  |

All nodes must be amd64 architecture.

**Compute node pool (optional, recommended for production):** heavy ML jobs and digital twins run as ephemeral Job pods. You can route them onto a dedicated node pool that autoscales from zero — tainted `rootcause.ai/workload=compute:NoSchedule`, labeled `rootcause.ai/nodepool=compute`, autoscaling min=0. This gives heavy jobs large nodes on demand without paying for idle capacity. The Deployment guide covers the configuration.

***

## Cloud-specific prerequisites

The platform runs on Azure, AWS, and GCP. The core deployment is identical; only the items below differ.

| Requirement                 | Azure                                     | AWS                                             | GCP                                   |
| --------------------------- | ----------------------------------------- | ----------------------------------------------- | ------------------------------------- |
| **Managed Kubernetes**      | AKS                                       | EKS                                             | GKE                                   |
| **Storage class**           | `managed-csi`                             | `gp3`                                           | `standard` or `premium-rwo`           |
| **Object storage**          | Azure Blob Storage                        | S3                                              | GCS                                   |
| **Compute pool autoscaler** | Built-in cluster autoscaler               | Cluster Autoscaler or Karpenter (self-deployed) | Built-in cluster autoscaler           |
| **Ingress options**         | Azure Application Gateway (AGIC) or nginx | nginx or ALB Ingress Controller                 | nginx or GCE Ingress                  |
| **Identity (OIDC)**         | Azure EntraID                             | Okta, Auth0, or any OIDC provider               | Google Workspace or any OIDC provider |

> **Note:** Azure Application Gateway requires additional ingress annotations and path configuration. The Deployment guide covers this in detail.

> **No cloud bucket?** On any cloud (or on-prem) you can skip external object storage entirely: the operator can deploy **Garage**, an in-cluster S3-compatible object store, fully automated — it creates the bucket, generates credentials, and wires everything to the platform. See Decision Point 3 below.

***

## What you need to provide

Hand this checklist to your infrastructure team. Everything must be in place before deployment begins.

### Cluster and access

* [ ] Kubernetes cluster provisioned (1.26+, amd64 nodes, SSD-backed storage)
* [ ] `kubectl` configured with cluster-admin access
* [ ] Helm 3.12+ installed
* [ ] (Optional) Compute node pool for ML jobs: autoscaling node group with min=0, tainted `rootcause.ai/workload=compute:NoSchedule`, labeled `rootcause.ai/nodepool=compute`

### Networking

* [ ] Ingress controller installed (nginx, Azure Application Gateway, or equivalent)
* [ ] Base domain with wildcard DNS record pointing to the ingress controller IP
* [ ] Subdomains planned for: platform, auth, and litellm (e.g., `platform.rootcause.example.com`, `auth.rootcause.example.com`, `litellm.rootcause.example.com`)
* [ ] TLS certificate — wildcard or per-subdomain
* [ ] Outbound (egress) access from the cluster to:
  * `registry.gitlab.com` — container images and OCI Helm charts
  * `https://telemetry.rootcause.ai` — platform telemetry
  * Your LLM provider APIs (e.g., OpenAI, Anthropic, Google, AWS Bedrock, Azure OpenAI) — unless serving local LLMs

### Storage

* [ ] Object storage — choose one:
  * A **single** bucket/container created with credentials. Datasets, digital twins, and ML models are stored as sub-directories of this one bucket.
  * Nothing — use the in-cluster **Garage** object store, deployed and configured automatically by the operator.
* [ ] Storage class available for persistent volumes (e.g., `managed-csi`, `gp3`)

### Registry access

* [ ] Container registry credentials from RootCause (GitLab deploy token with `read_registry` scope)

### Identity (choose one)

* [ ] **OIDC (recommended):** Issuer URL, client ID, client secret, and well-known configuration URL from your identity provider
* [ ] **SAML:** Metadata URL or XML, entity ID, and certificate from your identity provider
* [ ] **Managed FusionAuth:** No preparation needed — the operator provisions it automatically. Best for POCs or organizations without an existing IdP.

### LLM access

* [ ] API keys for at least one LLM provider (OpenAI, Anthropic, Google AI Studio, AWS Bedrock, or Azure OpenAI). LiteLLM is included in every deployment and proxies requests to your LLM providers.

***

## What RootCause provides

* **RootCause Operator** Helm chart (OCI registry)
* **Platform and dependencies** Helm charts (OCI registry, pulled automatically by the operator)
* **Admin UI** for configuration, deployment, user management, and upgrades
* **Deployment support** via Slack, email, and scheduled check-ins

***

## Decision points

Answer these before starting the Deployment guide. They determine which sections you'll fill in during the bootstrap wizard.

### 1. Identity provider

| Option                          | When to choose it                                                                            |
| ------------------------------- | -------------------------------------------------------------------------------------------- |
| **External OIDC** (recommended) | Your organization has an existing identity provider (EntraID, Okta, Auth0, Google Workspace) |
| **External SAML**               | Your IdP only supports SAML, or your security team requires it                               |
| **Managed FusionAuth**          | POC, eval, or no existing IdP. The operator deploys and configures FusionAuth automatically. |

### 2. Ingress controller

| Option                        | When to choose it                                                                                                                                                     |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **nginx**                     | Most common. Works on all clouds. Simpler configuration.                                                                                                              |
| **Azure Application Gateway** | Required by your Azure networking team, or you need WAF/DDoS protection at the ingress layer. Requires additional annotations and path config — see Deployment guide. |

### 3. Object storage

The platform uses one bucket/container; everything is stored under sub-directories of it.

| Option                    | What you need                                                                                                                                                     |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Azure Blob Storage        | Storage account name and one auth method: connection string, account key, or service principal (tenant ID, client ID, client secret); one container               |
| AWS S3 (or S3-compatible) | One bucket, access key, secret key, region — plus an endpoint URL for S3-compatible stores                                                                        |
| GCS                       | One bucket, project ID, service account credentials                                                                                                               |
| **Garage (in-cluster)**   | Nothing — the operator deploys it, creates the bucket, and generates credentials. Single-node mode for dev; 3-replica production mode needs 3+ schedulable nodes. |

### 4. ML job compute

| Option                                   | When to choose it                                                                                                                |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| **Default node pool**                    | Simplest. ML Job pods run on the general cluster nodes.                                                                          |
| **Dedicated scale-to-zero compute pool** | Production. Heavy jobs get large nodes on demand without paying for idle capacity; small ontology jobs stay on the default pool. |

***

## Next step

Once your infrastructure team has checked off the list above, proceed to the **Deployment guide**.


# Deployment Guide

This guide takes you from a prepared Kubernetes cluster to a running RootCause Platform. It assumes your infrastructure team has completed the checklist in the Requirements doc.

There are four CLI steps to bootstrap the operator, then everything else happens in the Admin UI.

***

## Before you start

Confirm you have:

* [ ] Kubernetes cluster running (1.26+) with `kubectl` cluster-admin access
* [ ] Helm 3.12+ installed
* [ ] Ingress controller deployed with wildcard DNS pointing to its IP
* [ ] Object storage ready: a single bucket/container with credentials — or nothing, if you plan to use the in-cluster Garage option
* [ ] Container registry credentials from RootCause (GitLab deploy token)
* [ ] DNS base domain and subdomains planned
* [ ] TLS certificate available
* [ ] Identity provider details ready (if using external OIDC or SAML)
* [ ] LLM provider API keys ready (at least two providers recommended — see Step 7)

If anything is missing, go back to the [Requirements doc](/installation-and-deployment/requirements) and hand the checklist to your infrastructure team.

***

## Step 1: Create the namespace

```bash
kubectl create namespace rootcause
```

All RootCause components will be deployed into this namespace.

**Verify:**

```bash
kubectl get namespace rootcause
```

***

## Step 2: Create registry credentials

The operator and platform images are hosted on GitLab Container Registry. Create an image pull secret:

```bash
kubectl create secret docker-registry regcred \
  -n rootcause \
  --docker-server=registry.gitlab.com \
  --docker-username=<your-username> \
  --docker-password=<your-deploy-token>
```

Use the GitLab deploy token provided by RootCause. It needs `read_registry` scope. The operator reuses this secret for both image pulls and OCI chart pulls — no separate chart registry secret is needed.

**Verify:**

```bash
kubectl get secret regcred -n rootcause
```

***

## Step 3: Install the unified MongoDB Kubernetes Operator (MCK)

The platform uses the unified MongoDB Kubernetes Operator (MCK — MongoDB Controllers for Kubernetes) to manage its MongoDB replica set and MongoDB Search (mongot). MongoDB Search is part of every deployment, and only MCK can deploy it — the legacy MongoDB Community Operator cannot, and the RootCause Operator's preflight checks reject it.

```bash
helm install mongodb-kubernetes mongodb-kubernetes \
  --repo https://mongodb.github.io/helm-charts \
  --version 1.9.1 \
  -n rootcause \
  --set operator.watchNamespace=rootcause
```

The RootCause Operator pins MCK chart version `1.9.1` for compatibility with the dependency charts it deploys.

> **Skip this step** if a compatible MCK is already installed cluster-wide. It should be configured to watch all namespaces. If an MCK is present but too old, the Admin UI's Rollout panel offers an **Upgrade MongoDB operator** button that remediates it in place.

**Verify:**

```bash
kubectl get pods -n rootcause
```

You should see one `mongodb-kubernetes-operator-...` pod in `Running` state.

***

## Step 4: Install the RootCause Operator

```bash
helm install rootcause-operator \
  oci://registry.gitlab.com/perceptura/client-deployments/releases-platform/charts/rootcause-operator \
  -n rootcause
```

The chart defaults `imagePullSecrets` to `regcred`, so no extra flags are needed.

**Verify:**

```bash
kubectl get pods -n rootcause
```

You should see:

```
rootcause-operator-controller-...   1/1   Running
rootcause-operator-admin-...        1/1   Running
mongodb-kubernetes-operator-...     1/1   Running
```

***

## Step 5: Access the Admin UI

> **Preflight checks:** on first startup the operator seeds a `RootCauseInstallation` in `mode: preflight`. Nothing is deployed yet, but the reconcile loop immediately runs live cluster checks — required CRDs, registry pull secret, MongoDB operator (MCK) version and schema compatibility — and populates the release catalog, so the Bootstrap page shows live verdicts and version dropdowns before you configure anything. Applying the wizard configuration in Step 6 switches the installation to `mode: active` and starts the actual deployment.

Port-forward the Admin UI to your local machine:

```bash
kubectl port-forward -n rootcause svc/rootcause-operator-admin 3000:3000
```

Open <http://localhost:3000> in your browser.

### Log in

The operator generates a master password during installation. Retrieve it:

```bash
kubectl get secret rootcause-bootstrap-auth -n rootcause \
  -o jsonpath='{.data.ADMIN_PASSWORD}' | base64 -d
```

Enter this password on the login page.

***

## Step 6: Configure via the Bootstrap Wizard

The Admin UI presents a wizard with several sections. Walk through each one.

### Release Versions

* **Dependencies chart version** and **Platform chart version**: Use the latest versions unless RootCause support has told you otherwise.

### Installation

* **Namespace**: Shown read-only — the namespace the operator was installed into.
* **Client ID**: Your organization identifier (provided by RootCause, e.g., `acme-corp`).

### Storage

Choose a storage backend and enter its connection details:

| Backend                              | What to enter                                                                                                                                                          |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **S3 / S3-compatible**               | Region, access key ID, secret access key; optional endpoint URL for S3-compatible stores                                                                               |
| **Azure Blob Storage**               | Storage account, endpoint suffix (`core.windows.net`), and one auth method: connection string, account key, or service principal (tenant ID, client ID, client secret) |
| **Google Cloud Storage**             | Project ID and service account credentials                                                                                                                             |
| **Garage (self-hosted, in-cluster)** | Nothing — fully automated                                                                                                                                              |

For cloud backends, enter a **single bucket/container name**. Datasets, digital twins, and ML models are stored as sub-directories of this one bucket (`ROOTCAUSE_BUCKET`).

For **Garage**, the operator deploys an S3-compatible object store inside the cluster, creates the bucket, generates credentials, and wires everything to the platform. Pick a mode:

* **Single node** — 1 replica, RF=1. For development and single-node clusters.
* **Production** — 3 replicas, RF=3, pod anti-affinity. Requires 3+ schedulable nodes.

Set the storage capacity (PVC size per replica, default `50Gi`).

Also set the **Kubernetes storage class** for persistent volumes (e.g., `managed-csi`, `gp3`, `standard-rwo`).

### Networking

| Field             | What to enter                                                                    |
| ----------------- | -------------------------------------------------------------------------------- |
| **Base domain**   | Your base domain (e.g., `rootcause.example.com`)                                 |
| **Ingress class** | `nginx` for most deployments. `azure/application-gateway` for Azure App Gateway. |
| **Subdomains**    | Platform, Auth, and LiteLLM subdomains (e.g., `platform`, `auth`, `litellm`)     |

#### Ingress annotations

Add annotations under **All ingresses (base)** based on your ingress controller:

**nginx:**

| Key                                        | Value  |
| ------------------------------------------ | ------ |
| `nginx.ingress.kubernetes.io/ssl-redirect` | `true` |

For TLS with a pre-existing wildcard certificate, select **Manual (bring your own secret)** under TLS mode and provide the secret name.

**Azure Application Gateway:**

| Key                                          | Value   |
| -------------------------------------------- | ------- |
| `appgw.ingress.kubernetes.io/ssl-redirect`   | `false` |
| `appgw.ingress.kubernetes.io/use-private-ip` | `true`  |

For each ingress (Platform, Auth, LiteLLM), also add:

| Key                                                 | Value                     |
| --------------------------------------------------- | ------------------------- |
| `appgw.ingress.kubernetes.io/appgw-ssl-certificate` | *(your certificate name)* |

> **Azure Application Gateway note:** App Gateway does not resolve loopback external URLs from within the cluster. You will need a `hostAliases` resource patch in the Advanced section — see [Azure Application Gateway patches](#azure-application-gateway-patches) below.

### Identity & Access

Choose based on the decision you made in the Requirements doc:

**External OIDC (recommended)**

| Field               | What to enter                                                                               |
| ------------------- | ------------------------------------------------------------------------------------------- |
| Authentication mode | OIDC                                                                                        |
| Deploy FusionAuth   | No                                                                                          |
| Issuer              | Your IdP's issuer URL                                                                       |
| Client ID           | Your application's client ID                                                                |
| Client secret       | Your application's client secret                                                            |
| Well-known URL      | Your IdP's OpenID configuration URL                                                         |
| Logout URL          | Your IdP's logout endpoint (include a `post_logout_redirect_uri` back to your platform URL) |

> **Azure EntraID specifics:** The issuer URL is `https://login.microsoftonline.com/<tenant-id>/v2.0`. In the Azure Portal, ensure your app registration has:
>
> 1. **Redirect URI**: `https://<platform-subdomain>.<base-domain>/api/auth/callback/login` (type: Web)
> 2. **Token configuration**: Include `email`, `profile`, and `openid` scopes
> 3. **API permissions**: `openid`, `profile`, `email` (Microsoft Graph, delegated)

**External SAML**

| Field                | What to enter                                                 |
| -------------------- | ------------------------------------------------------------- |
| Authentication mode  | SAML                                                          |
| Deploy FusionAuth    | No                                                            |
| *(remaining fields)* | Metadata URL or XML, entity ID, and certificate from your IdP |

**Managed FusionAuth (POC / no existing IdP)**

| Field                | What to enter     |
| -------------------- | ----------------- |
| Authentication mode  | Built-in (no SSO) |
| Deploy FusionAuth    | Yes               |
| FusionAuth API key   | *(leave blank)*   |
| FusionAuth Tenant ID | *(leave blank)*   |

Leave credentials blank. The operator auto-provisions everything: API keys, tenant, application, and OIDC configuration.

### Email (optional)

SMTP credentials for outbound platform email: user, passkey, host, port, and an optional CA certificate (only needed when the SMTP server uses a private CA). Host defaults to `smtp.rootcau.se` and port to `30025`. Skip this section if you don't need outbound email.

### Telemetry (optional)

An opt-in, in-cluster observability stack — off by default. When enabled, logs and metrics flow through an OpenTelemetry Collector gateway into local Loki + Prometheus, with a passwordless Grafana over both (reach it with `kubectl port-forward`). Configure retention days (default 7) and volume sizes, and optionally forward everything to an external OTLP collector (gRPC or HTTP).

### Dependencies

Each dependency is deployed by the operator by default, or connected to an external instance:

| Dependency | Deploy (default)                                                                                         | External                                 |
| ---------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| PostgreSQL | Deployed by the operator                                                                                 | Host, port, username, password, SSL mode |
| MongoDB    | Set replicas: 1 for testing, 3 for production. MongoDB Search (mongot) is deployed alongside by default. | Connection URI                           |
| Redis      | Set replicas: 1 for testing, 3 for production                                                            | Connection URL or JSON sentinel config   |
| Temporal   | Deployed by the operator                                                                                 | Frontend URL (`host:7233`)               |
| LiteLLM    | Deployed by the operator                                                                                 | URL of your existing LiteLLM instance    |

### Node Selector (optional)

Constrain **all** workloads — every pod across both the dependencies and platform charts — to nodes matching label key/value pairs. For example, `usage: rootcause` to match a dedicated AKS node pool label.

### Compute Node Pool (optional)

Route heavy ML jobs and digital twins (causal discovery, digital twin training, simulation) onto a dedicated node pool that scales to zero when idle. This applies only to the ephemeral Job pods the Data Service spawns — not the long-running services. Leave empty to run all ML jobs on the default nodes.

The contract is the same on every cloud:

1. **You provision** a node group that is tainted `rootcause.ai/workload=compute:NoSchedule`, labeled `rootcause.ai/nodepool=compute`, and autoscaling with **min = 0**.
2. **The wizard fields** stamp a matching node selector + toleration onto the spawned ML Job pods. Those pods stay `Pending` until a compute node exists.
3. **Your cluster autoscaler** sees the `Pending` pod and scales the pool `0 → 1`, then back to `0` when the job finishes. The operator does not create node groups.

AKS example (built-in autoscaler, nothing extra to deploy):

```bash
az aks nodepool add \
  --resource-group <rg> --cluster-name <cluster> \
  --name compute --mode User --node-vm-size Standard_E4s_v3 --node-count 0 \
  --enable-cluster-autoscaler --min-count 0 --max-count 2 \
  --node-taints rootcause.ai/workload=compute:NoSchedule \
  --labels rootcause.ai/nodepool=compute
```

On GKE, use the built-in autoscaler the same way. On EKS, self-deploy Cluster Autoscaler (or Karpenter) with node-template tags for the taint/label so the group can scale from zero.

Optional fields:

* **Pool name** — logical name used for pool-scoped capacity checks (e.g., `compute`)
* **Max node memory GiB** — lets the platform reject physically impossible workloads while the pool is at zero
* **Job kinds** — which ML job kinds are routed to the pool. Default: the heavy kinds (`causal_discovery`, `causal_discovery_aggregate`, `digital_twin`, `simulation`); small, frequent ontology jobs stay on the default pool to avoid scale-from-zero latency.

### Components

Configure replicas, resources, and extra environment variables per long-running component. Defaults work for testing. For production, use these as a starting point:

| Component    | Replicas | CPU request | Memory request |
| ------------ | -------- | ----------- | -------------- |
| Platform     | 2-3      | 500m        | 1 Gi           |
| Data Service | 2-3      | 1           | 2 Gi           |

ML jobs are not configured here — they run as ephemeral Kubernetes Job pods with per-job resources set automatically by the Data Service. See the **Upgrades & Operations** doc for detailed scaling guidance.

### Service Accounts (optional)

Create Kubernetes service accounts with annotations and assign them to the `platform` and/or `data-service` deployments. Useful for workload identity (e.g., AWS IAM Roles for Service Accounts).

### Advanced

For most deployments, you can skip this section. It's here for edge cases.

* **Resource patches**: Deep-merge patches into rendered Kubernetes manifests (annotations, tolerations, node selectors, `hostAliases`, etc.)
* **Raw Helm overrides**: Free-form YAML merged over computed values for any chart setting not covered by the wizard

#### Azure Application Gateway patches

Azure Application Gateway does not resolve external URLs from within the cluster. The platform pod needs a `hostAliases` entry to route auth traffic to the Application Gateway's IP directly.

Add a **Deployment** resource patch:

| Field       | Value              |
| ----------- | ------------------ |
| Chart       | platform           |
| Kind        | deployment         |
| Object name | rootcause-platform |

Patch content:

```yaml
spec:
  template:
    spec:
      hostAliases:
      - ip: "<app-gateway-public-ip>"
        hostnames:
        - "<auth-subdomain>.<base-domain>"
```

App Gateway also requires explicit path definitions. Add these in **Raw Helm Overrides**:

**Platform chart overrides:**

```yaml
platform:
  ingress:
    hosts:
      - host: <platform-subdomain>.<base-domain>
        paths:
          - path: /
            pathType: Exact
            port: 80
          - path: /*
            pathType: Prefix
            port: 80
```

**Dependencies chart overrides:**

```yaml
fusionauth:
  ingress:
    paths:
      - path: /*
        pathType: Prefix
      - path: /
        pathType: Exact
```

> Without both path types, App Gateway may return 502 errors on some requests.

### Effective Values Preview

Before applying, this section shows the final Helm values the operator computes from your configuration (wizard fields, patches, and raw overrides merged) — use it to sanity-check what will actually be deployed.

### Deploy

Review the **Deployment Summary** at the bottom of the wizard, then click **Apply configuration**.

The operator will:

1. Create required secrets (storage credentials, platform config)
2. Create the `RootCauseInstallation` custom resource
3. Deploy infrastructure dependencies (PostgreSQL, Redis, MongoDB, Temporal, LiteLLM, and optionally FusionAuth)
4. Deploy platform services (Platform, Data Service)

Watch the **Deployment status** panel on the right. The phase progresses through `Reconciling` to `Ready`, typically in 2-5 minutes.

***

## Step 7: Configure LLM models

After the platform is deployed, configure LLM access on the **LLM** page in the Admin UI. Configure at least two providers (e.g., one OpenAI, one Anthropic) so fallbacks keep the platform working through provider outages.

> If you configured an external LiteLLM instance in the wizard, manage models in your own instance instead, then continue to Step 8.

The LLM page has four sections. Work top to bottom:

### Provider Keys

Add an API key per LLM provider. The keys are stored as a Kubernetes secret in the installation namespace — you never need to log in to the LiteLLM UI or create virtual keys; the operator reads the LiteLLM master key itself.

### Models

Register the LiteLLM models backed by those provider keys: pick the provider, the upstream model, and a model name. Repeat for each model you want available.

### Tiers

Map the platform's model tiers (small / medium / large) to default models. The platform picks a tier per task; these defaults decide which registered model serves each tier.

### Fallbacks

Define per-model fallback chains so the platform always has a working LLM, even during provider outages: select a primary model and add one or more fallbacks in order of preference.

> **Tip:** Match fallbacks by weight class — if your primary is GPT-4, fall back to Claude Sonnet, not to a smaller model. The exact model doesn't matter as much as matching capability.

### Where this configuration lives

The model registry and fallback configuration are persisted declaratively in the `RootCauseInstallation` CR (`spec.config.dependenciesConfig.litellm.config`); the LiteLLM ConfigMap is rendered from that spec on every reconcile. Tier routing is stored in MongoDB. This configuration **survives upgrades and reinstalls** — there is nothing to export or screenshot. Exporting the CR (see Upgrades & Operations) backs it up along with everything else.

**Verify:** the Models section lists your models without runtime sync errors, and each tier has a default model assigned.

***

## Step 8: Create platform users

Navigate to the **Users** page in the Admin UI.

**With managed FusionAuth:**

1. Click **+ Add user**
2. Enter email, password, first name, last name
3. Click **Create user**

The operator creates a FusionAuth account, registers it to the platform application, and adds the email to the admin list automatically.

**With external OIDC or SAML:**

Create users in your external identity provider (EntraID, Okta, etc.), then add their email addresses in the **Platform admin emails** section on the Users page. These emails are stored in the CR and mounted as `PLATFORM_ADMIN_EMAILS` on the platform deployment.

***

## Step 9: Log in and verify

Navigate to `https://<platform-subdomain>.<base-domain>`.

* With FusionAuth: click "Continue with OIDC SSO" and log in with the credentials from Step 8
* With external OIDC/SAML: you'll be redirected to your identity provider

### Post-install smoke test

Run through these checks to confirm everything is working:

| # | Check                 | How                                                                                                              |
| - | --------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 1 | All pods running      | `kubectl get pods -n rootcause` — all should be `Running` or `Completed`                                         |
| 2 | Admin UI accessible   | <http://localhost:3000> loads (with port-forward active)                                                         |
| 3 | Platform login works  | Navigate to platform URL, complete login flow, reach the home page                                               |
| 4 | LLM responds          | Admin UI **LLM** page shows your models without sync errors; ask the platform's AI a question and get a response |
| 5 | Data works end-to-end | Create a workspace, open a Data View, confirm it loads                                                           |

If any check fails, see the **Troubleshooting** section in the Upgrades & Operations doc.

***

## Next step

Proceed to the **Upgrades & Operations** doc for day-2 operations: applying updates, rolling back, scaling, and troubleshooting.


# Upgrades & Operations

Day-2 operations for the RootCause Platform. This doc covers upgrades, rollback, scaling, configuration changes, and troubleshooting.

**Who this is for:** Data scientists can handle upgrades and routine operations (Sections 1-3). Infrastructure teams should review the backup, rollback, scaling, and troubleshooting sections.

***

## 1. How updates work

The RootCause Operator automatically checks the OCI registry for new chart versions. When an update is available, it appears on the **Releases** page in the Admin UI.

Key points:

* **You can jump directly to any version** — no need to step through intermediate releases
* **Dependencies and platform are upgraded together** — the operator manages both Helm releases as a unit
* **Updates are applied through the Admin UI** — no Helm commands needed for routine upgrades

***

## 2. Upgrading

### Before you upgrade (recommended)

The operator does not require backups before upgrading. However, we recommend these steps as best practice — they take a few minutes and give you a recovery path if anything unexpected happens.

**Recommended backup checklist:**

```bash
# Export the CR spec (captures your full configuration)
kubectl get rootcauseinstallation rootcause -n rootcause -o yaml > rc-backup-$(date +%Y%m%d).yaml

# PostgreSQL dump (Temporal, FusionAuth, and LiteLLM databases)
kubectl exec -it postgres-0 -n rootcause -- \
  pg_dumpall -U postgres > postgres-backup-$(date +%Y%m%d).sql

# MongoDB dump
kubectl exec -it perceptura-mongo-0 -n rootcause -- \
  mongodump --out=/backup/$(date +%Y%m%d)
```

The CR export already captures your LLM configuration — the model registry and fallback chains live in `spec.config.dependenciesConfig.litellm.config`, not in the database — so there is nothing separate to export for LiteLLM.

Also recommended:

* Check release notes for the target version
* Test in a staging environment if you have one

### Applying an upgrade

**Via the Admin UI (recommended):**

1. Open the Admin UI
2. Go to the **Releases** page
3. Select the target version
4. Click **Request upgrade**
5. Watch the **Deployment status** panel — the phase progresses through `Reconciling` to `Ready`

**Via CLI** (for automation or GitOps workflows):

```bash
# Update the chart versions in the CR spec
kubectl patch rootcauseinstallation rootcause -n rootcause \
  --type=merge -p '{"spec":{"release":{"dependenciesChartVersion":"<new-version>","platformChartVersion":"<new-version>"}}}'
```

The operator detects the spec change and reconciles automatically.

**Deferring until ML jobs finish:** an upgrade restarts the platform, so any in-progress ML jobs (causal discovery, digital twin training, etc.) would lose their work. The Releases page shows how many ML jobs are currently running and lets you request the upgrade **deferred until ML jobs are idle**. The operator then holds the action, sets the phase to `WaitingForMLJobs`, records the pending action and the live job list in the CR status (`status.pendingAction`, `status.activeMlJobs`), rechecks every 30 seconds, and applies the upgrade automatically once the last job finishes. Force reconcile and undeploy support the same deferral (`spec.actions.deferUntilMLJobsIdle`).

**Monitor the upgrade:**

```bash
# Watch pods restart
kubectl get pods -n rootcause -w

# Check installation status
kubectl get rootcauseinstallation -n rootcause -o jsonpath='{.status.phase}'
```

**Verify:** Run the same smoke test from the Deployment guide (Step 9) — all pods running, Admin UI accessible, platform login works, LLM responds, data loads.

***

## 3. Rolling back

The operator treats rollback the same as any other version change. To go back to a previous version, you select it and apply it — the operator deploys whichever version you tell it to.

This works because the operator manages the full deployment state. It doesn't need to "undo" anything — it simply deploys the version you specify.

### Steps

1. Open the Admin UI > **Releases** page
2. Select the previous version you want to return to
3. Click **Request upgrade** (yes, "upgrade" — the operator doesn't distinguish between moving forward or backward)
4. Watch the **Deployment status** panel
5. Verify with the smoke test

### When implicit rollback isn't enough

In rare cases — for example, if an upgrade included a database schema migration that isn't backward-compatible — selecting the previous version may not fully restore the old behavior. If this happens and you took backups before upgrading:

**Restore PostgreSQL:**

```bash
kubectl exec -i postgres-0 -n rootcause -- \
  psql -U postgres < postgres-backup-<date>.sql
```

**Restore MongoDB:**

```bash
kubectl exec -it perceptura-mongo-0 -n rootcause -- \
  mongorestore --drop /backup/<date>
```

LiteLLM model and fallback configuration lives in the CR spec, so it is reapplied automatically on every reconcile — nothing to re-enter.

Then select the previous version on the Releases page and apply it.

***

## 4. Scaling

Two things scale independently:

* **Long-running services** (Platform, Data Service) — fixed replica counts and resources, set in the **Components** section of the bootstrap wizard. Change values and click **Apply configuration** — the operator reconciles. The platform charts do not ship Horizontal Pod Autoscalers; replicas are whatever you set.
* **ML job pods** — ephemeral Kubernetes Jobs the Data Service spawns per task. There is no ML Jobs deployment to scale; capacity is a function of the nodes available to schedule those pods.

### Long-running services

**Replica counts by workload size:**

| Component    | Dev/Test | Small prod (50 users) | Medium prod (200 users) | Large prod (200+ users) |
| ------------ | -------- | --------------------- | ----------------------- | ----------------------- |
| Platform     | 1        | 2                     | 3                       | 5                       |
| Data Service | 1        | 3                     | 5                       | 10                      |

**Resource limits:**

**Platform (Web UI):**

|        | Request | Limit |
| ------ | ------- | ----- |
| CPU    | 500m    | 2     |
| Memory | 1 Gi    | 4 Gi  |

**Data Service:**

|        | Request | Limit |
| ------ | ------- | ----- |
| CPU    | 1       | 4     |
| Memory | 2 Gi    | 8 Gi  |

### ML job pods

ML workloads (causal discovery, digital twin training, simulation, ontology extraction) run as Kubernetes Jobs created per task: the pod runs to completion and is cleaned up. The Data Service sets resources per job kind:

| Job kind                     | CPU request / limit | Memory request / limit |
| ---------------------------- | ------------------- | ---------------------- |
| Causal discovery             | 4 / 16              | 8 Gi / 32 Gi           |
| Causal discovery (aggregate) | 2 / 8               | 16 Gi / 48 Gi          |
| Digital twin                 | 2 / 8               | 4 Gi / 16 Gi           |
| Simulation                   | 2 / 4               | 2 Gi / 8 Gi            |
| Ontology jobs                | 1-2 / 4-8           | 2-8 Gi / 8-20 Gi       |

If a job is OOM-killed, the retry escalates memory 1.5x per OOM, capped at 85% of the largest compute node's memory (or 64 Gi when the node size is unknown). Workloads that would exceed the cap are rejected as too large instead of thrashing.

To tune defaults without a code change, set the `ML_JOB_RESOURCES_OVERRIDE` environment variable on the Data Service (extra environment variables in the wizard's Components section) — a JSON mapping of job kind to partial resource fields:

```json
{"causal_discovery": {"memory_request": "16Gi", "memory_limit": "64Gi"}}
```

### Sizing the compute node pool

If you configured the **Compute Node Pool** section of the wizard, the heavy job kinds are routed to a dedicated node group that your cluster autoscaler scales from zero on demand. Sizing guidance:

* **Node size**: jobs are memory-bound. The largest default limit is 48 Gi (aggregate causal discovery), so nodes with 64 GB RAM are a sensible floor; use larger nodes for very large models (100+ variables), which escalate toward the node cap on retries.
* **Max node count**: bounds how many heavy jobs run in parallel. 2-4 is enough for most teams.
* **Max node memory GiB**: set this wizard field so the platform can reject physically impossible workloads even while the pool is scaled to zero.
* Job pods sitting in `Pending` for a few minutes while the pool scales `0 → 1` is normal, not a failure.

### Scaling databases

Databases scale through the Dependencies section of the wizard or via Raw Helm Overrides:

| Database   | How to scale                                                                        | Production recommendation           |
| ---------- | ----------------------------------------------------------------------------------- | ----------------------------------- |
| MongoDB    | Increase replica set members (1 → 3 for HA, a wizard toggle) and storage size       | 3 replicas, 100 Gi+ storage         |
| PostgreSQL | Vertical scaling (increase CPU/memory). Add read replicas for read-heavy workloads. | 2-4 CPU, 4-8 Gi RAM, 10 Gi+ storage |
| Redis      | Increase replicas (1 → 3, a wizard toggle) and memory                               | 1-4 CPU, 2-8 Gi RAM                 |

### Node placement

* **All workloads**: the wizard's **Node Selector** section applies a node selector to every pod across both charts (e.g., `usage: rootcause` for a dedicated node pool).
* **ML job pods only**: the **Compute Node Pool** section stamps a node selector + toleration onto the spawned Job pods, stored in the CR as:

```yaml
spec:
  config:
    computePool:
      nodePool: compute
      nodeSelector:
        rootcause.ai/nodepool: compute
      tolerations:
        - key: rootcause.ai/workload
          operator: Equal
          value: compute
          effect: NoSchedule
```

***

## 5. Changing configuration

Change any setting in the bootstrap wizard and click **Apply configuration**. The operator detects the spec change (generation bump) and reconciles — upgrading both Helm releases with the updated values.

Changes take effect within minutes. The Deployment status panel shows the reconciliation progress.

**Force reconcile:** If the installation is stuck or you need to re-apply values without changing the spec, click **Force reconcile** in the Deployment status panel. Via CLI:

```bash
kubectl patch rootcauseinstallation rootcause -n rootcause \
  --type=merge -p '{"spec":{"actions":{"forceReconcileNonce":"'$(uuidgen)'"}}}'
```

***

## 6. Managing secrets

The **Secrets** page in the Admin UI lists all namespace secrets. You can view, create, edit, and delete secrets. Missing secrets required by the platform are highlighted.

**Rotating credentials:**

1. Update the secret value on the Secrets page (or via `kubectl`)
2. Restart the affected pods so they pick up the new value:

```bash
# Example: restart data-service after rotating storage credentials
kubectl rollout restart deployment rootcause-platform-data-service -n rootcause
```

> LLM provider API keys are managed on the **LLM** page (Provider Keys section), not here.

***

## 7. Managing users

### With managed FusionAuth

Use the **Users** page in the Admin UI to add, edit, or remove users. The operator manages FusionAuth accounts and the platform admin email list automatically.

### With external OIDC/SAML

Manage user accounts in your identity provider (EntraID, Okta, etc.). In the Admin UI, use the **Platform admin emails** section on the Users page to control which users have admin access. These emails are stored in the CR and mounted as `PLATFORM_ADMIN_EMAILS`.

***

## 8. Uninstalling

On the Bootstrap page, scroll to **Danger Zone**, check the confirmation box, and click **Request undeploy**. The operator will:

1. Uninstall the platform Helm release
2. Uninstall the dependencies Helm release
3. Clean up operator-managed secrets

The phase moves through `Uninstalling` while this runs (or `WaitingForMLJobs` first, if you deferred the undeploy until running ML jobs finish). The installation CR is preserved in `Uninstalled` phase. You can redeploy by updating the spec and clicking Apply configuration — the operator will do a fresh deployment.

> **Warning:** Undeploying destroys all data in the deployed databases (PostgreSQL, MongoDB, Redis). Take backups before undeploying if you need to preserve data.

***

## 9. Troubleshooting

### Check operator logs

```bash
kubectl logs deploy/rootcause-operator-controller -n rootcause
```

### Check installation status

```bash
kubectl get rootcauseinstallation -n rootcause -o yaml
```

Key fields:

| Field                  | What it tells you                                                                                               |
| ---------------------- | --------------------------------------------------------------------------------------------------------------- |
| `status.phase`         | Current state: `Ready`, `Reconciling`, `WaitingForMLJobs`, `Degraded`, `Blocked`, `Uninstalling`, `Uninstalled` |
| `status.lastError`     | Error message if the phase is `Degraded`                                                                        |
| `status.conditions`    | Detailed condition status for each subsystem                                                                    |
| `status.activeMlJobs`  | ML Job pods currently running (count and job list)                                                              |
| `status.pendingAction` | Action (upgrade, force reconcile, undeploy) deferred until ML jobs finish                                       |

### Check Helm releases

```bash
helm list -n rootcause
```

### Check pod logs

```bash
# Platform logs
kubectl logs -l app=platform -n rootcause --tail=50

# Data service logs
kubectl logs -l app=data-service -n rootcause --tail=50

# Check logs from a crashed container
kubectl logs <pod-name> -n rootcause --previous
```

### Common issues

| Issue                                     | Cause                                                        | Fix                                                                                          |
| ----------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| `ImagePullBackOff`                        | Missing or invalid pull secret                               | Verify `regcred` exists with correct credentials                                             |
| `Degraded` with Helm error                | Chart values validation failure                              | Check `status.lastError` and fix the configuration in the wizard                             |
| FusionAuth stuck in Maintenance Mode      | `silentMode` not enabled                                     | Ensure operator version includes the silent mode fix (0.1.14+)                               |
| OIDC login returns `invalid_redirect_uri` | Wildcard validation not enabled                              | Ensure operator version includes `authorizedURLValidationPolicy: AllowWildcards` (0.1.16+)   |
| PVC stuck in Pending                      | No matching storage class                                    | Set `storageClass` in the bootstrap wizard to match your cluster                             |
| Pods stuck in Pending                     | Insufficient cluster resources                               | Scale up nodes or reduce replica counts                                                      |
| ML job pod Pending for a few minutes      | Compute node pool scaling from zero                          | Normal. If it persists, check your cluster autoscaler and the pool's taint/label.            |
| Phase stuck in `WaitingForMLJobs`         | A requested action was deferred until running ML jobs finish | Wait for the jobs (see `status.activeMlJobs`), or re-request the action without the deferral |
| `CrashLoopBackOff`                        | Application error on startup                                 | Check pod logs with `kubectl logs <pod-name> --previous`                                     |
| Upgrade stuck in `Reconciling`            | Operator unable to complete reconciliation                   | Check operator logs, then try Force reconcile                                                |

### Upgrade-specific issues

| Issue                                  | Cause                                                                                                  | Fix                                                                                                       |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
| Pods not restarting after upgrade      | Old pods still running                                                                                 | `kubectl rollout restart deployment <name> -n rootcause`                                                  |
| LiteLLM models missing after reinstall | `spec.config.dependenciesConfig.litellm.config` empty in the CR (e.g., CR restored from an old backup) | Re-add models on the Admin UI **LLM** page — they are stored in the CR and re-rendered on every reconcile |
| Configuration errors after upgrade     | New chart version has different value schema                                                           | Check `status.lastError`, update wizard fields to match new schema                                        |

***

## Quick reference: useful commands

```bash
# Get Admin UI master password
kubectl get secret rootcause-bootstrap-auth -n rootcause \
  -o jsonpath='{.data.ADMIN_PASSWORD}' | base64 -d

# Get LiteLLM master password
kubectl get secret rootcause-dependencies-litellm-secrets \
  -n rootcause -o jsonpath='{.data.LITELLM_MASTER_KEY}' | base64 -d

# Export CR spec (backup your configuration)
kubectl get rootcauseinstallation rootcause -n rootcause -o yaml > rc-backup.yaml

# Watch all pods
kubectl get pods -n rootcause -w

# Check installation phase
kubectl get rootcauseinstallation -n rootcause -o jsonpath='{.status.phase}'

# Force reconcile
kubectl patch rootcauseinstallation rootcause -n rootcause \
  --type=merge -p '{"spec":{"actions":{"forceReconcileNonce":"'$(uuidgen)'"}}}'

# Check events (sorted by time)
kubectl get events -n rootcause --sort-by='.lastTimestamp'
```


