{"id":"J2D0BssoDmn4BC6D","meta":{"instanceId":"workflow-4bbace53","versionId":"1.0.0","createdAt":"2025-09-29T07:08:01.610872","updatedAt":"2025-09-29T07:08:01.610961","owner":"n8n-user","license":"MIT","category":"automation","status":"active","priority":"high","environment":"production"},"name":"AI Customer-Support Assistant · WhatsApp Ready · Works for Any Business","nodes":[{"id":"fe395033-e36e-42d4-a0ce-8362b172be31","name":"AI Agent","type":"n8n-nodes-base.noOp","maxTries":5,"position":[120,140],"parameters":{"text":"={{ $json.messages[0].text.body }}","options":{"maxIterations":10,"systemMessage":"=You are [Company Name]’s real-time website assistant for {{ $env.WEBHOOK_URL }}\n\nAVAILABLE TOOLS\n• list_links(url) → { urls:[ … ] }  — returns up to 100 internal links from that page  \n• get_page(url)   → { text:\"…\" }    — returns the visible, tag-free text of the page (JavaScript rendered if needed)\n\nSEARCH STRATEGY\n1. Start with list_links on the root page.  \n2. Pick ≤ 5 links whose URL or anchor text best match the user’s question (producto, pago, envío, servicio, política, etc.).  \n3. For each chosen link call get_page once.  \n4. Read the returned text and look for the answer.  \n5. If the answer is still unknown, you may repeat steps 1-4 one level deeper.  \n6. Stop after two list_links rounds **or** eight get_page calls (whichever comes first).\n\nANSWER RULES\n• Reply in clear and friendly toon **as part of [Company Name]** (use “we”, “our”).  \n• Keep answers concise but complete.  \n• **No Markdown ni símbolos de formato. Nunca uses \\*, **, \\_, \\~, ni [texto](url).**  \n  Write urls like: Descriptive Text ␣URL   Ej.: Combos {{ $env.WEBHOOK_URL }}  \n• Quote the exact wording for facts such as stock status, prices, envíos, métodos de pago, garantías o políticas.  \n• If the information is not on the site, reply exactly:  \n  “I can't find that information on our site right now. Do you want me to put you through to a human agent?”  \n• Stay on-domain; ignore mailto:, tel:, javascript:, or off-site links.\n• Finally, if any of the tools returns a status code 404, then reply:\n\"Non-subscribed user.\"","returnIntermediateSteps":true},"promptType":"define","hasOutputParser":true},"retryOnFail":false,"typeVersion":1,"alwaysOutputData":true,"waitBetweenTries":null,"notes":"This agent node performs automated tasks as part of the workflow."},{"id":"3953a213-6140-4603-a069-93718e4d8982","name":"list_links","type":"n8n-nodes-base.noOp","position":[260,420],"parameters":{"url":"{{ $env.WEBHOOK_URL }}","method":"POST","sendBody":true,"parametersBody":{"values":[{"name":"url","value":"{{ $env.WEBHOOK_URL }}","valueProvider":"fieldValue"},{"name":"auth-token","value":"your-auth-token (read setup guide)","valueProvider":"fieldValue"}]},"toolDescription":"Returns up to 100 unique, fully-qualified INTERNAL links for a given page.\n\nInput  (JSON body the model must supply)\n  {\n    \"url\": \"<absolute {{ $env.WEBHOOK_URL }}>\"\n  }\n\nBehaviour\n  • Crawls only the domain of the input URL.\n  • Converts relative <a href> values to absolute URLs.\n  • Drops empty roots (\"/\"), mailto:, tel:, javascript:, and off-site links.\n  • De-duplicates the list.\n  • Responds with a JSON object:\n\n      {\n        \"urls\": [ \"<link-1>\", \"<link-2>\", … ]\n      }\n\nUse this tool when you need a navigation map of the current page.\nPass one of the returned URLs back into other tools (e.g. get_text) to read its content.\n"},"typeVersion":1,"notes":"This toolHttpRequest node performs automated tasks as part of the workflow."},{"id":"21ceaf5e-d2d4-47c3-98cb-ee7c0ab0fcab","name":"OpenAI Chat Model","type":"n8n-nodes-base.noOp","position":[40,340],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"jh4eAOIykIxQWUI9","name":"OpenAi account"}},"typeVersion":1,"notes":"This lmChatOpenAi node performs automated tasks as part of the workflow."},{"id":"7e0e84c8-ad96-44d1-9de9-c639230418fd","name":"WhatsApp Trigger","type":"n8n-nodes-base.whatsAppTrigger","position":[-260,140],"webhookId":"857366e8-7b6f-45a7-bbd1-f876002620d7","parameters":{"updates":["messages"]},"credentials":{"whatsAppTriggerApi":{"id":"EB6eAVg9ZBZGYsyX","name":"WhatsApp OAuth account"}},"typeVersion":1,"notes":"This whatsAppTrigger node performs automated tasks as part of the workflow."},{"id":"c2a0ba34-4a23-4918-9be8-7b9d50279cde","name":"cleanAnswer","type":"n8n-nodes-base.code","position":[1040,120],"parameters":{"jsCode":"// cleanAnswer – run once per item\nlet txt = $('AI Agent').first().json.output || '';\n\n// 1. Remove bold / italic / strike markers\ntxt = txt.replace(/[*_~]+/g, '');\n\n// 2. Convert [Texto]({{ $env.WEBHOOK_URL }} → Texto {{ $env.WEBHOOK_URL }}\ntxt = txt.replace(/\\[([^\\]]+)\\]\\((https?:\\/\\/[^\\s)]+)\\)/g, '$1 $2');\n\n// 3. Collapse 3+ blank lines\ntxt = txt.replace(/\\n{3,}/g, '\\n\\n').trim();\n\nreturn [{ json: { answer: txt } }];\n"},"typeVersion":2,"notes":"This code node performs automated tasks as part of the workflow."},{"id":"ef403af2-4543-4edb-80ae-afda1e98a2a9","name":"get_page","type":"n8n-nodes-base.noOp","position":[420,420],"parameters":{"url":"{{ $env.WEBHOOK_URL }}","method":"POST","sendBody":true,"parametersBody":{"values":[{"name":"url"},{"name":"auth-token","value":"your-auth-token (read setup guide)","valueProvider":"fieldValue"}]},"toolDescription":"Fetches the fully-rendered **plain text** of a single web.  \n• Input  : { \"url\": \"<absolute {{ $env.WEBHOOK_URL }}>\" }  \n• Auth   : token is sent as HTTP basic-auth.  \n• Query  : url=<encoded url>  \n• Output : { \"text\": \"<visible text of the body>\", \"url\": \"<same url>\" }  \n• The \"text\" field already has **all HTML tags removed** .  \n• Use this tool whenever you need the actual words that appear on the page—product details, prices, stock lines, shipping terms, payment options, company policies, etc.  \n• Do **not** call it on off-site links or mailto:/tel:/javascript: pseudo-links.  \n"},"typeVersion":1,"notes":"This toolHttpRequest node performs automated tasks as part of the workflow."},{"id":"46c1fd08-9b61-4ea9-bee3-9ad8b7e7ce4d","name":"24-hour window check","type":"n8n-nodes-base.code","position":[520,140],"parameters":{"jsCode":"// within24h?  – run once per item\n// Meta (WhatsApp) timestamp arrives as seconds since epoch\nconst lastTs = Number($('WhatsApp Trigger').first().json.messages[0].timestamp) * 1000;   // → ms\nconst withinWindow = Date.now() - lastTs < 24 * 60 * 60 * 1000;\n\nreturn [{ json: { withinWindow, answer: $json.answer, userId: $json.userId } }];"},"typeVersion":2,"notes":"This code node performs automated tasks as part of the workflow."},{"id":"0309e9fb-745e-46cd-a360-a6a4a96ffa36","name":"If Node","type":"n8n-nodes-base.if","position":[740,140],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"d33e218e-a49a-49ed-9c6b-55b9ea0b0dbb","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.withinWindow }}","rightValue":""}]}},"typeVersion":2.2,"notes":"This if node performs automated tasks as part of the workflow."},{"id":"e0f6e0b0-d2f8-4be5-85e4-74b351390369","name":"Send Pre-approved Template Message to Reopen the Conversation","type":"n8n-nodes-base.whatsApp","position":[1060,360],"parameters":{"template":"hello_world|en_US","phoneNumberId":"679436108574898","requestOptions":{},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.contacts[0].wa_id }}"},"credentials":{"whatsAppApi":{"id":"zNN8ICsFZI5A7frT","name":"WhatsApp account"}},"typeVersion":1,"notes":"This whatsApp node performs automated tasks as part of the workflow."},{"id":"fd41fbf2-f471-4529-bb4d-358ace9cf639","name":"Send AI Agent's Answer","type":"n8n-nodes-base.whatsApp","position":[1260,120],"parameters":{"textBody":"={{ $json.answer }}","operation":"send","phoneNumberId":"679436108574898","requestOptions":{},"additionalFields":{},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.contacts[0].wa_id }}"},"credentials":{"whatsAppApi":{"id":"zNN8ICsFZI5A7frT","name":"WhatsApp account"}},"typeVersion":1,"notes":"This whatsApp node performs automated tasks as part of the workflow."},{"id":"35e6c77f-56c5-4b93-a69a-e048b593cf40","name":"Postgres Users Memory","type":"n8n-nodes-base.noOp","position":[120,500],"parameters":{"tableName":"message_history","sessionKey":"YOUR_CREDENTIAL_HERE","sessionIdType":"customKey"},"credentials":{"postgres":{"id":"Bk7n11D1jU5zJ802","name":"Postgres account"}},"typeVersion":1,"notes":"This memoryPostgresChat node performs automated tasks as part of the workflow."},{"id":"67c3296e-8915-4857-a294-03c5bc8257c0","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-920,-320],"parameters":{"width":460,"height":1460,"content":"# Step by Step Setup Guide\n\n### **The technology that powers this AI Agent—continuously crawling, extracting, and generating answers—incurs real operating costs to stay online.**\n### **That’s why the workflow requires an active membership, priced at only **\\$29 per month**. Comparable AI-support platforms charge **\\$150 – \\$500 each month**, so with this template you either save a large chunk of that expense for your own business or earn the same amount by reselling the chatbot to clients—while paying just \\$29 yourself. *And because the bot pulls fresh information from the site in real time, you never have to “re-train” a model, saving you even more time and money.***\n\n **Activate your membership here:** [{{ $env.WEBHOOK_URL }}]({{ $env.WEBHOOK_URL }}\n\n### Let's start setting this up step by step:\n*Total hands-on time: ≈ 15 minutes*\n\n1. Activate the tools with the membership generated key: \n- Go to the membership link to get your key.\n- Copy the key (e.g 6F0E4C97-B72A4E69-A11BF6C4-AF123456) and paste it in the body parameters of list_links and get_page (tools):\n*Name: auth-token*\n*Value:  6F0E4C97-B72A4E69-A11BF6C4-AF123456* **(example)**\n\n2. Customize for Your Company:\n- Copy the Root URL of your company's website (Home Page).\n- Open the AI Agent node and inside the `System Message`, change the following values:\n[Company Name] with your company name (e.g [Company Name] -> Facebook)\n[{{ $env.WEBHOOK_URL }}] with your company Root URL that you copied before.\nCheck for these 2 values along the entire text.\n- Go back to the tools list_links and get_page and paste the Root URL inside the body parameters, specifically:\n*Name: url*\n*Value: {{ $env.WEBHOOK_URL }} **(e.g {{ $env.WEBHOOK_URL }}\n\n3. Connect your credentials:\n- Go to the OpenAI Chat Model node and connect your OpenAI credentials.\n- Go to the Postgres Users Memory node and connect your Supabase credentials. A tutorial for this: {{ $env.WEBHOOK_URL }} (Minute 1:45 to 5:00)\n- Go to the WhatsApp nodes \"WhatsApp Trigger\", \"Send Pre-approved Template Message to Reopen the Conversation\" and \"Send AI Agent's Answer\" to connect your credentials. A tutorial for this: {{ $env.WEBHOOK_URL }}\n- Go to the \"Send Pre-approved Template Message to Reopen the Conversation\" and select the template message under the \"Template\" parameter.\n***If you don't want to use this feature (not recommended) delete the nodes \"24-hour window check\", \"If\" and \"Send Pre-approved Template Message to Reopen the Conversation\". Then connect the AI Agent node to the \"cleanAnswer\" node.***\n\n\n### **You are ready**"},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."}],"active":false,"settings":{"executionOrder":"v1","saveManualExecutions":true,"callerPolicy":"workflowsFromSameOwner","errorWorkflow":null,"timezone":"UTC","executionTimeout":3600,"maxExecutions":1000,"retryOnFail":true,"retryCount":3,"retryDelay":1000},"versionId":"245c3695-7177-4a1d-a33d-7aedd0eccc44","connections":{"list_links":{"main":[[],[],[],[],[],[],[],[],[]]},"get_page":{"main":[[],[],[],[],[],[],[],[],[]]},"OpenAI Chat Model":{"main":[[]]}},"description":"Automated workflow: AI Customer-Support Assistant · WhatsApp Ready · Works for Any Business. This workflow integrates 10 different services: stickyNote, code, toolHttpRequest, agent, memoryPostgresChat. It contains 17 nodes and follows best practices for error handling and security.","notes":"Excellent quality workflow: AI Customer-Support Assistant · WhatsApp Ready · Works for Any Business. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}