Purpose
The Condition node evaluates a condition and routes the workflow to one of several branches. Each branch names a target activity to jump to, so a condition can send execution forward to different paths, or back to an earlier node to retry a step. Only one branch is chosen per evaluation. Condition nodes are the decision points in your workflows. They enable dynamic routing based on runtime data, creating adaptive workflows that respond to different scenarios intelligently.How conditions work
When execution reaches a Condition node:1
Evaluate the condition
The condition is evaluated against the variable store and produces a result, a boolean, a label, or a raw value depending on the condition type.
2
Match a branch
The result is matched against the node’s branches. Each branch has a
label and a goto (the id of the activity to jump to). If nothing matches and a default_branch is set, that branch is used.3
Jump to the target
The workflow jumps to the matched branch’s
goto activity. Only one branch is taken; the others are not run.4
Continue from the target
Execution continues from the target activity. If the target sits earlier in the workflow, the jump forms a loop (see Loops).
Condition nodes enable dynamic, adaptive workflows. The same workflow definition can handle different scenarios by routing through different branches based on runtime data.
Configuration
A Condition node is configured with acondition_type, the fields that type needs, and a list of branches.
Condition types
There are three condition types, set bycondition_type:
- variable
- llm
- expression
Compare a single value from the variable store against a fixed value using an operator. This is the default type.
variable_path is a plain dot-path (not a {{...}} template). See Referencing data.Branches and goto
Every condition lists one or morebranches. Each branch has:
label— the value this branch matches.goto— the id of the activity to jump to when this branch is chosen.value(optional) — an explicit value to match instead of the label.
- variable conditions with a boolean result match the
true/falselabels (alsoyes/noand1/0). With thematchoperator, the raw value is compared directly against the labels for multi-way routing. - llm conditions match the label the model returned.
- expression conditions match
true/false.
Default branch
default_branch names the label to fall back to when nothing matches. Without a default and with no match, the node fails, so set a default whenever a condition might not match cleanly (missing data, an unexpected LLM label).
Referencing data in conditions
Conditions read from the variable store using dot-paths, not{{...}} templates.
For a variable condition, variable_path starts with a scope:
- Activity outputs are stored flat under the activity’s id. Reference a field as
activity_id.field, notactivity_id.output.field. - Trigger and user input live in the
inputscope (input.field), execution context in thesystemscope (system.field). - Descend into nested objects with dots, and into list elements by numeric index:
plan.steps.0.action.
input and variables, so an activity output is reached as variables.activity_id.field and execution input as input.field.
For an llm condition, llm_prompt uses {{path}} templates (for example {{input.message}}), which follow the same scope names.
Operator reference
Forcondition_type: "variable", operator selects how the resolved variable_path value is compared with compare_value:
There is no regex operator.
match routes on the raw value; it does not match a pattern. Equality and numeric operators coerce types where sensible (for example 10 == "10", "5" > 3), but greater_than / less_than on non-numeric values fail the node.Loops (route back to an earlier node)
A branch whosegoto points at an earlier activity forms a loop. Use it to retry a step, refine a search, or keep iterating until a result is good enough, then exit.
Building a retry loop
The pattern is: do work, verify it, then a condition either exits or loops back.false back to the first step and true to the end:
verify.gap), which is empty on the first pass and refined on later passes, so each retry searches differently.
The bounded-exit branch
Loops are bounded so they can’t run forever. Two fields make the exit explicit and graceful:max_loops— the maximum number of times this condition may take a backward edge. After the budget is spent, the runtime stops looping.loop_exit_branch— the branchlabelto route through oncemax_loopsis reached. This lets a budget-stopped loop finish through a real branch (typically the one that leads to an END node) with normal output formatting, instead of erroring.
loop_exit_branch must be one of the node’s branch labels, and setting max_loops requires loop_exit_branch. Both are validated at save time and re-checked at runtime.
The safety cap
Even withoutmax_loops, every backward edge is bounded so a stuck loop can’t drain the workflow:
- A conditional with
max_loopsexits through itsloop_exit_branch(or, if that can’t be resolved, the terminal END node) once the budget is spent. - Any other backward edge (a raw
nextcycle, or a conditional with no budget) is capped atMAX_LOOPBACKS_PER_EDGE(default 25, env-configurable) traversals of the same edge, then routed through END. - As a final catch-all, the whole workflow is capped at
MAX_WORKFLOW_ITERATIONS(1000) activity steps.
(source activity, goto target). If no END node is reachable when a loop is stopped, the run finishes softly with a success result flagged loop_budget_exceeded.
Examples
Let’s look at practical Condition nodes in real workflows.Example 1: Confidence-based routing
Scenario: Route documents to auto-processing or human review based on a confidence score.auto-process; low-confidence documents route to human-review, balancing speed with accuracy.
Example 2: Document type routing
Scenario: Route to different processors based on document type, usingmatch for multi-way routing.
document_type value is matched directly against the branch labels, so each document type gets its own path.
Example 3: Intent routing with an LLM
Scenario: Send a message to the right handler based on what it’s about.Example 4: Multi-factor escalation
Scenario: Escalate only when several factors line up, using an expression.Example 5: Retry until satisfied
Scenario: Keep refining until a verifier is happy, then exit. See Loops.Advanced patterns
If-else-if chains
Chain Condition nodes so afalse branch leads to the next condition:
Condition with a fallback
Verify a step succeeded before continuing, and route failures to a human:Condition with parallel branches
Route into a Parallel node when multi-agent analysis is needed:Best practices
Keep conditions simple and readable
Keep conditions simple and readable
Complex expressions are hard to debug. Break complex logic into a chain of simple Condition nodes rather than one giant expression.
Check data exists before comparing
Check data exists before comparing
A missing value can make a comparison fail the node. Use the
exists operator (or gate on a value the upstream activity is guaranteed to set) before comparing.Always set a default branch
Always set a default branch
Set
default_branch whenever a condition might not match cleanly, especially for llm conditions where the model could return an unexpected label. Without a default, an unmatched result fails the node.Bound every loop deliberately
Bound every loop deliberately
When a branch routes backward, set
max_loops and a loop_exit_branch that reaches an END node, so the loop exits gracefully with a real result rather than hitting the global safety cap.Use descriptive branch labels
Use descriptive branch labels
For multi-way (
match / llm) routing, name branches after what they mean (passport, complaint) so the workflow reads clearly.Test every branch
Test every branch
Test with data that triggers each branch, including the default and the loop-exit path. Don’t just test the happy path.
Next steps
Human task node
Add human approval in conditional branches
Parallel node
Combine conditions with parallel execution
Memory system
Understand the variable store conditions read from
Agent node
Use agent outputs as condition inputs