Conditional Triggers & Conditions
This guide explains how to use the Conditional Triggers in Project Succession and how to write conditions for dynamic workflow automation.
Overview
Project Succession includes three powerful conditional triggers that let you create workflows based on custom conditions:
- Conditional Polling Trigger - Poll any data source and evaluate complex conditions
- Threshold Monitor Trigger - Monitor numeric values and fire on threshold crossings
- State Change Trigger - Detect changes in any value type over time
Data Sources
All conditional triggers can fetch data from the following sources:
File
Read and parse files in various formats.
{
"type": "File",
"path": "C:/path/to/file.json",
"format": "json"
}
Supported formats:
json- JSON filesyaml- YAML filesxml- XML filesini- INI/configuration filestext- Plain text files
HTTP Endpoint
Make HTTP requests to APIs or web services.
{
"type": "HttpEndpoint",
"url": "https://api.example.com/data",
"method": "GET",
"headers": {
"Authorization": "Bearer token123"
},
"body": null
}
Supported methods: GET, POST, PUT, DELETE, PATCH
Command
Execute shell commands and capture their output.
{
"type": "Command",
"command": "git",
"args": ["status", "--porcelain"]
}
System Metric
Monitor system resources.
{
"type": "SystemMetric",
"metric": {
"type": "CpuUsage"
}
}
Available metrics:
CpuUsage- Current CPU usage percentageMemoryUsage- Used memory in bytesMemoryTotal- Total memory in bytesDiskSpace- Free disk space:{"type": "DiskSpace", "path": "C:"}DiskUsagePercent- Disk usage percentage:{"type": "DiskUsagePercent", "path": "C:"}
Environment Variable
Read environment variables.
{
"type": "EnvironmentVariable",
"name": "PATH"
}
Writing Conditions
Conditions are written in JSON format and define the logic that determines when a trigger fires.
Basic Structure
{
"op": "OperatorName",
"left": { "type": "JsonPath", "value": "$.temperature" },
"right": { "type": "Number", "value": 30 }
}
Condition Values
Values in conditions can be:
String
{ "type": "String", "value": "hello" }
Number
{ "type": "Number", "value": 42.5 }
Boolean
{ "type": "Bool", "value": true }
JsonPath
Access nested data using JSONPath notation.
{ "type": "JsonPath", "value": "$.cpu.usage" }
JSONPath Examples:
$- Root element$.field- Access field$.nested.field- Access nested field$.array[0]- Access array element$.items[*].name- Access all names in array
Null
{ "type": "Null" }
Comparison Operators
Equals
Check if two values are equal.
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.status" },
"right": { "type": "String", "value": "completed" }
}
NotEquals
Check if two values are different.
{
"op": "NotEquals",
"left": { "type": "JsonPath", "value": "$.error" },
"right": { "type": "Null" }
}
GreaterThan
Check if left value is greater than right value (numeric).
{
"op": "GreaterThan",
"left": { "type": "JsonPath", "value": "$.temperature" },
"right": { "type": "Number", "value": 25.0 }
}
LessThan
Check if left value is less than right value (numeric).
{
"op": "LessThan",
"left": { "type": "JsonPath", "value": "$.memory_usage" },
"right": { "type": "Number", "value": 80 }
}
GreaterOrEqual
Check if left value is greater than or equal to right value.
{
"op": "GreaterOrEqual",
"left": { "type": "JsonPath", "value": "$.version" },
"right": { "type": "Number", "value": 2.0 }
}
LessOrEqual
Check if left value is less than or equal to right value.
{
"op": "LessOrEqual",
"left": { "type": "JsonPath", "value": "$.disk_free" },
"right": { "type": "Number", "value": 1000000 }
}
String/Array Operators
Contains
Check if a string contains a substring, array contains an element, or object contains a key.
String contains:
{
"op": "Contains",
"haystack": { "type": "JsonPath", "value": "$.filename" },
"needle": { "type": "String", "value": ".jpg" }
}
Array contains:
{
"op": "Contains",
"haystack": { "type": "JsonPath", "value": "$.tags" },
"needle": { "type": "String", "value": "urgent" }
}
Matches
Match a string against a regular expression.
{
"op": "Matches",
"value": { "type": "JsonPath", "value": "$.email" },
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
Common regex patterns:
- Email:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ - URL:
^https?://.* - IP Address:
^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$ - File extension:
\.jpg$(ends with .jpg)
Logical Operators
And
All conditions must be true.
{
"op": "And",
"conditions": [
{
"op": "GreaterThan",
"left": { "type": "JsonPath", "value": "$.temperature" },
"right": { "type": "Number", "value": 20 }
},
{
"op": "LessThan",
"left": { "type": "JsonPath", "value": "$.temperature" },
"right": { "type": "Number", "value": 30 }
}
]
}
Or
At least one condition must be true.
{
"op": "Or",
"conditions": [
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.status" },
"right": { "type": "String", "value": "error" }
},
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.status" },
"right": { "type": "String", "value": "failed" }
}
]
}
Not
Inverts the condition result.
{
"op": "Not",
"condition": {
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.enabled" },
"right": { "type": "Bool", "value": false }
}
}
Complete Examples
Example 1: CPU Monitoring
Data Source:
{
"type": "SystemMetric",
"metric": { "type": "CpuUsage" }
}
Condition: Fire when CPU usage is above 80%
{
"op": "GreaterThan",
"left": { "type": "JsonPath", "value": "$" },
"right": { "type": "Number", "value": 80.0 }
}
Example 2: API Monitoring
Data Source:
{
"type": "HttpEndpoint",
"url": "https://api.example.com/health",
"method": "GET"
}
Condition: Fire when status is not “healthy”
{
"op": "NotEquals",
"left": { "type": "JsonPath", "value": "$.status" },
"right": { "type": "String", "value": "healthy" }
}
Example 3: File Processing
Data Source:
{
"type": "File",
"path": "C:/renders/status.json",
"format": "json"
}
Condition: Fire when render is complete and no errors
{
"op": "And",
"conditions": [
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.render.status" },
"right": { "type": "String", "value": "complete" }
},
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.render.error_count" },
"right": { "type": "Number", "value": 0 }
}
]
}
Example 4: Complex Business Logic
Data Source:
{
"type": "HttpEndpoint",
"url": "https://api.example.com/orders",
"method": "GET"
}
Condition: Fire when there are urgent orders from premium customers
{
"op": "And",
"conditions": [
{
"op": "GreaterThan",
"left": { "type": "JsonPath", "value": "$.pending_orders" },
"right": { "type": "Number", "value": 0 }
},
{
"op": "Or",
"conditions": [
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.priority" },
"right": { "type": "String", "value": "urgent" }
},
{
"op": "Equals",
"left": { "type": "JsonPath", "value": "$.customer_tier" },
"right": { "type": "String", "value": "premium" }
}
]
}
]
}
Trigger-Specific Features
Conditional Polling Trigger
Fire Modes:
- Always - Fire every time the condition is true
- OnChange - Fire when condition becomes true (false→true), including first poll if condition is initially true
- OnEdge - Fire only when changing from false to true (excludes first poll, waits for an actual transition)
Example Configuration:
- Poll Interval: 60 seconds
- Fire Mode: OnEdge (only fire when condition becomes true)
- Initial Delay: 0 seconds
Threshold Monitor Trigger
Simplified numeric monitoring with specialized features.
Trigger Modes:
- OnCross - Fire when threshold is crossed in either direction
- WhileTrue - Fire continuously while above/below threshold
- OnEnter - Fire only when entering threshold zone (false→true)
- OnExit - Fire only when exiting threshold zone (true→false)
Hysteresis: Prevents rapid firing when value fluctuates around threshold.
- Threshold: 100
- Hysteresis: 5
- Fires at: 100 (going up)
- Resets at: 95 (going down)
State Change Trigger
Change Detection Modes:
- Any - Fire on any value change
- Specific - Fire only when changing from/to specific values
- Pattern - Fire when new value matches a regex pattern
Additional Options:
- Ignore First Poll (default: true) - Don’t fire on the first poll since there’s no previous state to compare against. Set to false if you want to fire immediately when a specific value is detected, even on startup.
Tips & Best Practices
1. Start Simple
Begin with simple conditions and add complexity as needed:
{
"op": "GreaterThan",
"left": { "type": "JsonPath", "value": "$.value" },
"right": { "type": "Number", "value": 100 }
}
2. Test JSONPath
Use the JSONPath $ to access the root, then build up:
- Start:
$ - Add field:
$.temperature - Add nested:
$.system.cpu.usage
3. Use Fire Modes Wisely
- Always: Continuous monitoring - fires every poll while condition is true (e.g., “CPU is high” alerts)
- OnChange: Transition detection with first-poll support - fires when condition becomes true, including initial state (e.g., “service became available”)
- OnEdge: Pure edge detection - fires only on false→true transitions, ignoring first poll (e.g., “new error appeared” alerts)
4. Combine Triggers
Use multiple triggers for different aspects:
- Threshold Monitor for numeric values
- State Change for status tracking
- Conditional Polling for complex logic
5. Poll Interval Considerations
- Frequent (5-30s): Critical systems, rapid changes
- Moderate (60-300s): Regular monitoring, API quotas
- Infrequent (300s+): Slow-changing data, resource conservation
6. Error Handling
Triggers continue polling even if:
- Data fetch fails
- Condition evaluation fails
- JSONPath returns null
Check logs for diagnostic information.
Troubleshooting
Condition Never Fires
Check:
- Data source is returning expected data
- JSONPath is correct (use
$to see full data) - Data types match (string vs number)
- Fire mode is appropriate
Fires Too Often
Solutions:
- Use OnEdge fire mode instead of Always to only fire on transitions
- Use OnChange if you want to include the first poll but still avoid continuous firing
- Add hysteresis for numeric thresholds to prevent flapping
- Increase poll interval to reduce polling frequency
- Add more specific conditions to narrow trigger criteria
Understanding Fire Modes:
- Always fires on every poll when condition is true - use only for continuous monitoring
- OnChange fires when becoming true (false→true) + first poll - good for state detection
- OnEdge fires only on transitions (false→true) - best for event detection
JSONPath Returns Null
Common issues:
- Field doesn’t exist in data
- Typo in path
- Case sensitivity
- Nested path incorrect
Solution: Start with $ and build path incrementally.
Type Mismatch Errors
Ensure value types match:
- Use
Numberfor numeric comparisons - Use
Stringfor text comparisons - Don’t compare strings with
GreaterThan
Reference
All Operators
| Operator | Types | Description |
|---|---|---|
Equals | Any | Values are equal |
NotEquals | Any | Values are different |
GreaterThan | Numeric | Left > Right |
LessThan | Numeric | Left < Right |
GreaterOrEqual | Numeric | Left >= Right |
LessOrEqual | Numeric | Left <= Right |
Contains | String/Array | Haystack contains needle |
Matches | String | Matches regex pattern |
And | Logical | All conditions true |
Or | Logical | Any condition true |
Not | Logical | Inverts result |
Value Types
| Type | Example |
|---|---|
String | {"type": "String", "value": "text"} |
Number | {"type": "Number", "value": 42.5} |
Bool | {"type": "Bool", "value": true} |
JsonPath | {"type": "JsonPath", "value": "$.field"} |
Null | {"type": "Null"} |
JSONPath Quick Reference
| Pattern | Description | Example |
|---|---|---|
$ | Root element | Entire data |
$.field | Direct field | $.name |
$.a.b.c | Nested field | $.user.profile.age |
$.array[0] | Array index | $.items[0] |
$.array[*] | All array elements | Returns array |