Keep it simple: Build linear flows with clear decision points. Avoid complex branching.Use agents for intelligence: Agent nodes handle complex conversations. Give them specific tools and clear system prompts.Route early: Filter and route conversations at the beginning. Use Send Text + Decide pattern.Functions for data: Use custom functions to fetch, process, and store data. Keep business logic out of agents.
Data collection flowUse functions to fetch user profile, order history, subscription status, and personalize the greeting.Multi-step workflowPattern: Collect user input → Process/validate → Agent interaction → Save results.
support_agent = AgentNode( id="support_agent", system_prompt="You are a technical support specialist. Help users with account issues, bugs, and technical problems. Always search for existing tickets first.", webhooks=[ FlowAgentWebhook( name="search_tickets", url="https://api.company.com/support/tickets/search", description="Search for user's existing support tickets" ), FlowAgentWebhook( name="create_ticket", url="https://api.company.com/support/tickets", http_method="POST", description="Create a new support ticket" ) ])
Design agents around the tools they need:
Customer service: User lookup, order status, refund processing
Sales: Product search, inventory check, order creation
Start flows with functions to enrich data and make smart routing decisions.User verification patternCheck if user exists in your system, then route accordingly:
Copy
flow = (Flow(name="User Verification") .add_node(StartNode(id="start")) .add_node(FunctionNode( id="check_user", function_id="verify_user_by_phone", # Use ID from kapso functions list save_response_to="user_status" )) .add_node(DecideNode( id="route_by_status", conditions=[ Condition(label="registered", description="User exists in database"), Condition(label="new", description="New user, not in database") ], provider_model_name="claude-sonnet-4-20250514" )) .add_node(AgentNode( id="existing_user_agent", system_prompt="Welcome back! You're talking to {{user_status.name}}. Help with their account.", provider_model_name="claude-sonnet-4-20250514" )) .add_node(AgentNode( id="onboarding_agent", system_prompt="Welcome! Help new users get started with account setup.", provider_model_name="claude-sonnet-4-20250514" )) .add_edge("start", "check_user") .add_edge("check_user", "route_by_status") .add_edge("route_by_status", "existing_user_agent", "registered") .add_edge("route_by_status", "onboarding_agent", "new"))
Data enrichment patternLoad user context first, then personalize everything:
Copy
flow = (Flow(name="Personalized Support") .add_node(StartNode(id="start")) .add_node(FunctionNode( id="load_context", function_id="get_user_profile", # Get ID with: kapso functions list save_response_to="profile" )) .add_node(SendTextNode( id="personalized_greeting", whatsapp_config_id="config", message=AIField(prompt="Create personalized greeting for {{profile.name}} with order history: {{profile.recent_orders}}"), provider_model_name="claude-sonnet-4-20250514" )) .add_node(WaitForResponseNode(id="wait")) .add_node(AgentNode( id="agent", system_prompt="Help {{profile.name}}. Recent orders: {{profile.recent_orders}}. Subscription: {{profile.plan}}", provider_model_name="claude-sonnet-4-20250514" )) .add_edge("start", "load_context") .add_edge("load_context", "personalized_greeting") .add_edge("personalized_greeting", "wait") .add_edge("wait", "agent", "response"))
Input validation patternValidate user input before processing:
Copy
flow = (Flow(name="Order Processing") .add_node(StartNode(id="start")) .add_node(SendTextNode(id="ask_order", message="What's your order number?")) .add_node(WaitForResponseNode(id="wait")) .add_node(FunctionNode( id="validate_order", function_id="check_order_exists", # Your deployed function ID save_response_to="order_info" )) .add_node(DecideNode( id="check_validity", conditions=[ Condition(label="valid", description="Order exists and is valid"), Condition(label="invalid", description="Order not found or invalid") ], provider_model_name="claude-sonnet-4-20250514" )) .add_node(AgentNode( id="process_order", system_prompt="Help with order {{order_info.number}}. Status: {{order_info.status}}", provider_model_name="claude-sonnet-4-20250514" )) .add_node(SendTextNode( id="order_not_found", message="Order not found. Please check the number and try again." )) .add_edge("start", "ask_order") .add_edge("ask_order", "wait") .add_edge("wait", "validate_order", "response") .add_edge("validate_order", "check_validity") .add_edge("check_validity", "process_order", "valid") .add_edge("check_validity", "order_not_found", "invalid"))