Flow design patterns, node organization, error handling, and optimization strategies
Master the art of building effective, maintainable, and performant Flow Agents with proven patterns and strategies used by top developers on the Hamsa platform.
Each node should have one primary purpose:❌ Multi-Purpose Node (Avoid):
Copy
Ask AI
Node: "Handle Everything" Message: "Tell me your account number, the issue you're having, when it started, and what you've tried so far" # Too much at once - overwhelming for user and AI
✅ Single-Purpose Nodes (Preferred):
Copy
Ask AI
Node 1: "Collect Account Number" Message: "Please provide your account number"Node 2: "Describe Issue" Message: "What issue are you experiencing?"Node 3: "When Started" Message: "When did this issue begin?"Node 4: "Previous Attempts" Message: "What have you tried so far?"
Global Nodes (Always Available): - "Transfer to Agent" (trigger: "speak to human" OR DTMF: 0) - "Main Menu" (trigger: "main menu" OR DTMF: 9) - "End Call" (trigger: "end call" OR DTMF: #) - "Help" (trigger: "help" OR DTMF: *)Announcements: Welcome Message: "...You can press 0 at any time to speak with an agent." Every Menu: "...or press 9 to return to the main menu."
❌ Conflicting Transitions:- Natural: "User wants help" (priority: 100)- Natural: "User needs assistance" (priority: 100)✅ Distinct Transitions:- Natural: "User wants to speak with a human agent" (priority: 200)- Natural: "User wants to return to the main menu" (priority: 100)
Node: "Collect Account Number" (Attempt 1) Message: "Please provide your account number" Transitions: - Equation: account_number_valid == true → Verify_Account - Equation: retry_count < 3 → Retry_with_Help - Always → Transfer_to_AgentNode: "Retry Account Number" (Attempt 2) Message: "I didn't get a valid account number. It should be 8 digits. You can say them one at a time or all together." # Provides more guidanceNode: "Final Retry" (Attempt 3) Message: "Let me transfer you to an agent who can help you look up your account." # Gives up gracefully
Node: "Before Error" Extract: - error_context_node: "Payment Processing" - error_context_data: "{{payment_amount}}" - error_timestamp: "{{current_time}}" Transitions: - Tool fails → Error_HandlerNode: "Error Handler" Message: "I encountered an issue while processing your {{error_context_data}} payment at {{error_timestamp}}. Let me get you help." # User knows exactly what went wrong
✅ Optimized (3 global nodes):- Transfer to Agent (critical)- Main Menu Return (navigation)- End Call (exit)Total: 3 × 300ms = 900ms max overhead per turn❌ Slow (10 global nodes):- Transfer to Sales Agent- Transfer to Support Agent- Transfer to Billing Agent- Transfer to Tech Support- Main Menu- Help- End Call- Cancel Process- Repeat Last- Account InfoTotal: 10 × 300ms = 3000ms (3 seconds!) overhead per turn
❌ Sequential (slow):Tool Node 1: "Get Account Info" → 2 seconds → Go to next nodeTool Node 2: "Get Payment History" → 2 seconds → Go to next nodeTotal: 4 seconds✅ Parallel (fast):Tool Node: "Get All Data" Tool 1: Get Account Info Tool 2: Get Payment History Execute in parallel → 2 secondsTotal: 2 seconds
Node: "Main Menu" Message: "Press 1 for Billing, 2 for Support, or describe your issue" Transitions: - DTMF: 1 → Billing (instant) - DTMF: 2 → Support (instant) - Natural: categorize → Router (200-800ms)# New users can still speak naturally
❌ Robotic:"Please state your account identification number consisting of eight numerical digits."✅ Natural:"What's your account number? It should be 8 digits."
❌ Too Long:"Thank you for calling our customer support line. We really appreciate your business and want to help you today. Before we begin, I need to collect some information from you to ensure I can provide you with the best possible service. First, I'll need your account number, which you can find on your most recent statement or invoice, or in your account portal online. It should be exactly 8 digits long. Please provide that now."✅ Concise:"Thanks for calling! To help you, I'll need your 8-digit account number."
Pattern: Confirm-Correct-Proceed 1. Collect data 2. Repeat back to user 3. Ask for confirmation 4. Allow correction 5. Proceed when confirmedExample:Node: "Collect Phone Number" Extract: callback_numberNode: "Confirm Phone Number" Message: "I have {{callback_number}} as your callback number. Is that correct?" Transitions: - Natural: "yes" → Schedule_Callback - Natural: "no" → Collect_Phone_Number_Again - Always → Repeat_Confirmation
Node: "Collect Account Number" Test Cases: ✓ Valid input: "12345678" ✓ Valid input spoken: "one two three four five six seven eight" ✗ Too short: "123456" ✗ Too long: "123456789" ✗ Invalid characters: "abcd1234" ✗ Empty input: "" ✓ User doesn't know: "I don't have it" ✓ User needs help: "where do I find that?"
Test Scenarios: ✓ User speaks over agent (interrupt handling) ✓ Long silence periods (timeout behavior) ✓ Unexpected input at every node ✓ Rapid repeated inputs ✓ Very long user responses (> 1 minute) ✓ Background noise (phone quality) ✓ Multiple language switching ✓ DTMF during voice response ✓ Network interruption/reconnection
❌ Risky: Rebuild entire flow at once✅ Safe: Change one branch at a timeProcess: 1. Identify improvement area 2. Test change in snapshot 3. Deploy to production 4. Monitor for issues 5. Move to next improvement
Pattern: Duplicate flow for testing Flow A: Current version (80% of traffic) Flow B: Experimental version (20% of traffic) Monitor: - Completion rates - Average call duration - User satisfaction scores - Transfer rates If Flow B performs better: → Gradually shift traffic (50/50, then 20/80, then 100%)
Node: "Billing Help" Message: "I can help with billing. Tell me everything about your billing issue including your account number, what the charge is for, when it occurred, whether you've disputed it before, and what resolution you're looking for." Transitions: - Natural: "wants refund" → Refund_Flow - Natural: "has question" → Billing_FAQ - Natural: "wants to pay" → Payment_Flow - Natural: "dispute charge" → Dispute_Flow - Natural: "update billing info" → Update_Info - Natural: "something else" → General_Billing# - Overwhelming message (too many questions at once)# - No fallback transition
✅ After:
Copy
Ask AI
Node: "Billing Help" Message: "I can help with billing. Are you calling about a charge, payment, or billing information update?" Transitions: - Natural: "charge or dispute" → Charge_Router (priority: 200) - Natural: "payment" → Payment_Flow (priority: 200) - Natural: "update info" → Update_Info (priority: 200) - Always → Billing_Clarification (priority: 0)Charge_Router: Transitions: - Natural: "wants refund" → Refund_Flow - Natural: "wants to dispute" → Dispute_Flow - Always → General_Charge_Help# - Focused question (one thing at a time)# - Fallback transition (safer)