Workflows

DMN Decision Tables

Model business rules as DMN decision tables — inputs, outputs, and FEEL rules with standard hit policies — then call them from a workflow (a business-rule task) or as a decision-as-a-service API. A spreadsheet-style editor with a live test panel, reusable across every process.

Some logic doesn't belong in a script — it's a decision. What risk tier is this change? How many approvals does it need? Which remediation applies to this alert? DMN (Decision Model and Notation) is the OMG standard for exactly this: a decision table with typed inputs, outputs, and rules. Versus implements it, so you can model a rule once, test it live, and reuse it from any workflow — or call it directly as an API.

This is part of BPMN Process Orchestration.

The decision-table editor — a change-risk table with FEEL rules and a live Test panel returning risk=high, approvals=2

Anatomy of a decision table

Workflows → Decisions lists your tables and opens the editor. A table has three parts:

  • Inputs (blue columns) — each is a FEEL expression over the context, e.g. vip_count or in_window. These produce the values the rules test.
  • Outputs (amber columns) — the named results the decision returns, e.g. risk, approvals_required.
  • Rules (rows) — each cell under an input is a FEEL unary test; each cell under an output is a FEEL expression. A rule fires when all its input tests pass, and then its output expressions produce the result.

Input cells are unary tests

CellMeaning
-any value (always matches)
> 50comparison (< <= > >= = !=)
"high", "critical"a disjunction (matches either)
[1..50]a range — [ ] inclusive, ( ) exclusive
not(...)negation
"prod" / 0equality against a literal

Output cells are plain FEEL expressions — "high", 2, or something computed like vip_count * 2.

Hit policies

The hit policy decides what happens when more than one rule matches:

  • Unique — exactly one rule may match (an error otherwise).
  • First — take the first matching rule (rules are ordered).
  • Priority / Any — priority ordering / all matches must agree.
  • Collect — return every match; Collect (sum / min / max / count) aggregate the outputs.

The change-risk example

The table above classifies a network change's risk from the number of affected VIPs and whether it runs inside the approved window:

VIPs affectedIn window→RiskApprovals
> 50false"high"2
> 50true"medium"1
[1..50]-"low"0
--"none"0

Evaluate { "vip_count": 80, "in_window": false } and it returns { risk: "high", approvals_required: 2 }.

Test it live

The Test panel in the editor lets you feed a JSON context and evaluate the table immediately — you see the outputs, the matched rules, and whether it was a single hit. No workflow, no deploy: edit a rule, hit Evaluate, and confirm the behavior before anyone depends on it.

Two ways to use a decision

1. Inside a workflow — a business-rule task. Add a node of type business-rule task and point it at a decision key. When a run reaches it, Versus evaluates the table over the run context and merges the outputs back into the context — so the very next gateway can route on risk, or a later step can read approvals_required. A decision becomes a first-class step in the process.

2. As a service — the decision API. POST /api/decisions/{key}/evaluate/ with a JSON context returns the outputs. Any part of Versus — or an external system — can ask a governed, versioned decision "what should happen here?" without embedding the rules. Real uses: change-risk scoring, upgrade-eligibility checks, alert-to-remediation mapping, firewall-rule risk classification.

Because the same FEEL engine powers both decision tables and gateway conditions, the rules you write in one place read exactly the same in the other.