If
Conditional branching based on expressions
The If node creates conditional branches in your workflow. Based on a CEL expression, data flows to either the "true" or "false" output, enabling different processing paths.
Overview
| Property | Value |
|---|---|
| Category | Control |
| Node ID | ds.if.perItem.in1.success2.error0 |
| Input Ports | 1 |
| Success Outputs | 2 (true, false) |
| Error Outputs | 0 |
| Execution Mode | Per-item |
Configuration
| Parameter | Type | Required | Description |
|---|---|---|---|
expr | CEL Expression | Yes | Boolean condition to evaluate |
Expression Parameter
A CEL expression that evaluates to true or false:
json.score > 0.8
json.sentiment == "positive"
json.attendees.size() > 3
How It Works
[If: expr?]
├─ True (Output 1) ──→ [Path A]
└─ False (Output 2) ─→ [Path B]
- Input data arrives at the If node
- The
expris evaluated with the input data - If
true: data flows to the first output (true branch) - If
false: data flows to the second output (false branch) - Only ONE branch executes per item
Input Schema
Accepts any data from upstream. Access it via json in the expression.
Output Schema
Both outputs pass through the same input data unchanged:
// Input (same for both outputs)
{
"meeting": { "title": "Q1 Review" },
"score": 0.85,
"sentiment": "positive"
}
The data is not modified—it's routed to the appropriate branch.
Examples
Basic Example: High Score Filter
Route based on a score threshold.
Configuration:
Expression: json.score > 0.8
Workflow:
[AI: Score meeting]
↓
[If: json.score > 0.8]
├─ True ──→ [Slack: "High priority!"]
└─ False ─→ [Email: "Regular follow-up"]
Example: Check for Existence
Route based on whether data exists.
Expression: has(json.callRecording) && json.callRecording.transcript != ""
Workflow:
[Load Meeting]
↓
[If: has transcript?]
├─ True ──→ [AI: Analyze transcript]
└─ False ─→ [Slack: "No transcript available"] → [Sink]
Example: String Comparison
Route based on classification result.
Expression: json.classification == "urgent"
Workflow:
[AI: Classify urgency]
↓
[If: json.classification == "urgent"]
├─ True ──→ [SMS + Slack]
└─ False ─→ [Email only]
Example: Numeric Range
Handle multiple conditions with nested If nodes.
Workflow:
[AI: Score deal]
↓
[If: json.score >= 0.8]
├─ True ──→ [Handle High Score]
└─ False ─→ [If: json.score >= 0.5]
├─ True ──→ [Handle Medium Score]
└─ False ─→ [Handle Low Score]
Example: Array Size Check
Route based on number of items.
Expression: json.actionItems.size() > 0
Workflow:
[AI: Extract action items]
↓
[If: json.actionItems.size() > 0]
├─ True ──→ [Create Tasks]
└─ False ─→ [Sink]
Example: Complex Conditions
Combine multiple conditions.
Expression: json.sentiment == "negative" && json.score < 0.3
Workflow:
[AI: Analyze meeting]
↓
[If: negative AND low score?]
├─ True ──→ [Alert Manager] → [Create Risk Task]
└─ False ─→ [Standard Processing]
CEL Expression Reference
Comparison Operators
| Operator | Meaning | Example |
|---|---|---|
== | Equals | json.status == "active" |
!= | Not equals | json.status != "closed" |
> | Greater than | json.score > 0.5 |
>= | Greater or equal | json.count >= 10 |
< | Less than | json.priority < 3 |
<= | Less or equal | json.age <= 30 |
Logical Operators
| Operator | Meaning | Example |
|---|---|---|
&& | AND | json.a > 1 && json.b < 5 |
|| | OR | json.x == 1 || json.y == 2 |
! | NOT | !json.processed |
String Operations
| Expression | Description |
|---|---|
json.name.startsWith("A") | Starts with |
json.name.endsWith("z") | Ends with |
json.name.contains("abc") | Contains substring |
json.name.matches("^[A-Z].*") | Regex match |
Array/List Operations
| Expression | Description |
|---|---|
json.items.size() | Array length |
json.items.size() > 0 | Has items |
"a" in json.tags | Contains element |
Null/Existence Checks
| Expression | Description |
|---|---|
has(json.field) | Field exists |
json.field != null | Not null |
json.field ?? "default" | Default if null |
Best Practices
1. Always Connect Both Outputs
Every If node should have both branches connected:
✅ Good:
[If]
├─ True ──→ [Action]
└─ False ─→ [Sink]
❌ Bad:
[If]
├─ True ──→ [Action]
└─ False ─→ (disconnected)
2. Check for Existence Before Access
Prevent errors by checking if data exists:
✅ Safe:
has(json.callRecording) && json.callRecording.transcript != ""
❌ Risky:
json.callRecording.transcript != "" // May error if callRecording is null
3. Use Clear Condition Names
Consider what each branch means:
[If: is_urgent?] ← Clear meaning
├─ True ──→ [Urgent Handler]
└─ False ─→ [Normal Handler]
4. Keep Conditions Simple
For complex logic, compute upstream:
✅ Better:
[AI: Classify] → [If: json.class == "A"]
❌ Complex:
[If: (json.a > 5 && json.b < 3) || (json.c == "x" && json.d.size() > 2)]
5. Handle Edge Cases
Think about what happens for unexpected values:
// What if score is null?
json.score > 0.8 // May error
// Safer:
has(json.score) && json.score > 0.8
Common Issues
Expression evaluation error
Symptom: Node fails with evaluation error
Cause: Accessing field that doesn't exist
Solution: Use has() to check existence:
has(json.field) && json.field == "value"
Wrong branch executing
Symptom: Data goes to unexpected branch
Cause: Expression logic error
Solution:
- Check the expression carefully
- Log the input data to verify values
- Test with known inputs
Neither branch executing
Symptom: Workflow seems stuck
Cause: Expression throws error (execution fails)
Solution: Review expression for null access errors
Related Nodes
- Sink - Terminate false branches gracefully
- AI Prompt - Generate classification for routing
- Zip - Merge branches back together
Technical Details
Evaluation
The expression is evaluated using CEL (Common Expression Language):
- Type-safe evaluation
- Null-safe with
has()checks - Supports complex expressions
Execution Mode
Per-item mode means:
- Each input item is evaluated separately
- Different items can route to different branches
- 5 items might result in 3 true + 2 false
Output Port Order
- Output 1 (index 0): True branch
- Output 2 (index 1): False branch
The visual order in the UI should match: top/left = true, bottom/right = false.