Skip to main content
Transitions define when and how the conversation moves from one node to another. Each node can have multiple transitions; they are evaluated by priority (highest first) and the first matching transition fires.

Transition Types

TypeEvaluationUse Case
Natural LanguageLLM-basedIntent detection, sentiment
Structured EquationRule-basedVariable comparisons, thresholds
DTMFKeypad inputIVR menus, quick selection
AlwaysNo conditionFallback / default path

Priority

Each transition has a numeric priority. Higher values are evaluated first. When multiple transitions have the same priority, their order is indeterminate. Default priorities if not set manually:
  • Natural Language: 100
  • Structured Equation: 200
  • DTMF: 300
  • Always: 0
Set priorities explicitly when you need a specific evaluation order.
Always include an Always transition as a fallback. If no transitions match, the conversation stalls.

Natural Language Transitions

The LLM evaluates whether the condition (prompt) is met based on the user’s input and conversation context.

Configuration

{
  type: 'natural_language',
  prompt: string,       // Condition description (required)
  description?: string
}

Examples

Prompt: "The user wants to speak with a human agent"
→ Target: Transfer_to_Agent

Prompt: "The user is asking about billing or payment issues"
→ Target: Billing_Department

Prompt: "The user agrees or says yes"
→ Target: Confirm_Path

Prompt: "The user declines or says no"
→ Target: Alternative_Path
Write conditions that describe user intent, not exact phrases. “The user wants to speak with a human” matches “get me an agent”, “transfer me”, “I need a person”, etc.

Structured Equation Transitions

Equation transitions evaluate variable conditions using rule-based logic — no LLM involved.

Configuration

{
  type: 'structured_equation',
  logic: 'all' | 'any',    // AND or OR
  conditions: Array<{
    variable: string,
    operator: Operator,
    value: string | number | boolean,
    description?: string
  }>,
  description?: string
}

Operators

OperatorDescription
equalsExact match
not_equalsNot equal
greater_thanNumeric
less_thanNumeric
greater_than_or_equalNumeric
less_than_or_equalNumeric
containsString contains substring
not_containsString does not contain
existsVariable has any value
not_existsVariable is null/undefined

Examples

Single condition:
Variable: account_status
Operator: equals
Value: 'active'
→ Target: Active_Account_Path
AND logic (all conditions must pass):
Logic: all
Conditions:
  - account_balance > 1000
  - account_type equals "premium"
→ Target: VIP_Path
OR logic (any condition passes):
Logic: any
Conditions:
  - support_tier equals "platinum"
  - is_enterprise equals true
→ Target: Priority_Support
Existence check:
Variable: customer_id
Operator: exists
→ Target: Known_Customer_Path
Hamsa handles type coercion automatically — a string "25" compared to number 21 with greater_than evaluates correctly.

DTMF Transitions

DTMF transitions fire when the user presses a specific keypad key. → See DTMF Features for full documentation on all DTMF capabilities.

Configuration

{
  type: 'dtmf',
  key: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '*' | '#',
  description?: string
}

Example

Conversation Node: "Main Menu"
Message: "Press 1 for Sales, Press 2 for Support, Press 3 for Billing"
Transitions:
  - DTMF: key=1 → Sales_Department
  - DTMF: key=2 → Support_Department
  - DTMF: key=3 → Billing_Department
  - Always → Repeat_Menu

Always Transitions

Always transitions have no condition — they fire when no other transition matches. Use them as the fallback on every node that has conditional transitions.

Configuration

{
  type: 'always',
  description: string
}

Examples

Menu fallback:
Transitions:
  - DTMF: key=1 → Sales
  - DTMF: key=2 → Support
  - Always → Repeat_Menu   # User didn't press a valid key
Router else path:
Transitions:
  - Equation: account_type equals "premium" → Premium_Flow
  - Equation: account_type equals "standard" → Standard_Flow
  - Always → Basic_Flow
Always transitions should have the lowest priority (default 0) so they are evaluated last.

Advanced Patterns

Combining types

Node: "Support Menu"
Message: "Describe your issue, or press 0 for an agent"
Transitions:
  - DTMF: key=0 → Transfer_Agent      (priority: 1000)
  - Natural: "urgent issue" → Urgent  (priority: 200)
  - Natural: "billing" → Billing      (priority: 200)
  - Always → General_Inquiry          (priority: 0)

Loops with exit conditions

Node: "Collect Account Number"
Message: "Please provide your 8-digit account number"
Transitions:
  - Equation: account_number.length equals 8 → Proceed  (priority: 200)
  - Natural: "speak to agent" → Transfer                 (priority: 150)
  - Equation: attempt_count >= 3 → Max_Attempts          (priority: 100)
  - Always → Retry_Input                                 (priority: 0)

Time-based routing

Router Node: "Hours Check"
Transitions:
  - Logic: all
    Conditions:
      - current_hour >= 9
      - current_hour < 17
    Target: Business_Hours_Flow    (priority: 200)
  - Always → After_Hours_Flow      (priority: 0)

Validation

The flow builder validates transitions before deployment:
  • All transitions have non-empty conditions
  • Target nodes exist
  • Every non-terminal node has at least one transition
  • DTMF keys are valid (0–9, *, #)
  • Warning if no Always transition (routing may stall)

Transition Schema

interface Transition {
  id: string;
  name?: string;
  condition:
    | NaturalLanguageCondition
    | StructuredEquationCondition
    | DTMFCondition
    | AlwaysCondition;
  targetNodeId: string;
  priority: number;
  isEnabled: boolean;
}

Next Steps

Global Nodes

Nodes reachable from anywhere in the flow

DTMF Features

Full keypad interaction documentation

Variables

Variables used in equation conditions

Router Node

Pure routing without conversation