Overview
Router nodes perform pure conditional logic routing without having any conversation. They instantly evaluate conditions based on variables and data, then transition to the appropriate next node. Think of router nodes as the “if/else” or “switch/case” statements of your flow.
Key characteristic: Router nodes execute instantly—no conversation, no waiting for user input, just logic evaluation and immediate transition.
When to Use
Use router nodes to:
- Route based on extracted data: Direct flow based on account status, tier, location
- Implement business logic: Different paths for different customer segments
- Create decision trees: Multi-branch routing based on multiple conditions
- Handle tool responses: Route based on API results
- A/B test flows: Split traffic between different conversation paths
- Time-based routing: Different flows for business hours vs after hours
- Priority routing: High-value leads to different paths
Use Router Node when:
- Decision is based on variables/data, not conversation
- You need multiple conditional branches
- Logic is deterministic (not LLM-based)
- Instant routing without user interaction
Use Conversation Node instead when:
- Need to ask questions to determine next step
- Decision requires conversation context
- Want natural language understanding
Core Configuration
Router nodes have minimal configuration—they’re pure routing logic.
{
type: "router",
label?: string,
description?: string,
// Router nodes only have transitions
// No conversation, no tools, no settings
transitions: Transition[] // At least one required
}
The power of router nodes is entirely in their transitions. All logic is defined through transition conditions.
Transition Types
Router nodes support structured equation and always transitions. Natural language transitions are not typically used (no conversation to evaluate).
Structured Equation Transitions
Define logical conditions using variables and operators.
Simple Condition
Router Node: Check_Account_Status
transitions:
- Equation: {{account_status}} == "active" → Active_Flow
- Equation: {{account_status}} == "suspended" → Suspended_Flow
- Equation: {{account_status}} == "closed" → Closed_Flow
- Always → Unknown_Status_Flow
Multiple Conditions (AND Logic)
All conditions must be true.
Router Node: Qualify_Lead
transitions:
- Structured Equation (logic: all):
- {{budget}} >= 5000
- {{is_decision_maker}} == true
- {{timeline}} == "immediate"
→ High_Priority_Sales
- Structured Equation (logic: all):
- {{budget}} >= 1000
- {{budget}} < 5000
→ Medium_Priority
- Always → Low_Priority
Multiple Conditions (OR Logic)
Any condition can be true.
Router Node: Emergency_Check
transitions:
- Structured Equation (logic: any):
- {{urgency_level}} == "critical"
- {{is_emergency}} == true
- {{priority_customer}} == true
→ Immediate_Escalation
- Always → Standard_Process
Always Transition
Fallback when no other conditions match.
Router Node: Category_Router
transitions:
- Equation: {{category}} == "sales" → Sales_Flow
- Equation: {{category}} == "support" → Support_Flow
- Equation: {{category}} == "billing" → Billing_Flow
- Always → General_Flow # Catch-all for unknown categories
Always include an “always” transition as a fallback. Router nodes without a matching transition will cause flow errors.
Operators
Use these operators in equation conditions:
| Operator | Description | Example |
|---|
== | Equals | {{status}} == "active" |
!= | Not equals | {{status}} != "suspended" |
> | Greater than | {{age}} > 18 |
< | Less than | {{balance}} < 0 |
>= | Greater than or equal | {{score}} >= 80 |
<= | Less than or equal | {{items}} <= 5 |
contains | String contains | {{email}} contains "@gmail.com" |
not_contains | String doesn’t contain | {{phone}} not_contains "+1" |
Comparison Examples
String comparison:
{{customer_tier}} == "premium"
{{location}} == "USA"
{{status}} != "inactive"
Numeric comparison:
{{order_total}} >= 100
{{quantity}} > 0
{{discount_percentage}} <= 20
Boolean comparison:
{{is_verified}} == true
{{has_subscription}} == false
Contains:
{{email}} contains "@company.com"
{{full_name}} contains "Smith"
{{phone}} not_contains "+1"
Use Cases & Examples
Example 1: Account Status Routing
Scenario: Different flows for different account statuses.
# Previous node extracts account_status
Tool Node: Lookup_Account
outputMapping:
account_status: $.status
transitions:
- Always → Status_Router
Router Node: Status_Router
label: "Route by account status"
transitions:
- Equation: {{account_status}} == "active"
→ Active_Account_Flow
- Equation: {{account_status}} == "suspended"
→ Reactivation_Flow
- Equation: {{account_status}} == "trial"
→ Trial_Extension_Flow
- Equation: {{account_status}} == "cancelled"
→ Win_Back_Flow
- Always → New_Customer_Flow
Example 2: Budget-Based Lead Qualification
Scenario: Route leads to different sales tiers based on budget.
Conversation Node: Qualify_Budget
message: "What's your budget range for this project?"
extractVariables:
- budget_amount: "Extract budget in dollars"
transitions:
- Always → Budget_Router
Router Node: Budget_Router
transitions:
- Equation: {{budget_amount}} >= 50000
→ Enterprise_Sales_Team
- Structured Equation (logic: all):
- {{budget_amount}} >= 10000
- {{budget_amount}} < 50000
→ Mid_Market_Team
- Structured Equation (logic: all):
- {{budget_amount}} >= 1000
- {{budget_amount}} < 10000
→ Small_Business_Team
- Always → Self_Service_Flow
Example 3: Time-Based Routing
Scenario: Different flows for business hours vs after hours.
Router Node: Time_Router
label: "Route based on business hours"
transitions:
- Structured Equation (logic: all):
- {{current_hour}} >= 9
- {{current_hour}} < 17
- {{current_day_of_week}} != "Saturday"
- {{current_day_of_week}} != "Sunday"
→ Business_Hours_Flow
- Always → After_Hours_Flow
Example 4: Geographic Routing
Scenario: Route to region-specific agents.
Router Node: Region_Router
transitions:
- Structured Equation (logic: any):
- {{caller_state}} == "CA"
- {{caller_state}} == "OR"
- {{caller_state}} == "WA"
→ West_Coast_Team
- Structured Equation (logic: any):
- {{caller_state}} == "NY"
- {{caller_state}} == "NJ"
- {{caller_state}} == "CT"
→ East_Coast_Team
- Always → National_Team
Example 5: Customer Tier & Purchase History
Scenario: VIP treatment for premium customers with purchase history.
Tool Node: Lookup_Customer
outputMapping:
membership_tier: $.tier
lifetime_value: $.lifetime_value
last_purchase_days: $.days_since_purchase
transitions:
- Always → Customer_Router
Router Node: Customer_Router
transitions:
# VIP path: Premium tier AND high lifetime value
- Structured Equation (logic: all):
- {{membership_tier}} == "premium"
- {{lifetime_value}} >= 10000
→ VIP_Concierge_Service
# Loyal path: Recent purchase
- Equation: {{last_purchase_days}} <= 30
→ Active_Customer_Flow
# Win-back path: No recent purchase
- Structured Equation (logic: all):
- {{last_purchase_days}} > 90
- {{membership_tier}} != "cancelled"
→ Reactivation_Campaign
# Default path
- Always → Standard_Service
Example 6: Multi-Factor Lead Scoring
Scenario: Complex lead scoring with multiple factors.
Conversation Node: Qualify_Lead
extractVariables:
- company_size: "Number of employees"
- budget_range: "Annual budget"
- timeline: "When to start"
- decision_maker: "Are they the decision maker"
transitions:
- Always → Lead_Score_Router
Router Node: Lead_Score_Router
# High-priority leads
transitions:
- Structured Equation (logic: all):
- {{company_size}} >= 100
- {{budget_range}} >= 50000
- {{timeline}} == "immediate"
- {{decision_maker}} == true
→ Hot_Lead_Immediate_Transfer
# Medium-priority leads
- Structured Equation (logic: all):
- {{company_size}} >= 20
- {{budget_range}} >= 10000
- {{decision_maker}} == true
→ Warm_Lead_Schedule_Demo
# Low-priority leads
- Structured Equation (logic: any):
- {{company_size}} < 20
- {{budget_range}} < 10000
- {{decision_maker}} == false
→ Nurture_Campaign
# Unqualified
- Always → Self_Service_Resources
Example 7: Inventory-Based Routing
Scenario: Different flows based on product availability.
Tool Node: Check_Inventory
outputMapping:
stock_quantity: $.available
next_shipment_days: $.next_shipment_in_days
transitions:
- Always → Inventory_Router
Router Node: Inventory_Router
transitions:
# In stock
- Equation: {{stock_quantity}} > 0
→ Process_Order
# Out of stock but coming soon
- Structured Equation (logic: all):
- {{stock_quantity}} == 0
- {{next_shipment_days}} <= 7
→ Backorder_Option
# Out of stock, long wait
- Structured Equation (logic: all):
- {{stock_quantity}} == 0
- {{next_shipment_days}} > 7
→ Suggest_Alternatives
# Unknown availability
- Always → Manual_Check_Flow
Example 8: Payment Status Routing
Scenario: Handle different payment outcomes.
Tool Node: Process_Payment
outputMapping:
payment_status: $.status
decline_reason: $.decline_reason
transitions:
- Always → Payment_Router
Router Node: Payment_Router
transitions:
- Equation: {{payment_status}} == "succeeded"
→ Payment_Success_Flow
- Equation: {{payment_status}} == "insufficient_funds"
→ Insufficient_Funds_Flow
- Equation: {{payment_status}} == "card_declined"
→ Card_Declined_Flow
- Equation: {{payment_status}} == "requires_authentication"
→ 3DS_Authentication_Flow
- Always → Payment_Error_Flow
Advanced Patterns
Nested Routers
Chain multiple routers for complex decision trees.
Router Node: Primary_Router
transitions:
- Equation: {{customer_type}} == "business"
→ Business_Size_Router
- Equation: {{customer_type}} == "individual"
→ Individual_Income_Router
- Always → Unknown_Router
Router Node: Business_Size_Router
transitions:
- Equation: {{company_size}} >= 1000
→ Enterprise_Flow
- Equation: {{company_size}} >= 100
→ Mid_Market_Flow
- Always → Small_Business_Flow
Router Node: Individual_Income_Router
transitions:
- Equation: {{annual_income}} >= 100000
→ High_Net_Worth_Flow
- Always → Standard_Individual_Flow
Router + Conversation Hybrid
Use routers to branch, then personalize with conversation.
Router Node: Tier_Router
transitions:
- Equation: {{tier}} == "premium"
→ Premium_Greeting
- Always → Standard_Greeting
Conversation Node: Premium_Greeting
message: "Welcome back, {{name}}! As a premium member, you have priority access to our specialists."
Conversation Node: Standard_Greeting
message: "Thanks for calling! How can I help you today?"
A/B Testing
Split traffic randomly or by criteria for testing.
Router Node: AB_Test_Router
label: "50/50 split for testing new flow"
transitions:
# Use session_id hash or random value to split
- Equation: {{session_id}} contains "a"
→ Flow_Variant_A
- Equation: {{session_id}} contains "b"
→ Flow_Variant_B
- Always → Flow_Variant_A
Priority Escalation
Route urgent cases immediately.
Router Node: Priority_Router
transitions:
# Critical priority
- Structured Equation (logic: any):
- {{urgency}} == "critical"
- {{account_value}} >= 100000
- {{is_escalation}} == true
→ Immediate_Human_Transfer
# High priority
- Structured Equation (logic: all):
- {{urgency}} == "high"
- {{issue_complexity}} == "complex"
→ Senior_Agent_Queue
# Standard
- Always → Standard_Support_Flow
Flow Examples
Example Flow 1: Customer Service Routing
Example Flow 2: Lead Qualification
Example Flow 3: Nested Decision Tree
Best Practices
✅ Do’s
Always include fallback transitions
Router Node:
transitions:
- Equation: {{status}} == "A" → Path_A
- Equation: {{status}} == "B" → Path_B
- Always → Default_Path # ✅ Fallback for unknown values
Use descriptive labels
Router Node: Customer_Tier_Router
label: "Route based on membership tier and lifetime value"
# Not: "Router_1"
Group related conditions
# ✅ Good: Logical grouping
- Structured Equation (logic: all):
- {{tier}} == "premium"
- {{lifetime_value}} >= 10000
→ VIP_Flow
# vs scattered conditions
Order transitions by priority
# Most specific/important first
transitions:
- High priority condition → Critical_Path
- Medium priority → Standard_Path
- Always → Fallback
Test all paths
- Verify every transition works
- Test edge cases
- Ensure fallback handles unexpected values
Use routers for data-based decisions
# ✅ Good: Data-driven
Router based on {{account_status}}
# ❌ Bad: Should use conversation node
Router based on user's spoken words
❌ Don’ts
Don’t skip the always transition
# ❌ Bad: No fallback
Router Node:
transitions:
- Equation: {{type}} == "A" → Path_A
- Equation: {{type}} == "B" → Path_B
# What happens if type is "C"? Flow breaks!
# ✅ Good: Has fallback
Router Node:
transitions:
- Equation: {{type}} == "A" → Path_A
- Equation: {{type}} == "B" → Path_B
- Always → Unknown_Type_Handler
Don’t use routers for conversation-based logic
# ❌ Bad: Needs conversation to determine
Router based on "what user wants"
# ✅ Good: Use conversation node with transitions
Conversation node: "How can I help?"
transitions:
- Natural Language: "wants sales" → Sales
Don’t make overly complex conditions
# ❌ Too complex
- Structured Equation (logic: all):
- {{a}} > 5
- {{b}} < 10
- {{c}} == "x"
- {{d}} != "y"
- {{e}} >= 3
→ Complex_Path
# ✅ Better: Split into multiple routers
Don’t route on undefined variables
# ❌ Bad: Variable might not exist
- Equation: {{undefined_var}} == "value"
# ✅ Good: Ensure variable exists first
Tool Node: Extract_Data
outputMapping:
my_var: $.field
→ Router_Using_My_Var
Don’t create unreachable paths
# ❌ Bad: Second condition never reached
transitions:
- Equation: {{status}} == "active" → Active
- Always → Default # This always fires!
- Equation: {{status}} == "inactive" → Inactive # Never reached!
# ✅ Good: All before always
transitions:
- Equation: {{status}} == "active" → Active
- Equation: {{status}} == "inactive" → Inactive
- Always → Default
Troubleshooting
Issue: Router always takes the same path
Possible causes:
- Variable not being set correctly
- Variable value is different than expected
- Always transition is first (catches everything)
Solution:
- Check variable extraction in previous nodes
- Debug variable values using test calls
- Verify transition order (always should be last)
- Add logging to see actual variable values
Issue: Flow gets stuck at router
Possible causes:
- No transition matches and no always fallback
- Variable doesn’t exist
- Condition syntax error
Solution:
- Always add an “always” transition
- Verify variables exist before router
- Check condition syntax
- Test with various input values
Issue: Wrong path being taken
Possible causes:
- Variable type mismatch (string vs number)
- Unexpected variable value
- Condition logic error
Solution:
- Check variable data types
- Use correct comparison operators
- Test conditions independently
- Review extracted variable values
Issue: Cannot reference variable in router
Possible causes:
- Variable not extracted yet
- Variable name typo
- Wrong variable scope
Solution:
- Ensure variable is extracted before router
- Check variable name spelling:
{{exact_name}}
- Verify variable is in scope
- Review flow order
Router nodes are extremely fast:
- No LLM calls: Pure logic evaluation
- No API requests: Local computation
- Instant transitions: Sub-millisecond routing
- Efficient: Minimal resource usage
Best practices for performance:
- Use routers for high-volume routing
- Prefer routers over conversation nodes for data-based decisions
- Keep condition logic simple for fastest evaluation
- Order transitions with most likely first
Schema Reference
{
type: "router",
label?: string, // Optional display label
description?: string, // Optional internal description
// Router nodes are pure logic - minimal config
// All behavior is defined through transitions
transitions: Array<{
id: string,
name?: string,
priority: number, // Higher = evaluated first
isEnabled: boolean,
condition: {
type: "structured_equation" | "always",
// For structured_equation
logic?: "all" | "any", // AND or OR
conditions?: Array<{
variable: string,
operator: "equals" | "not_equals" | "greater_than" |
"less_than" | "greater_than_or_equal" |
"less_than_or_equal" | "contains" | "not_contains",
value: string | number | boolean
}>,
// For always
description?: string
},
targetNodeId: string
}>,
position: { x: number, y: number }
}
Next Steps