> ## Documentation Index
> Fetch the complete documentation index at: https://docs.airmdr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Facts Auto Remediation Conditions

> Configure conditions in Facts to define when an associated remediation playbook can run for an approval action. Use supported case fields and playbook inputs to control which cases meet your remediation criteria

## Overview

An auto-remediation fact associates a condition with a remediation playbook. The condition compares case attributes, supported playbook inputs, or both.

For example: `disposition_label = "Malicious" AND confidence.score > 85`

This expression matches a case when:

* The disposition is `Malicious`.
* The confidence score is greater than `85`.

The condition evaluates whether the action meets the rule. The selected playbook performs the configured work.

> [!NOTE]
>
> A matching condition does not guarantee successful execution. The playbook must also be able to start and receive its required inputs.

Use this guide to:

* Configure an auto-remediation fact in the AirMDR UI.
* Select supported fields and operators.
* Write and combine conditions.
* Reference inputs from the selected remediation playbook.
* Verify matching and nonmatching outcomes.
* Reproduce the supplied service API test using your own identifiers.

> **📋 Prerequisites**
>
> Before configuring an auto-remediation fact:
>
> * Sign in to the AirMDR organization where the fact will apply.
> * Ensure your account can access and manage Facts.
> * Identify the remediation playbook and its required inputs.
> * Identify the exact field values you want the condition to compare.
> * Prepare a test case and an appropriate test playbook.
>
> If you cannot edit a fact or select the required playbook, contact your AirMDR administrator or support contact to verify your access.

> **🤔 How to access the Facts Page?**
>
> 1. Sign in to AirMDR.
> 2. Select the appropriate organization.
> 3. In the left navigation, open **Knowledge Management** and navigate to **Facts**.
> 4. Locate the required fact using **Search facts.**
> 5. Use the available filters to narrow the results.
>
> | Control | Purpose |
> | :- | :- |
> | **Search facts** | Locate a fact using search text. |
> | **Tags** | Filter facts by their tags. |
> | **Status** | Filter facts by status. |
> | **Modified By** | Filter facts by the user who modified them. |
> | **Exclude expired** | Exclude expired facts from the displayed results. |
> | **+ Add Fact** | Start creating a fact. |
>
> The Facts list displays the following information:
>
> | Column | Information displayed |
> | :- | :- |
> | **Scope** | The scope associated with the fact. |
> | **Fact** | The fact content and associated tags. |
> | **Status** | The current fact status. |
> | **Updated** | When the fact was updated. |
> | **Modified By** | Who modified the fact. |
> | **Start Date** | The configured start date, if any. |
> | **Expires On** | The configured expiration date, if any. |
>
> Select an existing fact to open **Edit Fact**.
>
> > [!NOTE]
> >
> > If a fact is missing, check the selected organization, filters, search text, and **Exclude expired** setting.

### 📧 Step-by-Step: Configure an Auto-Remediation Fact

**1. Create or open a fact**

On the **Facts** page:

* Select **+ Add Fact** to create a fact.
* Select an existing fact to edit its configuration.

**2. Describe the intended behavior**

In **Content**, describe what the fact should allow.

For example:

> Automatically run the selected remediation playbook for malicious cases with a confidence score greater than 85.

Keep the description clear enough for another user to understand the intended behavior.

> [!NOTE]
>
> Enter the executable expression in **Condition**. Use **Content** to describe its purpose.

**3. Add the auto-remediation tag**

In **Tags**, add: `auto-remediation`

The supplied API reference and recorded auto-remediation fact use this tag.

**4. Configure the scope and dates**

Review the following fields:

| Field | Configuration |
| :- | :- |
| **Scope** | Select the appropriate available scope. The recorded example uses **Organizational**. |
| **Start Date** | Set a future start date if needed. The UI indicates that leaving this blank activates the fact immediately. |
| **Expiry Date** | Set an expiration date if needed. The UI indicates that leaving this blank applies no expiration. |

> [!TIP]
>
> For a temporary test rule, configure an expiry date.

> [!TIP]
>
> After saving, also check the fact’s status and any applicable approval requirements.

**5. Select the remediation playbook**

In the **Auto-remediation** section, select the required **Remediation Playbook**.

Review its inputs before writing a condition that references them. The available playbook input fields depend on the playbook selected for the fact.

**6. Enter the condition**

In **Condition**, enter an expression using supported fields and operators.

For example: `disposition_label = "Malicious" AND confidence.score > 85`

This condition requires both comparisons to match.

**7. Review and save**

1. Check that **Content** accurately describes the expression.
2. Verify the selected playbook.
3. Review the scope, start date, and expiry date.
4. Check field names, operators, quotation marks, and grouping.
5. Select **Save**.
6. Locate the saved fact in the Facts list.
7. Review **Status**, **Start Date**, and **Expires On**.

If the fact is **Pending**, follow your organization’s fact approval process before relying on it for automation.

**8. Verify the Outcome in the UI**

After configuring a fact:

1. Confirm that it is saved with the intended condition and remediation playbook.
2. Review its status, scope, start date, and expiration date.
3. Use a test case with known field values.
4. Ensure the relevant approval action refers to the intended playbook.
5. Check that required playbook inputs are available.
6. Open **Investigations** and inspect the relevant action in **All Actions**.
7. Review the action status and any execution or failure details.
8. Where available, inspect the **AUTO REMEDIATED** group.
9. Verify the playbook execution outcome.
10. Repeat using a case that does not satisfy the condition.

The supplied test showed the following outcomes:

| Outcome | Observation |
| :- | :- |
| Condition matched and execution succeeded | The playbook ran and the action completed. |
| Condition did not match | The action stayed open. |

An open action alone does not establish why automation did not occur. Check the condition, fact eligibility, selected playbook, required inputs, and execution details.

**Recommended verification:** Test a matching case, a nonmatching case, a threshold boundary, and a missing-value case where relevant.

### Condition Syntax

A comparison generally consists of a field, an operator, and a value: field operator value

For example: `severity_label = "High"`

> [!TIP]
>
> **Use **`AND`**, **`OR`**, **`NOT`**, and parentheses to combine comparisons.**

> **Format values correctly**
>
> | Value type | Required format | Example |
> | :- | :- | :- |
> | Text | Enclose the value in double quotes. | `severity_label = "High"` |
> | Number | Enter the number without quotes. | `confidence.score > 85` |
> | Boolean | Use `true` or `false` without quotes. | `archived = false` |
> | Time | Enter epoch seconds without quotes. | `created_at > 1759276800` |
> | Text alternatives | Use a bracketed list of quoted values. | `disposition_label in ["NoThreatFound", "NonMaliciousPositive"]` |
> | Numeric alternatives | Use a bracketed list of numbers. | `confidence.score in [85, 90, 95]` |
>
> Use the exact field paths listed in this guide. For example:
>
> * Use `severity_label` for the severity label.
> * Use `disposition_label` for the disposition label.
> * Use `confidence.score` for numeric confidence.

> **Logical operators**
>
> | Operator | Behavior | Example |
> | - | - | - |
> | `AND` | Both comparisons must match. | `severity_label = "High" AND disposition_label = "Malicious"` |
> | `OR` | At least one comparison must match. | `severity_label = "High" OR severity_label = "Medium"` |
> | `NOT` | Negates a comparison. | `NOT severity_label = "Low"` |
> | Parentheses | Group comparisons explicitly. | `(severity_label = "High" OR severity_label = "Medium") AND disposition_label = "Malicious"` |

> **Evaluation precedence**
>
> Conditions are evaluated in this order:
>
> 1. `NOT`
> 2. `AND`
> 3. `OR`
>
> Use parentheses when combining `AND` and `OR`.
>
> For example:
>
> ```text theme={null}
> (severity_label = "High" OR severity_label = "Medium")
> AND disposition_label = "Malicious"
> ```
>
> This expression requires a malicious disposition and either high or medium severity.

> **Unsupported comparison symbols**
>
> The supplied expression reference does not support:
>
> ```text theme={null}
> >=
> <=
> !=
> ```
>
> For an **integer** confidence score, express “at least 85” as: `confidence.score > 84`
>
> This replacement depends on the value being an integer; it does not provide a general greater-than-or-equal comparison for fractional values.
>
> Express “severity is not Low” as: `NOT severity_label = "Low"`
>
> > [!NOTE]
> >
> > Enter Facts expressions directly in **Condition** using the syntax shown here.

### Supported Fields and Operators

> **Operators by data type**
>
> | Data type | Supported operators |
> | - | - |
> | Text | `=`, `in`, `contains`, `starts_with`, `ends_with`, `matches`, `exists` |
> | Number | `=`, `>`, `<`, `in`, `exists` |
> | Boolean | `=`, `exists` |
> | Time in epoch seconds | `=`, `>`, `<`, `exists` |

> **Operator reference**
>
> | Operator | Purpose | Applicable types |
> | - | - | - |
> | `=` | Compare a value for equality. | Text, number, boolean, time |
> | `>` | Compare against a lower numeric or timestamp boundary. | Number, time |
> | `<` | Compare against an upper numeric or timestamp boundary. | Number, time |
> | `in` | Compare against a list of alternatives. | Text, number |
> | `contains` | Compare a portion of a text value. | Text |
> | `starts_with` | Compare the beginning of a text value. | Text |
> | `ends_with` | Compare the end of a text value. | Text |
> | `matches` | Apply a supported pattern comparison. | Text |
> | `exists` | Test field presence. | Text, number, boolean, time |

> **Supported text fields**
>
> These fields support: `=, in, contains, starts_with, ends_with, matches, exists`
>
> | Field path | Value being compared |
> | - | - |
> | `assignee.assignee_id` | Assignee identifier |
> | `assignee.assignee_type` | Assignee type |
> | `assignee.email` | Assignee email |
> | `case_detail_fields.alert_type` | Alert type |
> | `case_detail_fields.findings.risk_label` | Finding risk label |
> | `case_detail_fields.provider.display_name` | Provider display name |
> | `case_detail_fields.provider.name` | Provider name |
> | `case_detail_fields.provider.provider_id` | Provider identifier |
> | `case_id` | Display case identifier |
> | `case_uuid` | Case UUID |
> | `category` | Case category |
> | `disposition_label` | Disposition label |
> | `name` | Case name |
> | `organization_code` | Organization code |
> | `organization_id` | Organization identifier |
> | `severity_label` | Severity label |
> | `status_label` | Status label |
> | `sub_category` | Case subcategory |
>
> Example:
>
> ```text theme={null}
> case_detail_fields.provider.name = "gmail"
> AND category = "Email attacks"
> ```

> **Supported numeric fields**
>
> These fields support: `=, >, <, in, exists`
>
> | Field path | Value being compared |
> | - | - |
> | `confidence.score` | Numeric confidence score |
> | `priority` | Numeric priority value |
> | `type` | Numeric case type value |
>
> Example: `confidence.score > 85`
>
> > [!NOTE]
> >
> > The catalog identifies `priority` and `type` as numeric fields. Use their stored numeric values rather than substituting UI display labels.

> **Supported boolean fields**
>
> These fields support: `=, exists`
>
> | Field path | Value being compared |
> | - | - |
> | `archived` | Archived flag |
> | `case_reinvestigated` | Reinvestigation flag |
> | `is_agentic_case` | Agentic case flag |
> | `is_customer_request` | Customer request flag |
> | `marked_for_review` | Marked-for-review flag |
> | `reviewed` | Reviewed flag |
> | `sla_response_met` | SLA response flag |
>
> Example: `archived = false`
>
> Use lowercase `true` or `false` without quotation marks.\\

> **Supported time fields**
>
> These fields support: `=, >, <, exists`
>
> | Field path | Value being compared |
> | :- | :- |
> | `created_at` | Case creation timestamp |
> | `escalations.escalated_at` | Escalation timestamp |
> | `modified_at` | Case modification timestamp |
> | `status_modified_at` | Status modification timestamp |
>
> Example: `created_at > 1759276800`
>
> > [!NOTE]
> >
> > Enter timestamps in **epoch seconds**, rather than milliseconds or formatted date strings.

> **Missing fields**
>
> If a case does not contain a field, a comparison against that field evaluates to false.
>
> For example: `confidence.score > 85`
>
> A case without `confidence.score` does not satisfy this comparison.
>
> A condition that does not reference confidence can still match that case:
>
> ```text theme={null}
> severity_label = "High" AND disposition_label = "Malicious"
> ```
>
> Take care with negated comparisons because `NOT` reverses the comparison result. Where a rule must positively establish an attribute, use an explicit positive comparison.

> **Fields under lists**
>
> A field under a list matches when any element satisfies the comparison.
>
> Examples of supported paths under lists include:
>
> ```text theme={null}
> case_detail_fields.findings.risk_label
> escalations.escalated_at
> ```
>
> Do not assume that comparisons on different list fields must refer to the same list element unless that behavior has been confirmed.

### Use Playbook Inputs in Conditions

Conditions can reference supported inputs from the remediation playbook associated with the fact.

Use this format: `playbook.<normalized_input_name>`

> **Normalize the input name**
>
> The supplied reference specifies the following normalization:
>
> 1. Convert the input name to lowercase.
> 2. Replace each run of spaces and punctuation with one underscore.
> 3. Add the `playbook.` prefix.
>
> For example:
>
> | Playbook input name | Condition field |
> | :- | :- |
> | `Domain name` | `playbook.domain_name` |
>
> The field must correspond to an input from the selected playbook.

> **Supported input types**
>
> | Input type | Supported operators |
> | - | - |
> | `string` | `=`, `in`, `contains`, `starts_with`, `ends_with`, `matches`, `exists` |
> | `static_enum` | `=`, `in`, `contains`, `starts_with`, `ends_with`, `matches`, `exists` |
> | `variable_enum` | `=`, `in`, `contains`, `starts_with`, `ends_with`, `matches`, `exists` |
> | `list_string` | Same text operators; matches when any element satisfies the comparison. |
> | `list_static_enum` | Same text operators; matches when any element satisfies the comparison. |
> | `list_variable_enum` | Same text operators; matches when any element satisfies the comparison. |
> | `int`, `list_int` | `=`, `>`, `<`, `in`, `exists` |
> | `bool`, `list_bool` | `=`, `exists` |

> **Unsupported inputs**
>
> Conditions cannot reference:
>
> | Input type | Availability |
> | :- | :- |
> | `float` | Unsupported |
> | `schema` | Unsupported |
> | `datetime` | Unsupported |
> | Any secret input | Unsupported |
>
> The supplied reference states that a condition naming an unsupported input is rejected when the fact is saved.

> **Example using a playbook input**
>
> For a playbook containing a supported text input named **Domain name**:
>
> ```text theme={null}
> playbook.domain_name = "example.com"
> ```
>
> Combine the input with case attributes:
>
> ```text theme={null}
> disposition_label = "Malicious"
> AND confidence.score > 85
> AND playbook.domain_name = "example.com"
> ```
>
> This requires:
>
> * A malicious disposition.
>
> * Confidence greater than 85.
>
> * The playbook input to match `example.com`.
>
> > [!NOTE]
> >
> > Referencing an input in a condition does not supply its value. The required input must still be available to the playbook.

### 🛡️ Sample Tested Condition (For Reference)

> ****Example 1: Malicious cases with confidence greater than 85****
>
> ```text theme={null}
> disposition_label = "Malicious" AND confidence.score > 85
> ```
>
> | Case values | Expected result |
> | :- | :- |
> | Malicious; confidence 90 | Matches |
> | Malicious; confidence 85 | Does not match |
> | Malicious; confidence 95 | Matches |
> | Malicious; confidence missing | Does not match |
> | Another disposition; confidence 95 | Does not match |
>
> The comparison is strictly greater than 85. A score of exactly 85 is excluded.

> ****Example 2: High-severity malicious cases****
>
> ```text theme={null}
> severity_label = "High" AND disposition_label = "Malicious"
> ```
>
> | Case values | Expected result |
> | :- | :- |
> | High; Malicious | Matches |
> | Medium; Malicious | Does not match |
> | High; NoThreatFound | Does not match |
> | High; Malicious; confidence missing | Matches |
>
> Confidence does not affect this expression because it is not referenced.

> ****Example 3: Selected dispositions with confidence greater than 80****
>
> ```text theme={null}
> disposition_label in ["NoThreatFound", "NonMaliciousPositive"]
> AND confidence.score > 80
> ```
>
> | Case values | Expected result |
> | :- | :- |
> | NoThreatFound; confidence 95 | Matches |
> | NonMaliciousPositive; confidence 90 | Matches |
> | Malicious; confidence 90 | Does not match |
>
> Both listed dispositions are accepted when the confidence requirement is satisfied.

> ****Example 4: High or medium severity, malicious disposition, and confidence greater than 80****
>
> ```text theme={null}
> (severity_label = "High" OR severity_label = "Medium")
> AND disposition_label = "Malicious"
> AND confidence.score > 80
> ```
>
> | Case values | Expected result |
> | :- | :- |
> | High; Malicious; confidence 90 | Matches |
> | High; Malicious; confidence 85 | Matches |
> | Medium; Malicious; confidence 95 | Matches |
> | High; NoThreatFound; confidence 95 | Does not match |
> | High; Malicious; confidence missing | Does not match |
> | Low; NonMaliciousPositive; confidence 90 | Does not match |
>
> The parentheses ensure that the disposition and confidence requirements apply to both allowed severities.

## Additional Information

> **🧰 Troubleshooting**
>
> | Issue | Checks and corrective action |
> | - | - |
> | The fact is missing from the list. | Check the organization, search text, Tags, Status, Modified By, and Exclude expired setting. |
> | The condition cannot be saved. | Verify the field path, operator, value type, quotation marks, and parentheses. Remove unsupported comparison symbols. |
> | A playbook input is rejected. | Confirm that it belongs to the selected playbook and uses the correct normalized name. Check that its type is supported and it is not a secret input. |
> | A confidence condition does not match. | Check that confidence exists, is numeric, and satisfies the strict comparison. A value of 85 does not satisfy `> 85`. |
> | The fact is saved, but an action remains open. | Check fact status, scope, start and expiry dates, expression result, playbook association, required inputs, and processing time. |
> | A playbook cannot start or fails. | Review action and execution details. Check required inputs and playbook dependencies. |
> | The condition matches more cases than expected. | Review parentheses, `OR` grouping, list matching, negated comparisons, and actual case values. |
> | A timestamp comparison behaves unexpectedly. | Verify that the value uses epoch seconds rather than milliseconds or a formatted date. |
> | A service API request fails. | Check the approved URL, authentication instructions, access, identifiers, and request payload. Retain the response and unique request ID. |

> **🛑 Best Practices**
>
> * Start with a narrow condition and verify it against known case values.
> * Test matching and nonmatching cases.
> * Include threshold boundaries and missing values in testing.
> * Use parentheses when combining `AND` and `OR`.
> * Keep the fact description aligned with its executable condition.
> * Review playbook inputs whenever you change the selected playbook.
> * Configure expiration for temporary rules.
> * Remove test facts after testing.
> * Review execution outcomes when validating automation.

> **👉 Support & Maintenance**
>
> * 📧 Contact [**AirMDR Support**](mailto:support@airmdr.com) through your designated support channel.
>
> When requesting help, provide:
>
> | Information | Why it helps |
> | - | - |
> | Organization and fact identifier | Identifies the configuration being reviewed. |
> | Condition expression | Shows the rule being evaluated. |
> | Selected remediation playbook | Identifies the associated execution workflow. |
> | Case identifier and UUID | Identifies the affected case. |
> | Relevant case values | Allows comparison against the expression. |
> | Action and execution identifiers | Connects the condition test with the resulting execution. |
> | Request IDs for API tests | Helps trace individual requests. |
> | Error message or response | Shows the observed failure. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.