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

# Logic Engine

> The visual rule builder behind dynamic tags, computed columns and Custom Vitals, with AI Composer and the AI Transform node

Available on

Custom Vitals need Protect.

The **Logic Engine** is a visual rule builder, and it's a generic capability with three jobs:

* **Automatic tag membership** — decide which devices or users carry a [tag](https://docs.threataware.com/tags.md)
* **Dynamic columns** — compute a new column value on the Devices grid (see [Dynamic columns and AI Transform](#dynamic-columns-and-ai-transform))
* **Custom Vitals** (Protect only) — your own compliance checks, which flag an issue on every device that fails (see [Custom Vitals](https://docs.threataware.com/vitals-configuration.md#custom-vitals)) New in 3.3

All three are built the same way: you assemble a flow on a canvas rather than writing a query.

## How a flow works

![Logic Engine canvas for the APAC tag — a Device source node feeding two Condition nodes (Tags NOT Contains End-User, then Longitude NOT Greater than 60), ending in an Apply Tag: APAC node, with a Draft/Published toggle](https://mintcdn.com/threatawareltd/2TtU6nxy23lvBRte/images/core/logic-engine-tag-flow.png?fit=max\&auto=format\&n=2TtU6nxy23lvBRte\&q=85\&s=661e339f36829877b0882644d9b28b28)

A flow reads top to bottom:

1. A **source** node — the `Device` or `User` record being evaluated
2. One or more **Condition** nodes — each tests a property against one or more values and branches **True** / **False**
3. Optional **Transform** nodes that derive a new value along the way
4. An **output** node — **Apply Tag** for a tag, **Output** for a column, or **Flag Issue** for a Custom Vital

Each flow has a **Draft** and a **Published** state, so a half-built rule never goes live until you click **Publish**.

### Nodes

Add a node from the palette on the left of the canvas, or click **+** under a node's **True** or **False** output.

| Node | What it does |
| - | - |
| **Condition** | Tests one property. Properties are grouped by source, such as Device, User, Microsoft Intune or Qualys |
| **Any Group** / **All Group** | Holds several conditions and passes when any of them, or all of them, are true |
| **Output** | Ends a column flow with the value to write |
| **Transform** | Maps one value to another, such as a source system's status codes to readable labels |
| **AI Transform** | Asks an AI model to derive a value from the fields you pass it. See [The AI Transform node](#the-ai-transform-node) |
| **Code Transform** | Derives a value with a short TypeScript function, for logic that's precise but awkward to build from conditions |

### Operators

A Condition can use **Equals**, **Contains**, **Starts with**, **Ends with** or **Is empty**, and number properties add **Greater than**. Turn on **NOT** to invert the test. You can enter more than one value, and the condition matches if any of them match.

> [!NOTE]
>
> The Logic Engine is **not** the [query language](https://docs.threataware.com/query-language.md). The query bar finds devices on the grid, and has wildcards for partial matches. The Logic Engine builds the rules behind tags, columns and Custom Vitals, with operators such as **Greater than** and branching logic the query bar doesn't have.

## Build and test a flow

Right-click the canvas for the editing tools:

* **Debug** — pick a device or user and the flow highlights the path it takes, so you can see which output it reaches before you publish
* **Auto Layout** and **Fit View** — tidy the flow and bring it all into view
* **Insert Node**, **Copy** / **Paste** and **Undo** / **Redo**
* **Add Note** and **Show Notes** — leave an explanation on the canvas for whoever edits the flow next
* **Show Minimap** and **Show Node IDs** — find your way around a large flow

Always run **Debug** against a device or user you expect to match, and one you don't, before you click **Publish**.

## AI Composer

New in 3.3 **Composer** is available wherever you use the Logic Engine: tags, dynamic columns and [Custom Vitals](https://docs.threataware.com/vitals-configuration.md#custom-vitals). Describe the logic you need in plain English and Composer builds the flow for you, from a single condition to multi-branch rules with transformations. It's the quickest way to get a working flow, and you don't need to know which node or operator to use.

**1. Open Composer**

Open the Logic Engine for a tag, column or Custom Vital and make sure the editor is on **Draft**. Composer opens in the panel on the right; toggle it with the Composer icon in the top bar.

**2. Describe what you want**

For example: "Build a flow that tags devices as 'Encrypted' if Jamf or Intune reports encryption enabled."

**3. Review and refine**

Composer adds the nodes to the canvas. Check them, ask Composer for changes or edit the nodes by hand, and test with **Debug** before you click **Publish**.

> [!NOTE]
>
> Composer only works on a draft, and only one person can edit a flow at a time. Depending on your plan, requests may use AI credits; the panel shows your usage.

## Live re-evaluation

A published flow keeps itself up to date. When a device's or user's details change in a source system, it joins or leaves the tag, column value or Custom Vital result automatically. There's nothing to refresh by hand.

> [!NOTE]
>
> Device rules and user rules are evaluated separately. A tag's count in **Settings → Tags** includes inactive devices, so it can be higher than the number you see on the Devices grid with its default **Active** filter.

## Dynamic columns and AI Transform

The Logic Engine's other job is building **dynamic columns** on the Devices grid. Open the columns panel (**Toggle columns**, or <kbd>⇧</kbd> <kbd>C</kbd>) and click **Open Column Editor**. Columns under the **Logic Engine** heading are computed by a flow rather than read from an integration; click **+ Add Column** to create one. The flow is the same shape as a tag flow, but it ends in an **Output** node instead of **Apply Tag**:

1. A **source** node (the device record) supplies fields
2. **Condition** and **Transform** nodes derive a value
3. An **Output** node writes the result into the column

For example, a **Risk** column can send devices through a few conditions to Outputs of Critical, High, Medium or Low, and a **Device Type** column can sort devices into types from their OS and hardware details.

### The AI Transform node

An **AI Transform** node sends the device fields you reference to an AI model with a natural-language prompt, and writes the model's answer into the column. Use it for *fuzzy* classification — judgements that are hard to express as a chain of conditions.

A simple example is an **AI Device type** column. Its flow is `Device → AI Transform → Output`:

![AI Device type column flow — a Device source node feeding an AI Transform node whose prompt classifies Workstation/Server/Unknown from the OsName and Model fields, ending in an Output node named aiTransform1](https://mintcdn.com/threatawareltd/S07xRpOM8Bx9QzyY/images/core/logic-engine-ai-transform.png?fit=max\&auto=format\&n=S07xRpOM8Bx9QzyY\&q=85\&s=c973fbdfe8b620635bdf921f528cabd7)

Its AI Transform node uses a prompt like:

```text theme={null}
Based on the following data, determine to the best of your ability
whether the device is a "Workstation" or a "Server" and output the type.
If you are unable to tell within a high degree of accuracy, then please
output "Unknown".

OS: OsName
Model: Model
```

The source node supplies `OsName` and `Model`, the prompt references them, and the result — `Workstation`, `Server`, or `Unknown` — populates the column.

### When to use AI Transform vs a Condition flow

| Use a Condition flow | Use AI Transform |
| - | - |
| The logic is deterministic (field comparisons you can enumerate) | The input is messy free text or model strings that don't map cleanly |
| Every case is knowable up front | The set of inputs is open-ended (e.g. thousands of distinct `Model` strings) |
| You need instant, predictable results | A best-effort classification is acceptable |

Prefer plain Condition nodes whenever the logic *can* be expressed as field comparisons — they're faster, free, and fully predictable. Reach for AI Transform only when conditions would be brittle.

### Best-practice prompt patterns

> **Constrain the output to a fixed set**
>
> Tell the model exactly which values it may return. The AI Device type column returns only `Workstation`, `Server`, or `Unknown` — never free prose. A bounded output keeps the column filterable and safe to build saved views, Vitals, and Actions on.

> **Always give an explicit 'Unknown' fallback**
>
> *"If you are unable to tell within a high degree of accuracy, output Unknown."* Without this the model guesses, and a confident-but-wrong value is worse than an honest gap. You can then filter the column for `Unknown` to measure how much you're relying on the model.

> **Reference only the fields that matter**
>
> Pass the smallest set of fields that answers the question (here, `OsName` + `Model`). Extra fields add noise and processing cost without improving the judgement.

> **Validate in Draft before publishing**
>
> Use the flow's **Debug** option to run it against a real device and check the output. Keep the column in **Draft** until the results look right, then **Publish**.

> **Re-check coverage after publishing**
>
> Sort or filter on the new column and confirm the distribution is sane — a large `Unknown` share usually means the prompt needs more context or a sharper instruction.

> [!NOTE]
>
> Unlike [Reporting](https://docs.threataware.com/reporting.md) — where the AI sees only the schema — an AI Transform sends the **actual values** of the fields you reference to the model. Reference only fields you're comfortable processing this way, and don't pipe sensitive identifiers into the prompt.

### What you can build with it

AI Transform is good at turning **messy, open-ended input** — model strings, hostnames, job titles, OS builds — into a **clean, filterable value** that drives tags, Vitals, Actions, and saved views. Each example below follows the same safe pattern: reference a few fields, constrain the output, and give an `Unknown` escape hatch.

**Spot unsupported operating systems.** A condition can match the OS name, but it can't know *which* builds are past vendor support — that's world knowledge a rule can't hold.

```text theme={null}
Using the OS name and build below, classify the operating system's
vendor support status. Output exactly one of: "Supported",
"Approaching end-of-life", "Unsupported", or "Unknown".

OS: OsName
Build: OS Build
```

Feed the column into an `Unsupported-OS` tag and a [Tracked View](https://docs.threataware.com/tracked-views.md) to drive the upgrade project. *Sense-check the model's verdict against your own end-of-life calendar before relying on it for compliance.*

**Decode your hostname naming convention.** Most estates encode site, role, or build year in device names — but every org's scheme differs, so a fixed pattern needs hand-coding for each one. Describe the scheme in plain English instead:

```text theme={null}
Device names follow the pattern <SITE>-<FLOOR>-<ASSETID>,
e.g. "ACS-31-0G29W" is site "ACS", floor "31". Output just the
site code, or "Unknown" if the name doesn't match the pattern.

Name: Name
```

Now you can tag and report by site without touching your naming convention or your CMDB.

**Flag hardware due for refresh.** Knowing that a "ProBook 640 G2" is years past its prime is world knowledge. AI Transform reads the make and model and tiers it:

```text theme={null}
Based on the manufacturer and model, estimate where this hardware
sits in its lifecycle. Output one of: "Current", "Due for refresh",
"End-of-life", or "Unknown".

Manufacturer: Manufacturer
Model: Model
```

Sort the column and you have a refresh-budget candidate list in one click.

**Tag VIP devices from the user's role.** The same role can have many job titles, such as "CRO", "Chief Revenue Officer", "VP Sales" and "Head of Revenue". Rather than maintain a list, let the model read the intent:

```text theme={null}
Decide whether the primary user is a senior executive or VIP, based
on their job title and department. Output "VIP" or "Standard".

Job title: JobTitle
Department: Department
```

Tag the `VIP` results, then filter Vitals and Tracked Views to that tag so you can keep a closer eye on those devices.

**Canonicalise messy vendor names.** `"Dell Inc."`, `"Dell Incorporated"`, and `"DELL"` are three values for one vendor. Collapse them for clean grouping and reporting:

```text theme={null}
Normalise the manufacturer below to a single canonical brand
(e.g. "Dell", "HP", "Lenovo", "Apple", "Microsoft"). If it doesn't
match a known hardware vendor, output "Other".

Manufacturer: Manufacturer
```

The common thread: each of these would be brittle or impossible as a fixed rule, because the input is unbounded free text or the judgement needs outside knowledge. That's the sweet spot for AI Transform — and because every output is a constrained value, the column stays as filterable and dependable as any raw field.

## Cross-references

> **[Tags](https://docs.threataware.com/tags.md)**
>
> Tag design and strategy

> **[Custom Vitals](https://docs.threataware.com/vitals-configuration.md#custom-vitals)**
>
> Build your own compliance checks

> **[Query Language](https://docs.threataware.com/query-language.md)**
>
> Grid search syntax — separate from the Logic Engine


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