AutomationFlowsSlack & Telegram › Whatsapp Assistant Base — P1

Whatsapp Assistant Base — P1

WhatsApp Assistant Base — P1. Uses supabase, httpRequest, telegram, whatsApp. Webhook trigger; 22 nodes.

Webhook trigger★★★★☆ complexity22 nodesSupabaseHTTP RequestTelegramWhatsApp
Slack & Telegram Trigger: Webhook Nodes: 22 Complexity: ★★★★☆ Added:

This workflow follows the HTTP Request → Supabase recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "WhatsApp Assistant Base \u2014 P1",
  "nodes": [
    {
      "parameters": {
        "httpMethod": [
          "GET",
          "POST"
        ],
        "path": "whatsapp",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "d5122d4b-1504-4d46-843d-0fce1470d782",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "notes": "Verificacion GET + eventos POST de Meta Cloud API. En Meta for Developers, configurar la URL del tunel + /whatsapp. La verificacion de firma se hace en el nodo 'Verificar Firma Meta'.",
      "multipleMethods": true
    },
    {
      "parameters": {
        "conditions": [
          {
            "id": "1",
            "leftValue": "={{ $json.body && $json.body.entry ? 'false' : 'true' }}",
            "rightValue": "true",
            "operator": "string"
          }
        ],
        "options": {}
      },
      "id": "a6433ae9-a3ee-4968-85cb-766ca9cc6d80",
      "name": "IF Verificaci\u00f3n",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        240,
        0
      ],
      "notes": "Rama true = handshake de Meta (devuelve hub.challenge). Rama false = evento real."
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query['hub.challenge'] }}"
      },
      "id": "44570dd2-323f-4293-924a-00a7f643b33f",
      "name": "Responder Challenge",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        480,
        -120
      ],
      "notes": "Responde el challenge de Meta para validar el webhook."
    },
    {
      "parameters": {
        "jsCode": "// Normalize WhatsApp Cloud API webhook payload with input guards.\nconst payload = $input.first().json;\nconst headers = payload.headers || {};\nconst businessPhone = ($env.WHATSAPP_BUSINESS_PHONE || '').replace(/\\D/g, '');\nfor (const entry of payload.body.entry || payload.entry || []) {\n  for (const change of entry.changes || []) {\n    const value = change.value || {};\n    if (value.messages && value.messages.length > 0) {\n      const msg = value.messages[0];\n      const from = String(msg.from || '').replace(/\\D/g, '');\n      // Loop prevention: ignore messages sent by the business's own number.\n      if (businessPhone && from === businessPhone) {\n        return [{ json: { valid: false, reason: 'own_number' } }];\n      }\n      const isText = msg.type === 'text' && msg.text && msg.text.body;\n      if (!isText) {\n        return [{ json: { valid: false, reason: 'unsupported_type' } }];\n      }\n      return [{ json: {\n        valid: true,\n        reason: 'text',\n        contact_phone: from,\n        message_text: String(msg.text.body).slice(0, 2000),\n        message_id: msg.id || '',\n        timestamp: msg.timestamp || '',\n        type: msg.type\n      }}];\n    }\n    if (value.statuses && value.statuses.length > 0) {\n      return [{ json: { valid: false, reason: 'status' } }];\n    }\n  }\n}\nreturn [{ json: { valid: false, reason: 'no_message' } }];"
      },
      "id": "c33bc535-dbc9-4a64-b739-47be017dc62b",
      "name": "Normalizar Mensaje",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        80
      ],
      "notes": "Extrae solo mensajes de texto; descarta status y tipos no soportados; loop prevention y max 2000 caracteres."
    },
    {
      "parameters": {
        "conditions": [
          {
            "id": "1",
            "leftValue": "={{ $json.valid ? 'true' : 'false' }}",
            "rightValue": "true",
            "operator": "string"
          }
        ],
        "options": {}
      },
      "id": "44bade24-748e-464c-bdf9-d4c1a165cbe2",
      "name": "IF Mensaje V\u00e1lido",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        720,
        80
      ],
      "notes": "Rama true = mensaje de texto procesable. Rama false = fin del flujo."
    },
    {
      "parameters": {
        "resource": "row",
        "operation": "getAll",
        "tableId": "contactos",
        "returnAll": false,
        "limit": 1,
        "filterType": "manual",
        "matchType": "allFilters",
        "filters": {
          "conditions": [
            {
              "keyName": "telefono",
              "condition": "eq",
              "keyValue": "={{ $json.contact_phone }}"
            }
          ]
        }
      },
      "id": "1dbd302b-4fa3-4235-8a29-2c6b7b9a7b04",
      "name": "Obtener Contacto",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        960,
        80
      ],
      "notes": "Busca el contacto por telefono (unico por tenant). Credenciales: supabaseApi (URL + Service Role Key)."
    },
    {
      "parameters": {
        "conditions": [
          {
            "id": "1",
            "leftValue": "={{ $json.exists ? 'true' : 'false' }}",
            "rightValue": "true",
            "operator": "string"
          }
        ],
        "options": {}
      },
      "id": "3792c6a5-d17a-4b71-b037-5dba5b19d93b",
      "name": "IF Contacto Existe",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1200,
        80
      ],
      "notes": "Rama true = contacto conocido (usa su id y tenant). Rama false = primer mensaje: crearlo."
    },
    {
      "parameters": {
        "resource": "row",
        "operation": "create",
        "tableId": "contactos",
        "dataToSend": "defineBelow",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "telefono",
              "fieldValue": "={{ $json.contact_phone }}"
            },
            {
              "fieldId": "nombre",
              "fieldValue": "={{ null }}"
            },
            {
              "fieldId": "tenant_id",
              "fieldValue": "={{ $env.TENANT_ID }}"
            }
          ]
        }
      },
      "id": "2d728fb1-3c2c-4223-810e-5bdc45c0dc29",
      "name": "Crear Contacto",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1440,
        200
      ],
      "notes": "Crea el contacto con el TENANT_ID del .env (primer mensaje del cliente)."
    },
    {
      "parameters": {
        "resource": "row",
        "operation": "getAll",
        "tableId": "conversaciones",
        "returnAll": false,
        "limit": 20,
        "orderBy": "created_at.desc",
        "filterType": "manual",
        "matchType": "allFilters",
        "filters": {
          "conditions": [
            {
              "keyName": "contacto_id",
              "condition": "eq",
              "keyValue": "={{ $('Resolver Contacto').item.json.contacto_id }}"
            }
          ]
        }
      },
      "id": "f7199594-f6ff-40fd-8372-1641f94da55f",
      "name": "Obtener Historial",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1440,
        -40
      ],
      "notes": "Ultimas 20 conversaciones del contacto (mas recientes primero) para contexto de Gemini."
    },
    {
      "parameters": {
        "resource": "row",
        "operation": "create",
        "tableId": "conversaciones",
        "dataToSend": "defineBelow",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "tenant_id",
              "fieldValue": "={{ $('Resolver Contacto').item.json.tenant_id }}"
            },
            {
              "fieldId": "contacto_id",
              "fieldValue": "={{ $('Resolver Contacto').item.json.contacto_id }}"
            },
            {
              "fieldId": "role",
              "fieldValue": "user"
            },
            {
              "fieldId": "content",
              "fieldValue": "={{ $('Normalizar Mensaje').item.json.message_text }}"
            }
          ]
        }
      },
      "id": "da0528a2-b0bc-4a65-85db-22d574d3fbf8",
      "name": "Guardar Mensaje Usuario",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1680,
        80
      ],
      "notes": "Persiste el mensaje del usuario antes de llamar a Gemini."
    },
    {
      "parameters": {
        "jsCode": "// Historial seguro (try/catch + normalizacion) + mensaje nuevo.\nlet historyRows = [];\ntry { historyRows = $('Obtener Historial').all().map(i => i.json).flat(1).filter(r => r && typeof r === 'object' && !Array.isArray(r)); } catch (e) {}\nconst contents = historyRows.map(h => ({ role: h.role === 'assistant' ? 'model' : 'user', parts: [{ text: h.content }] }));\ncontents.push({ role: 'user', parts: [{ text: $('Normalizar Mensaje').item.json.message_text }] });\nconst systemInstruction = $env.SYSTEM_PROMPT || 'Eres el asistente virtual del negocio. Responde corto y claro.';\nreturn [{ json: { model: 'gemini-2.5-flash', contents, system_instruction: { parts: [{ text: systemInstruction }] } } }];"
      },
      "id": "7408b250-c516-475e-b19a-f651eccbf83d",
      "name": "Preparar Contexto Gemini",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1920,
        80
      ],
      "notes": "Construye el body de Gemini con historial + mensaje nuevo. SYSTEM_PROMPT viene del .env (requiere N8N_BLOCK_ENV_ACCESS_IN_NODE=false)."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ $json }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-goog-api-key",
              "value": "={{ $env.GEMINI_API_KEY }}"
            }
          ]
        }
      },
      "id": "1068693f-2785-48b8-923b-86ee954e6021",
      "name": "Gemini Responder",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2160,
        80
      ],
      "notes": "Free tier: sin tarjeta. Si cambias de modelo (DeepSeek, Claude), solo cambia esta URL y el modelo en 'Preparar Contexto Gemini'."
    },
    {
      "parameters": {
        "jsCode": "// Extract text from Gemini response and clean control markers\nconst text = ($json.candidates && $json.candidates[0] && $json.candidates[0].content && $json.candidates[0].content.parts[0].text) || '';\nconst clean = text.replace(/\\[DERIVAR\\]/gi, '').replace(/\\[LEAD[^\\]]*\\]/gi, '').trim().slice(0, 4000);\nreturn [{ json: { raw: text, clean, needs_human: /\\[DERIVAR\\]/i.test(text), lead_marker: (text.match(/\\[LEAD ([^\\]]*)\\]/i) || [null, ''])[1] } }];"
      },
      "id": "433f1a6c-544c-408e-b925-087ec7c0f3c9",
      "name": "Extraer Respuesta",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2400,
        80
      ],
      "notes": "Limpia los marcadores [DERIVAR] y [LEAD ...] de la respuesta y detecta si requiere humano."
    },
    {
      "parameters": {
        "resource": "row",
        "operation": "create",
        "tableId": "conversaciones",
        "dataToSend": "defineBelow",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "tenant_id",
              "fieldValue": "={{ $('Resolver Contacto').item.json.tenant_id }}"
            },
            {
              "fieldId": "contacto_id",
              "fieldValue": "={{ $('Resolver Contacto').item.json.contacto_id }}"
            },
            {
              "fieldId": "role",
              "fieldValue": "assistant"
            },
            {
              "fieldId": "content",
              "fieldValue": "={{ $json.clean }}"
            }
          ]
        }
      },
      "id": "f97f29fa-c196-431b-b08c-be2d853a18af",
      "name": "Guardar Respuesta IA",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        2640,
        80
      ],
      "notes": "Persiste la respuesta del asistente (texto limpio, sin marcadores)."
    },
    {
      "parameters": {
        "conditions": [
          {
            "id": "1",
            "leftValue": "={{ $('Extraer Respuesta').item.json.needs_human ? 'true' : 'false' }}",
            "rightValue": "true",
            "operator": "string"
          }
        ],
        "options": {}
      },
      "id": "beb32019-26a8-4857-bd41-128a1638d485",
      "name": "IF Derivar a Humano",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2880,
        80
      ],
      "notes": "Rama true = notifica al humano por Telegram. Rama false = responde directo."
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "sendMessage",
        "chatId": "7309831214",
        "text": "Derivacion a humano. Contacto: {{ $('Normalizar Mensaje').item.json.contact_phone }}. Respuesta IA: {{ $('Extraer Respuesta').item.json.clean }}. Atender en el panel.",
        "additionalFields": {}
      },
      "id": "7c4cad52-c9c6-4d6b-83ad-9ff2c2c8e654",
      "name": "Notificar Humano",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3120,
        -40
      ],
      "notes": "Omitido el Update Row derivado_a_humano=true para mantener el flujo simple; si se requiere auditoria, anadir un nodo Update Row sobre la conversacion del usuario filtrando por content."
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "messageType": "text",
        "recipientPhoneNumber": "={{ $('Normalizar Mensaje').item.json.contact_phone }}",
        "textBody": "={{ $('Extraer Respuesta').item.json.clean }}"
      },
      "id": "a312a38f-4b48-45ad-9ca6-193e35140066",
      "name": "Enviar WhatsApp",
      "type": "n8n-nodes-base.whatsApp",
      "typeVersion": 1.1,
      "position": [
        3120,
        200
      ],
      "notes": "Envia la respuesta del asistente via WhatsApp Business Cloud. El 'Sender Phone Number' se selecciona en el nodo (carga los numeros del Business Account de la credencial whatsAppApi)."
    },
    {
      "parameters": {
        "jsCode": "// Verify Meta webhook signature (X-Hub-Signature-256) with the app secret.\n// Dev (WEBHOOK_VERIFY_SIGNATURE=false): pasa sin verificar (modo disabled).\n// Produccion: HMAC-SHA256 via WebCrypto (sin require, compatible con el sandbox de n8n).\nconst mode = String($env.WEBHOOK_VERIFY_SIGNATURE || 'false').toLowerCase();\nconst passthrough = (verified, m) => [{ json: Object.assign({ verified, mode: m }, $input.first().json) }];\n\nif (mode === 'false') {\n  return passthrough(true, 'disabled');\n}\n\nconst secret = $env.META_APP_SECRET || '';\nconst headers = $input.first().json.headers || {};\nconst signature = headers['x-hub-signature-256'] || headers['X-Hub-Signature-256'] || '';\nconst rawBody = JSON.stringify($input.first().json.body);\n\nif (!secret) {\n  return passthrough(false, 'missing_secret');\n}\n\nconst run = async () => {\n  try {\n    const encoder = new TextEncoder();\n    const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n    const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(rawBody));\n    const hex = Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join('');\n    return passthrough(signature === 'sha256=' + hex, 'enabled');\n  } catch (e) {\n    return passthrough(false, 'crypto_unavailable');\n  }\n};\nreturn run();"
      },
      "id": "783bf572-e631-42a6-bc63-89ff22d371d9",
      "name": "Verificar Firma Meta",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        240
      ],
      "notes": "Verifica X-Hub-Signature-256 con META_APP_SECRET. Activa con WEBHOOK_VERIFY_SIGNATURE=true. Devuelve el payload original (Object.assign) para que los nodos siguientes no lo pierdan. En dev queda desactivada."
    },
    {
      "parameters": {
        "conditions": [
          {
            "id": "1",
            "leftValue": "={{ $json.verified ? 'true' : 'false' }}",
            "rightValue": "true",
            "operator": "string"
          }
        ],
        "options": {}
      },
      "id": "5f218d74-a366-4a8f-ab77-e427411fe71c",
      "name": "IF Firma OK",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        480,
        240
      ],
      "notes": "Rama true = firma valida (o verificacion desactivada en dev) -> Normalizar Mensaje. Rama false = rechazo 401."
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "unauthorized",
        "options": {
          "statusCode": 401
        }
      },
      "id": "ac44e27d-ffd9-4163-862d-f08b9745bbab",
      "name": "Responder Rechazo",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        720,
        240
      ],
      "notes": "Responde 401 cuando la firma HMAC no es valida."
    },
    {
      "parameters": {
        "jsCode": "// Normaliza el resultado de Obtener Contacto (items-fila o 1 item-array) y emite SIEMPRE 1 item.\nconst raw = $('Obtener Contacto').all().map(i => i.json);\nconst rows = raw.flat(1).filter(r => r && typeof r === 'object' && !Array.isArray(r));\nconst telefono = $('Normalizar Mensaje').item.json.contact_phone || '';\nreturn [{ json: { exists: rows.length > 0, contacto: rows[0] || null, telefono } }];"
      },
      "id": "eval-contacto-0001",
      "name": "Evaluar Contacto",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        300
      ],
      "notes": "Convierte el resultado de Obtener Contacto (0 o 1 filas) en un item unico { exists, contacto }."
    },
    {
      "parameters": {
        "jsCode": "// Unifica el contacto existente o el recien creado; try/catch porque los nodos pueden no haberse ejecutado.\nlet fromEval = {};\ntry { fromEval = $('Evaluar Contacto').all().map(i => i.json)[0] || {}; } catch (e) {}\nlet fromCreate = {};\ntry { fromCreate = $('Crear Contacto').all().map(i => i.json)[0] || {}; } catch (e) {}\nconst c = (fromEval.contacto && fromEval.contacto.id ? fromEval.contacto : fromCreate) || {};\nreturn [{ json: { contacto_id: c.id || null, tenant_id: c.tenant_id || null, telefono: fromEval.telefono || '' } }];"
      },
      "id": "resolver-contacto-0001",
      "name": "Resolver Contacto",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        260
      ],
      "notes": "Unifica el contacto existente o el creado; siempre emite 1 item con contacto_id y tenant_id."
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "IF Verificaci\u00f3n",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Verificar Firma Meta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Verificaci\u00f3n": {
      "main": [
        [
          {
            "node": "Responder Challenge",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Verificar Firma Meta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalizar Mensaje": {
      "main": [
        [
          {
            "node": "IF Mensaje V\u00e1lido",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Mensaje V\u00e1lido": {
      "main": [
        [
          {
            "node": "Obtener Contacto",
            "type": "main",
            "index": 0
          },
          {
            "node": "Evaluar Contacto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Contacto Existe": {
      "main": [
        [
          {
            "node": "Resolver Contacto",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Crear Contacto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crear Contacto": {
      "main": [
        [
          {
            "node": "Resolver Contacto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Guardar Mensaje Usuario": {
      "main": [
        [
          {
            "node": "Preparar Contexto Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar Contexto Gemini": {
      "main": [
        [
          {
            "node": "Gemini Responder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Responder": {
      "main": [
        [
          {
            "node": "Extraer Respuesta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraer Respuesta": {
      "main": [
        [
          {
            "node": "Guardar Respuesta IA",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Guardar Respuesta IA": {
      "main": [
        [
          {
            "node": "IF Derivar a Humano",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Derivar a Humano": {
      "main": [
        [
          {
            "node": "Notificar Humano",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Enviar WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notificar Humano": {
      "main": [
        [
          {
            "node": "Enviar WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Firma Meta": {
      "main": [
        [
          {
            "node": "IF Firma OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Firma OK": {
      "main": [
        [
          {
            "node": "Normalizar Mensaje",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Responder Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Evaluar Contacto": {
      "main": [
        [
          {
            "node": "IF Contacto Existe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolver Contacto": {
      "main": [
        [
          {
            "node": "Obtener Historial",
            "type": "main",
            "index": 0
          },
          {
            "node": "Guardar Mensaje Usuario",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": true,
  "tags": []
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

WhatsApp Assistant Base — P1. Uses supabase, httpRequest, telegram, whatsApp. Webhook trigger; 22 nodes.

Source: https://github.com/JeanCardozo/chatAI/blob/main/workflows/whatsapp-assistant-base.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

WhatsApp Assistant Base - P1. Uses httpRequest, supabase, whatsApp. Webhook trigger; 20 nodes.

HTTP Request, Supabase, WhatsApp
Slack & Telegram

WhatsApp Assistant Base - P1. Uses httpRequest, supabase, whatsApp. Webhook trigger; 20 nodes.

HTTP Request, Supabase, WhatsApp
Slack & Telegram

🤖 Telegram Messaging Agent for Text/Audio/Images. Uses telegram, stickyNote, httpRequest, lmChatOpenAi. Webhook trigger; 39 nodes.

Telegram, HTTP Request, OpenAI Chat +2
Slack & Telegram

🤖 Telegram Messaging Agent for Text/Audio/Images. Uses telegram, stickyNote, httpRequest, lmChatOpenAi. Webhook trigger; 39 nodes.

Telegram, HTTP Request, OpenAI Chat +2
Slack & Telegram

This workflow is designed to monitor the Top 5 cryptocurrencies in real-time, calculate trading signals (BUY, SELL, HOLD), and send human-readable alerts through multiple channels. It integrates data

HTTP Request, OpenAI Chat, WhatsApp +3