Skip to main content

Your First Rule

Let’s build a simple rule that calculates whether a customer qualifies for a discount. This tutorial will teach you the basics of facts, rules, and outcomes.
What you’ll learn: By the end of this guide, you’ll understand how to create facts, write rules, and test your logic in the Flow Debugger.

Step 1: Understanding the Problem

Imagine you run an online store with this discount policy:
  • Orders over $100 get 10% off
  • Orders under $100 get no discount
Let’s build a rule to calculate this automatically.

Step 2: Define Your Facts

Facts are your input data - the information your rules will evaluate. For our discount rule, we need to know the order total.
{
  "orderTotal.value": 120
}
Key concept: Facts are a flat key-value object. The keys (like "orderTotal.value") are what you’ll reference in your rules using @fact:. The values can be static data or variable mapping expressions like "$.previous_step.data" to pull data from other steps in your flow.

Facts with Variable Mapping

In a real flow, you’d typically map facts from previous steps using variable mapping:
{
  "orderTotal.value": "$.checkout_step.total",
  "customerTier.value": "$.customer_lookup.tier",
  "orderItems.value": "$.cart_step.items"
}
When the Rules step runs, these variable mapping expressions are resolved to actual values before rules are evaluated.

Step 3: Write Your Rule

Now let’s create a rule that checks if the order qualifies for a discount:
{
  "qualifiesForDiscount.value": {
    "operator": ">=",
    "input": ["@fact:orderTotal.value", 100]
  }
}

Breaking Down the Rule

1

Rule Name

qualifiesForDiscount.value - The full unique name for this rule. The .value suffix is just a naming convention to create unique keys
2

Operator

>= means “greater than or equal to”
3

Input

Compare @fact:orderTotal.value (120) against 100
4

Result

Returns true if condition is met, false otherwise
The @fact: syntax is how you reference data from your facts. Think of it as saying “grab the value from the orderTotal fact”.

Step 4: Add the Rules Step to Your Flow

  1. Open your flow in the Flow Builder
  2. Click Add Step
  3. Select Rules from the available steps
  4. Configure the step:
    • Facts: Map from a previous step using $.previous_step_id or paste your test facts
    • Rules: Paste the rule JSON above
Rules step configuration

Step 5: Test Your Rule

Use the Flow Debugger to test with different values:
Input Facts:
{
  "orderTotal.value": 120
}
Expected Output:
{
  "qualifiesForDiscount.value": true
}
✅ Order total is ≥ $100, so discount applies

Step 6: Calculate the Discount Amount

Now let’s extend our rule to calculate the actual discount amount using conditional logic:
{
  "qualifiesForDiscount.value": {
    "operator": ">=",
    "input": ["@fact:orderTotal.value", 100]
  },
  "discountAmount.value": [
    {
      "condition": {
        "operator": "=",
        "input": ["@fact:qualifiesForDiscount.value", true]
      },
      "outcome": {
        "operator": "*",
        "input": ["@fact:orderTotal.value", 0.10]
      }
    },
    {
      "outcome": 0
    }
  ],
  "finalPrice.value": {
    "operator": "-",
    "input": [
      "@fact:orderTotal.value",
      "@fact:discountAmount.value"
    ]
  }
}
Notice how rules reference each other: The discountAmount rule uses @fact:qualifiesForDiscount.value to check the outcome of the first rule. The .value is part of the rule’s unique name, not a special property.

Understanding Conditional Rules

The discountAmount rule uses the conditional format - an array of condition/outcome pairs:
1

First condition

If qualifiesForDiscount is true, calculate 10% of order total
2

Default outcome

If no conditions match, return 0 (no discount)

Test the Complete Rule

Input:
{
  "orderTotal.value": 120
}
Output:
{
  "qualifiesForDiscount.value": true,
  "discountAmount.value": 12,
  "finalPrice.value": 108
}
Perfect! $120 order gets $12 off (10%), resulting in a final price of $108.

Common Patterns You Just Learned

Comparison

Using operators like >=, <, = to compare values

Conditional Logic

If-then-else using condition/outcome arrays

Calculations

Math operations like * and -

Rule References

Rules can reference other rules with @fact:ruleName.property where the property is part of the unique name

Common Beginner Mistakes

Forgetting the @fact: prefix
// ❌ Wrong
"input": ["orderTotal.value", 100]

// ✅ Correct
"input": ["@fact:orderTotal.value", 100]
Inconsistent property naming
// ❌ Confusing - mixing naming conventions
"qualifiesForDiscount": { ... }
"discountAmount.value": { ... }

// ✅ Better - consistent naming convention
"qualifiesForDiscount.value": { ... }
"discountAmount.value": { ... }
Using consistent property suffixes (like .value) makes your rules easier to read and maintain.
Using “inputs” instead of “input”
// ❌ Wrong
"inputs": ["@fact:orderTotal.value", 100]

// ✅ Correct
"input": ["@fact:orderTotal.value", 100]
Forgetting default outcome in conditional rules
// ❌ Incomplete - no default
"discount.value": [
  {
    "condition": { ... },
    "outcome": 0.1
  }
]

// ✅ Complete - has default
"discount.value": [
  {
    "condition": { ... },
    "outcome": 0.1
  },
  {
    "outcome": 0
  }
]

What’s Next?

Quick Reference

Simple Rule Structure

{
  "ruleName.value": {
    "operator": "operatorName",
    "input": [/* values to evaluate */]
  }
}

Conditional Rule Structure

{
  "ruleName.value": [
    {
      "condition": {
        "operator": "operatorName",
        "input": [...]
      },
      "outcome": "result if condition is true"
    },
    {
      "outcome": "default result"
    }
  ]
}

Referencing Facts and Rules

"@fact:factName.value"        // Reference a fact (value is part of fact name)
"@fact:ruleName.value"        // Reference another rule's outcome
"@fact:orderTotal.formatted"  // Different property = different unique key
The property suffix (like .value, .formatted) is just part of the unique name - use different suffixes when you want multiple calculations from the same data.

Common Operators

OperatorPurposeExample
=Equals{"operator": "=", "input": ["@fact:status.value", "active"]}
>=Greater than or equal{"operator": ">=", "input": ["@fact:age.value", 18]}
<Less than{"operator": "<", "input": ["@fact:price.value", 100]}
+Addition{"operator": "+", "input": [10, 20]}
*Multiplication{"operator": "*", "input": ["@fact:price.value", 0.9]}
andBoolean AND{"operator": "and", "input": [condition1, condition2]}
orBoolean OR{"operator": "or", "input": [condition1, condition2]}
Pro tip: Start with simple rules and test them individually before combining into complex logic. Use consistent property naming (like .value) throughout your rules for clarity.
Need Help? Visit our Help Center or join the Community for support.