This workflow corresponds to n8n.io template #4966 — we link there as the canonical source.
This workflow follows the Agent → Google Docs 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 →
{
"id": "e0BX3fhHvcBuQTBU",
"name": "whats app agent community",
"tags": [],
"nodes": [
{
"id": "02f761e2-83c4-488b-91f4-f4ae11b15c00",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"maxTries": 5,
"position": [
1040,
440
],
"parameters": {
"text": "={{ $json.finalPrompt }}\n\n\n",
"options": {
"systemMessage": "You are [Company]\u2019s support assistant for Black Ball Sporting Club.\n\u2022 Do NOT include any preamble such as \u201cBased on the document you provided\u201d or \u201cOkay, [Name].\u201d Just jump straight to the answer.\n* don't ever start your response with\"based on the document you provided\" , or \"According to the document\", don't mention any documents at all , also don't mention today's date unless you asked\n"
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": false,
"typeVersion": 1.7,
"alwaysOutputData": true,
"waitBetweenTries": null
},
{
"id": "57ecb397-5772-4db3-8a5a-ce28a4e01e63",
"name": "cleanAnswer",
"type": "n8n-nodes-base.code",
"position": [
2300,
340
],
"parameters": {
"jsCode": "// cleanAnswer \u2013 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](https://url) \u2192 Texto https://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\n// 4. Remove the unwanted source-reference preamble\ntxt = txt.replace(/^.*?based on the document you provided[,:]?\\s*/i, '');\n\nreturn [{ json: { answer: txt } }];\n"
},
"typeVersion": 2
},
{
"id": "d70cf8b1-8c24-44f2-9b37-5205b130cff2",
"name": "24-hour window check",
"type": "n8n-nodes-base.code",
"position": [
1860,
440
],
"parameters": {
"jsCode": "// within24h? \u2013 run once per item\n// Meta (WhatsApp) timestamp arrives as seconds since epoch\nconst lastTs = Number($('when message received').first().json.messages[0].timestamp) * 1000; // \u2192 ms\nconst withinWindow = Date.now() - lastTs < 24 * 60 * 60 * 1000;\n\nreturn [{ json: { withinWindow, answer: $json.answer, userId: $json.userId } }];"
},
"typeVersion": 2
},
{
"id": "66c83de5-413a-440f-804e-15b137beb873",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
2080,
440
],
"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
},
{
"id": "80fc3049-8474-4392-9e04-f5686eb82687",
"name": "Send Pre-approved Template Message to Reopen the Conversation",
"type": "n8n-nodes-base.whatsApp",
"position": [
2300,
540
],
"parameters": {
"template": "hello_world|en_US",
"phoneNumberId": "641448739058783",
"recipientPhoneNumber": "={{ $('when message received').item.json.contacts[0].wa_id }}"
},
"typeVersion": 1
},
{
"id": "d77ae0ae-c332-4030-8c77-8ea44c56c9a8",
"name": "Send AI Agent's Answer",
"type": "n8n-nodes-base.whatsApp",
"position": [
2520,
340
],
"parameters": {
"textBody": "={{ $json.answer }}",
"operation": "send",
"phoneNumberId": "=641448739058783",
"additionalFields": {},
"recipientPhoneNumber": "={{ $('when message received').item.json.contacts[0].wa_id }}"
},
"typeVersion": 1
},
{
"id": "c9d931c3-d88c-4d15-b8fe-787327c0200a",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1000,
660
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-preview-04-17-thinking"
},
"typeVersion": 1
},
{
"id": "630ac52d-1d65-408e-b614-17a97bddab10",
"name": "when message received",
"type": "n8n-nodes-base.whatsAppTrigger",
"position": [
380,
440
],
"parameters": {
"options": {},
"updates": [
"messages"
]
},
"credentials": {
"whatsAppTriggerApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "df46b528-cbbd-49c2-9b83-4402ef0c8ac7",
"name": "Prepare Prompt",
"type": "n8n-nodes-base.aiTransform",
"position": [
820,
440
],
"parameters": {
"jsCode": "const googleDocs = $input.all().map((item) => item.json);\nconst whatsappMessages = $(\"when message received\")\n .all()\n .map((item) => item.json);\n\nconst date = new Date();\nconst formattedDate = `${date.getMonth() + 1} ${date.getDate()}, ${date.getFullYear()}`;\n\nconst docText = googleDocs[0].content.split(\"\\n\").join(\" \");\n\nconst body = whatsappMessages[0].messages[0].text.body;\n\nconst finalPrompt = `Today's date is: ${formattedDate}\\n\\n${docText}\\n\\nUser's question:\\n${body}`;\n\nreturn { finalPrompt };\n",
"instructions": "Write code to:\n\u2022 Get today\u2019s date formatted \u201cMonth Day, Year\u201d\n\u2022 Extract the Google Doc\u2019s plain text by joining its body.content textRuns\n\u2022 Extract the WhatsApp message from messages[0].text.body\n\u2022 Build a field finalPrompt exactly as:\n\nvbnet\nCopy\nEdit\nToday's date is: [date]\n\n[doc text]\n\nUser's question:\n[body]\n\u2022 Return finalPrompt only.",
"codeGeneratedForPrompt": "Write code to:\n\u2022 Get today\u2019s date formatted \u201cMonth Day, Year\u201d\n\u2022 Extract the Google Doc\u2019s plain text by joining its body.content textRuns\n\u2022 Extract the WhatsApp message from messages[0].text.body\n\u2022 Build a field finalPrompt exactly as:\n\nvbnet\nCopy\nEdit\nToday's date is: [date]\n\n[doc text]\n\nUser's question:\n[body]\n\u2022 Return finalPrompt only."
},
"typeVersion": 1
},
{
"id": "19de46dc-add8-4cad-81a9-6e5b341f1f33",
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
1640,
440
],
"parameters": {
"columns": {
"value": {
"User": "={{ $('when message received').item.json.messages[0].from }}",
"Message": "={{ $('when message received').item.json.messages[0].text.body }}",
"Response": "={{ $('AI Agent').item.json.output }}",
"Timestamp": "={{ $json.currentDate }}"
},
"schema": [
{
"id": "Timestamp",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "User",
"type": "string",
"display": true,
"required": false,
"displayName": "User",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Message",
"type": "string",
"display": true,
"required": false,
"displayName": "Message",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Response",
"type": "string",
"display": true,
"required": false,
"displayName": "Response",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 5",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 6",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 7",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 7",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 8",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 8",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 9",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 9",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 10",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 10",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 11",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 11",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 12",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 12",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 13",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 13",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 14",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 14",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 15",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 15",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 16",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 16",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 17",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 17",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 18",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 18",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 19",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 19",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 20",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 20",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 21",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 21",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 22",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 22",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 23",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 23",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 24",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 24",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 25",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 25",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Column 26",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Column 26",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Timestamp"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Ub8QIhGPOm1G4ylaM48iMAous1zvBO3YDl-38AKDuFw/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1Ub8QIhGPOm1G4ylaM48iMAous1zvBO3YDl-38AKDuFw",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Ub8QIhGPOm1G4ylaM48iMAous1zvBO3YDl-38AKDuFw/edit?usp=drivesdk",
"cachedResultName": "Chat Logs"
}
},
"typeVersion": 4.6
},
{
"id": "b622392e-65dc-4d27-a5f9-d27ea57aae61",
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"position": [
1420,
440
],
"parameters": {
"options": {}
},
"typeVersion": 2
},
{
"id": "a6ae2118-9d68-4fb0-b975-b9c6d4170e00",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"height": 1420,
"content": "**Smart WhatsApp AI Assistant Using Google Docs**\n\n\ud83d\udccc What it does:\nAnswers WhatsApp questions instantly using internal document knowledge. No training needed \u2014 just update the doc.\n\n\ud83d\udcc4 Reads a live Google Doc\n\ud83d\udcac Receives WhatsApp messages\n\ud83e\udde0 Crafts AI prompt using today's date + message + doc\n\u26a1 Uses OpenAI/Gemini to generate a response\n\ud83d\udce4 Sends reply back over WhatsApp\n\n\ud83e\uddf0 Prerequisites:\n- WhatsApp Business Cloud API account\n- Google Doc with your business content\n- OpenAI or Gemini API \nkey\n- you can setup the postgress memory using the following link:\nhttps://www.youtube.com/watch?v=JjBofKJnYIU\n\n\n\ud83d\udee0 Setup:\n1. Paste your Google Doc ID in the Docs node\n2. Connect WhatsApp Cloud API (Meta)\n3. Map the message field\n4. Connect OpenAI or Gemini\n5. Publish and test with a live message\n\nYou\u2019re done!\n\ud83e\udd1d Need Help Setting It Up?\nIf you'd like help connecting your WhatsApp Business API, setting up Google Docs access, or customizing this AI assistant for your business or clients\u2026\n\n\ud83d\udce9 I offer setup, branding, and customization services:\nWhatsApp Cloud API setup & verification\n\nGoogle OAuth & Doc structure guidance\n\nAI model configuration (OpenAI / Gemini)\n\nBranding & prompt tone customization\n\nLogging, reporting, and escalation logic\n\nJust send a message via:\n\nEmail: tharwat.elsayed2000@gmail.com\n\nWhatsApp: +201061803236"
},
"typeVersion": 1
},
{
"id": "8f4a786b-fc6d-4e2f-b8df-c605475afc81",
"name": "company's knowledge",
"type": "n8n-nodes-base.googleDocs",
"position": [
600,
440
],
"parameters": {
"operation": "get",
"documentURL": "=1Uv1WYCcXNlp-jaeJ7-3MNxWYfPj-wcYnJv4_colXSvk"
},
"typeVersion": 2
},
{
"id": "a6de89dd-ada0-432c-9f8e-ece38264ad81",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1120,
660
],
"parameters": {
"sessionKey": "={{ $('when message received').item.json.contacts[0].wa_id }}",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "d9d79584-559b-4948-be55-ba2e4160a527",
"connections": {
"If": {
"main": [
[
{
"node": "cleanAnswer",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Pre-approved Template Message to Reopen the Conversation",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"main": [
[
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"cleanAnswer": {
"main": [
[
{
"node": "Send AI Agent's Answer",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets": {
"main": [
[
{
"node": "24-hour window check",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Prepare Prompt": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"company's knowledge": {
"main": [
[
{
"node": "Prepare Prompt",
"type": "main",
"index": 0
}
]
]
},
"24-hour window check": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"when message received": {
"main": [
[
{
"node": "company's knowledge",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
whatsAppTriggerApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Document-Aware WhatsApp AI Bot for Customer Support Google Docs-Powered WhatsApp Support Agent 24/7 WhatsApp AI Assistant with Live Knowledge from Google Docs
Source: https://n8n.io/workflows/4966/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
WhatsApp AI Assistant for Clinic Appointment Booking Automate your entire appointment lifecycle with an intelligent AI assistant that lives on WhatsApp. This workflow empowers any clinic or independen
This workflow implements a WhatsApp-based virtual restaurant assistant that automates customer interaction from the first message to post-dining follow-up.
Wait Splitout. Uses whatsAppTrigger, whatsApp, httpRequest, memoryBufferWindow. Event-driven trigger; 35 nodes.
Wait Splitout. Uses whatsAppTrigger, whatsApp, httpRequest, memoryBufferWindow. Event-driven trigger; 35 nodes.
This n8n template demonstrates the beginnings of building your own n8n-powered WhatsApp chatbot! Under the hood, utilise n8n's powerful AI features to handle different message types and use an AI agen