Hotel concierge AI agent on WhatsApp

Guests ask about breakfast, Wi-Fi or late checkout on WhatsApp; the agent answers and logs requests for your team.

AI agentAdvanced Saves ~20 hours/month AI AgentsBy Flowngn team

Works with n8n · Make · Zapier

How it works

Trigger: WhatsApp — a guest sends a message
  1. A guest asks a question or makes a request.
  2. The agent answers from your Hotel info sheet, or checks the guest's own booking.
  3. It logs requests (towels, transfers, late checkout) for the team.
  4. It alerts reception about every request and any emergency.

What it can do

Unlike a fixed flow, an agent decides which of its tools to use, in what order — and remembers the conversation.

  • Answers about times, facilities, Wi-Fi, parking and nearby places
  • Shows guests their own booking
  • Logs housekeeping, transfer and late-checkout requests
  • Replies in Arabic dialects or English

System prompt

The instructions that shape the agent. It's already inside the n8n template — copy it into Make or Zapier, and adjust the YOUR_… parts.

System prompt
You are the WhatsApp concierge for YOUR_HOTEL. Reply in the customer's language and dialect (Egyptian Arabic, Gulf Arabic, Modern Standard Arabic or English). Be warm and brief.

Today is {{ $now.toFormat('cccc d LLLL yyyy, HH:mm') }}. The guest's phone is {{ $('Get question').item.json.from }}.

Tools:
- "Hotel info": check-in/out times, breakfast hours, Wi-Fi, parking, pool, facilities, nearby places, airport transfer prices. Answer only from it.
- "My booking": this guest's booking (dates, room, status). It only returns the person who is messaging.
- "Log request": logs a request for the team: housekeeping, extra towels, late checkout, airport pickup, restaurant table, maintenance.
- "Notify team": alerts reception about every request, complaints, emergencies, and anything you can't answer.

Rules:
- Never confirm late checkout, upgrades, refunds or prices that aren't in Hotel info; log the request and say reception will confirm.
- Never share other guests' information or room numbers.
- For emergencies (health, safety, fire), tell the guest to call reception at YOUR_RECEPTION_PHONE right away and use "Notify team".

Safety rules

Built into the prompt and the tools:

  • Never confirms upgrades, refunds or late checkout itself
  • Never shares other guests' details
  • Sends emergencies to reception straight away

Uses your own AI key (Claude, OpenAI or another model). Cost depends on the model and conversation length — a small, fast model keeps most conversations to a fraction of a cent.

Diagram

WIncoming messageWhatsApp Trigger{ }Get questionCodeConcierge agentAI AgentClaude modelAnthropic Chat Mo…◷MemorySimple MemoryGHotel infoGoogle Sheets ToolGMy bookingGoogle Sheets ToolGLog requestGoogle Sheets ToolTNotify teamTelegram ToolWReply on WhatsAppWhatsApp Business Cloud
Trigger App Code AI Agent tool

Code

JavaScript used in the Code step — already included in the template below.

Get question · Code node
// Keeps only text messages and pulls out who sent it and what they asked.
const msg = $input.first().json.messages?.[0];
if (!msg || msg.type !== "text") return [];

return [{ json: { from: msg.from, question: msg.text.body } }];

Build it

Pick your tool — same automation, step by step.

Copy and paste straight into an n8n canvas (Ctrl+V), or download and use Import from File. Then connect your own credentials and replace every YOUR_… placeholder. AI steps use a Claude model node — swap it for OpenAI, Gemini or Ollama if you prefer.

Workflow JSON
Show code (339 lines)
{
  "name": "Hotel concierge AI agent on WhatsApp (Flowngn)",
  "nodes": [
    {
      "parameters": {
        "content": "## Hotel concierge AI agent on WhatsApp\nGuests ask about breakfast, Wi-Fi or late checkout on WhatsApp; the agent answers and logs requests for your team.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
        "height": 260,
        "width": 340
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -420,
        -60
      ]
    },
    {
      "parameters": {
        "updates": [
          "messages"
        ]
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Incoming message",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "webhookId": "3757d265-b3e9-4413-a7d9-26f1c148349a"
    },
    {
      "parameters": {
        "jsCode": "// Keeps only text messages and pulls out who sent it and what they asked.\nconst msg = $input.first().json.messages?.[0];\nif (!msg || msg.type !== \"text\") return [];\n\nreturn [{ json: { from: msg.from, question: msg.text.body } }];"
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Get question",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        300,
        0
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.question }}",
        "options": {
          "systemMessage": "=You are the WhatsApp concierge for YOUR_HOTEL. Reply in the customer's language and dialect (Egyptian Arabic, Gulf Arabic, Modern Standard Arabic or English). Be warm and brief.\n\nToday is {{ $now.toFormat('cccc d LLLL yyyy, HH:mm') }}. The guest's phone is {{ $('Get question').item.json.from }}.\n\nTools:\n- \"Hotel info\": check-in/out times, breakfast hours, Wi-Fi, parking, pool, facilities, nearby places, airport transfer prices. Answer only from it.\n- \"My booking\": this guest's booking (dates, room, status). It only returns the person who is messaging.\n- \"Log request\": logs a request for the team: housekeeping, extra towels, late checkout, airport pickup, restaurant table, maintenance.\n- \"Notify team\": alerts reception about every request, complaints, emergencies, and anything you can't answer.\n\nRules:\n- Never confirm late checkout, upgrades, refunds or prices that aren't in Hotel info; log the request and say reception will confirm.\n- Never share other guests' information or room numbers.\n- For emergencies (health, safety, fire), tell the guest to call reception at YOUR_RECEPTION_PHONE right away and use \"Notify team\"."
        }
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Concierge agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        600,
        0
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "claude-sonnet-5",
          "mode": "list"
        },
        "options": {}
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Claude model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        175,
        220
      ]
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Get question').item.json.from }}",
        "contextWindowLength": 10
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        345,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Returns hotel information: times, facilities, Wi-Fi, parking, nearby places, transfer prices.",
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Hotel info",
          "mode": "name"
        },
        "options": {}
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Hotel info",
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.5,
      "position": [
        515,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Returns the booking of the guest who is messaging.",
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Bookings",
          "mode": "name"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "phone",
              "lookupValue": "={{ $('Get question').item.json.from }}"
            }
          ]
        },
        "options": {}
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "My booking",
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.5,
      "position": [
        685,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Logs a guest request for the team.",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Requests",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "time": "={{ $now.toISO() }}",
            "phone": "={{ $('Get question').item.json.from }}",
            "type": "={{ $fromAI('type', \"housekeeping, late checkout, transfer, restaurant, maintenance or other\", 'string') }}",
            "details": "={{ $fromAI('details', \"What the guest asked for, with times\", 'string') }}",
            "status": "open"
          }
        },
        "options": {}
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Log request",
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.5,
      "position": [
        855,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Alerts reception about guest requests, complaints, emergencies and questions you can't answer.",
        "chatId": "YOUR_TEAM_CHAT_ID",
        "text": "={{ $fromAI('message', \"What the team needs to know, including the customer's phone\", 'string') }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Notify team",
      "type": "n8n-nodes-base.telegramTool",
      "typeVersion": 1.2,
      "position": [
        1025,
        220
      ]
    },
    {
      "parameters": {
        "operation": "send",
        "phoneNumberId": "YOUR_PHONE_NUMBER_ID",
        "recipientPhoneNumber": "={{ $('Get question').item.json.from }}",
        "textBody": "={{ $json.output }}"
      },
      "id": "3757d265-b3e9-4413-a7d9-26f1c148349a",
      "name": "Reply on WhatsApp",
      "type": "n8n-nodes-base.whatsApp",
      "typeVersion": 1,
      "position": [
        900,
        0
      ]
    }
  ],
  "connections": {
    "Incoming message": {
      "main": [
        [
          {
            "node": "Get question",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get question": {
      "main": [
        [
          {
            "node": "Concierge agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Concierge agent": {
      "main": [
        [
          {
            "node": "Reply on WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude model": {
      "ai_languageModel": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Memory": {
      "ai_memory": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Hotel info": {
      "ai_tool": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "My booking": {
      "ai_tool": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Log request": {
      "ai_tool": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Notify team": {
      "ai_tool": [
        [
          {
            "node": "Concierge agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}

Open in the playground to edit →

Tips

  • Add your top 10 nearby restaurants and sights to Hotel info; guests ask about them most.

Related flows