AutomationFlows β€Ί AI & RAG β€Ί Automated Reservation System with Telegram, Google Gemini Ai, and Google Sheets

Automated Reservation System with Telegram, Google Gemini Ai, and Google Sheets

ByTharwat Mohamed @tharwatelsayedβœ“ on n8n.io

πŸ’‘ What It Is

Event triggerβ˜…β˜…β˜…β˜†β˜† complexityAI-powered10 nodesTelegram TriggerGoogle Gemini ChatGoogle Sheets ToolGmail ToolTelegramAgentAi TransformMemory Postgres Chat
AI & RAG Trigger: Event Nodes: 10 Complexity: β˜…β˜…β˜…β˜†β˜† AI nodes: yes Added:

This workflow corresponds to n8n.io template #5454 β€” we link there as the canonical source.

This workflow follows the Agent β†’ Gmail Tool 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
{
  "id": "TQT1s777PZUJUvxu",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "telegram court agent",
  "tags": [],
  "nodes": [
    {
      "id": "cdee9b4c-c94d-47c7-802b-0825919db984",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -540,
        -160
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "24052a80-a551-4347-9fbc-5cf4498885b1",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -100,
        60
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.5-flash-preview-04-17"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "409972f9-cdce-4f99-9071-ee3171daf28c",
      "name": "court info",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        140,
        60
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MhuNGRokppbeqwLx9aBjbh3CmZqwWlmJ7UZwU3jMjXs/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1MhuNGRokppbeqwLx9aBjbh3CmZqwWlmJ7UZwU3jMjXs",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MhuNGRokppbeqwLx9aBjbh3CmZqwWlmJ7UZwU3jMjXs/edit?usp=drivesdk",
          "cachedResultName": "court info"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "605d1d9c-8164-4cd1-8c47-e1a13748ce31",
      "name": "Gmail",
      "type": "n8n-nodes-base.gmailTool",
      "position": [
        260,
        60
      ],
      "parameters": {
        "sendTo": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('To', ``, 'string') }}",
        "message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Subject', ``, 'string') }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "01d625c7-17e7-4cdc-9463-346eef53397e",
      "name": "Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        580,
        -160
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3cf98881-4c56-41fc-9025-96aee9ee6954",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        52,
        -160
      ],
      "parameters": {
        "text": "={{ $json.finalPrompt }}",
        "options": {
          "systemMessage": "\n\nYou are a helpful Court Reservation Assistant for Black Ball Sporting Club. Your role is to help players book training courts through a simple, guided process. Keep responses concise and friendly.\n\n## Core Behavior\n\n- Always respond with complete, helpful messages\n- If you don't understand something, ask for clarification politely\n- Handle errors gracefully without technical jargon\n- Stay focused on court reservations\n\n## Reservation Process\n\n### 1. Welcome New Users\n\nWhen someone starts a conversation:\n\n- Greet them warmly\n- Explain you help with court bookings\n- Ask for their reservation details\n\n### 2. Collect Information\n\nAsk users to provide these details (they can send multiple messages):\n\n- **Date** (YYYY-MM-DD format, e.g., 2025-06-15)\n- **Full Name**\n- **Email Address**\n- **Court Number** (check available courts using the court info tool)\n- **Start Time** (24-hour format, e.g., 14:30)\n- **End Time** (24-hour format, e.g., 16:00)\n\n**Example:** \"I need: Date, Your Name, Email, Court Number, Start Time, and End Time. You can send these in separate messages or all together.\"\n\n### 3. Validation & Conflict Check\n\nBefore confirming any booking:\n\n- Verify date format is YYYY-MM-DD\n- Check start time is before end time\n- Ensure email looks valid (contains @ symbol)\n- Use the court confirmation tool to check for scheduling conflicts\n- If there's a conflict, suggest alternative times or courts\n\n### 4. Booking Confirmation\n\nOnce details are validated and no conflicts exist:\n\n- Save the reservation using the court confirmation tool\n- Send confirmation email using the Gmail tool\n- Confirm success to the user in Telegram\n\n## Error Handling\n\n**Invalid Formats:**\n\"I need the date as YYYY-MM-DD (like 2025-06-15) and times as HH:MM (like 14:30). Could you try again?\"\n\n**Time Conflicts:**\n\"Sorry, that time slot is already booked. Here are some available alternatives: [suggest 2-3 nearby time slots]\"\n\n**Missing Information:**\n\"I still need [list missing items]. Could you provide those details?\"\n\n**System Errors:**\n\"I'm having trouble accessing the booking system right now. Please try again in a moment.\"\n\n## Important Rules\n\n- Never send empty or incomplete responses\n- Always acknowledge what the user sent before asking for more info\n- If using tools fails, explain the issue simply\n- Offer helpful alternatives when possible\n- Keep the conversation moving forward\n- Don't repeat the same instructions multiple times\n\n## Tone\n\n- Friendly but professional\n- Encouraging and supportive\n- Clear and direct\n- Solution-focused"
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "f1aa7109-5ecc-433f-96a5-c65f80cca591",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        380,
        60
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Date__using_to_match_', ``, 'string') }}",
            "name": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('name', ``, 'string') }}",
            "court": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('court', ``, 'string') }}",
            "email": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('email', ``, 'string') }}",
            "end time": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('end_time', ``, 'string') }}",
            "confirmed": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('confirmed', ``, 'string') }}",
            "start time": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('start_time', ``, 'string') }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "court",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "court",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "start time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "start time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "end time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "end time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "confirmed",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "confirmed",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t4W_a2n6yveUCitx2Q2i5jNFMV08_Fos2xqpBAUnbPo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1t4W_a2n6yveUCitx2Q2i5jNFMV08_Fos2xqpBAUnbPo",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t4W_a2n6yveUCitx2Q2i5jNFMV08_Fos2xqpBAUnbPo/edit?usp=drivesdk",
          "cachedResultName": "court confirmations"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "718b57b6-15bb-47cb-8371-77c8e1997572",
      "name": "Prepare Prompt",
      "type": "n8n-nodes-base.aiTransform",
      "position": [
        -320,
        -160
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst today = new Date();\nconst formattedDate = `${today.toLocaleString(\"default\", { month: \"long\" })} ${today.getDate()}, ${today.getFullYear()}`;\n\nconst finalPrompt = items.map((item) => {\n  const telegramMessage = item?.json?.message?.text;\n  return {\n    finalPrompt: `Today's date is: ${formattedDate}\\n\\nUser's question:\\n${telegramMessage}`,\n  };\n});\n\nreturn finalPrompt;\n",
        "instructions": "Write code to:\n\u2022 Get today\u2019s date formatted \u201cMonth Day, Year\u201d\n\u2022 Extract the telegram message from chat.text\n\u2022 Build a field finalPrompt exactly as:\n\nvbnet\nCopy\nEdit\nToday's date is: [date]\n\n\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 telegram message from chat.text\n\u2022 Build a field finalPrompt exactly as:\n\nvbnet\nCopy\nEdit\nToday's date is: [date]\n\n\n\nUser's question:\n[body]\n\u2022 Return finalPrompt only."
      },
      "typeVersion": 1
    },
    {
      "id": "04fbff80-7046-4530-948b-30c8cdacf77a",
      "name": "Postgres Chat Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "position": [
        20,
        60
      ],
      "parameters": {
        "sessionKey": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 20
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "53ebf4e3-b3dc-4160-afe7-ecfb7b353337",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1080,
        -460
      ],
      "parameters": {
        "width": 360,
        "height": 1300,
        "content": "\ud83e\udde0 Purpose\nThis workflow powers a general-purpose reservation bot using Telegram, Google Sheets, and Email. Users send one message to request a reservation\u2014it's validated against existing bookings, stored, and confirmed automatically.\n\n\ud83d\udce5 Input Collected (in one go):\n\nDate\n\nName\n\nEmail\n\nResource (court, room, etc.)\n\nStart Time\n\nEnd Time\n\nConfirm (by replying \"yes\")\n\n\ud83e\udde9 Main Logic Flow\n\nTelegram Trigger \u2192 captures full request\n\nFunction \u2192 parses message fields\n\nGoogle Sheets \u2192 checks for availability\n\nDecision Node \u2192 validates time slot\n\nGoogle Sheets \u2192 appends confirmed data\n\nEmail Node \u2192 sends confirmation\n\nTelegram \u2192 replies with confirmation summary\n\n\ud83d\udcc4 Google Sheets Setup Required\n\nResource Info sheet (optional reference)\n\nReservation Log sheet with these headers:\n\n\nCopy\nEdit\nDate | Name | Email | Resource | Start Time | End Time | Status\n\u26a0\ufe0f Notes\n\nAll data is captured from a single user input (no multi-step flow).\n\nTime conflict logic uses date + resource + time slot.\n\nYou can rename \"Resource\" to anything (Room, Coach, Session, etc.)\n\n\ud83d\udcec Publisher Support\nNeed help customizing or deploying this bot?\n\ud83d\udce7 tharwat.elsayed.hamad@gmail.com"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "4f5c1642-5090-42ab-aa01-54633931c7ee",
  "connections": {
    "Gmail": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "court info": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Prompt": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Prepare Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "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.

Pro

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

About this workflow

πŸ’‘ What It Is

Source: https://n8n.io/workflows/5454/ β€” original creator credit. Request a take-down β†’

More AI & RAG workflows β†’ Β· Browse all categories β†’

Related workflows

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

AI & RAG

assistente. Uses openAi, telegram, telegramTrigger, agent. Event-driven trigger; 21 nodes.

OpenAI, Telegram, Telegram Trigger +9
AI & RAG

n8n_amin. Uses lmChatOllama, gmailTool, telegramTrigger, telegram. Event-driven trigger; 19 nodes.

Ollama Chat, Gmail Tool, Telegram Trigger +6
AI & RAG

✨ What It Is Automate your professional communication directly from Telegram using this powerful AI assistant built with n8n.

Agent, Mcp Client Tool, Mcp Trigger +7
AI & RAG

Telegram Trigger receives incoming messages (text, voice, photo, document). Switch routes by message type to appropriate processors: Text β†’ forwarded as-is. Voice β†’ downloaded and sent to Transcribe a

Memory Buffer Window, Telegram Trigger, Telegram +12
AI & RAG

Transform your Telegram messenger into a powerful, multi-modal personal or team assistant. This n8n workflow creates an intelligent agent that can understand text, voice, images, and documents, and ta

Memory Buffer Window, Telegram Trigger, Telegram +10