Car service centre AI agent on WhatsApp

Customers ask "is my car ready?", get price ranges and book service slots on WhatsApp.

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

Works with n8n · Make · Zapier

How it works

Trigger: WhatsApp — a customer sends a message
  1. A customer asks about a service, a price or their car.
  2. The agent checks your price list, or the customer's own open jobs.
  3. It finds free slots and books the service in your calendar.
  4. It alerts your service advisor.

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 "is my car ready?" from your Jobs sheet
  • Gives price ranges and durations
  • Books service appointments

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 assistant for YOUR_GARAGE, a car service centre. 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') }}. Opening hours: YOUR_HOURS. The customer's phone is {{ $('Get question').item.json.from }}.

Tools:
- "Services & prices": our services (oil change, brakes, AC, inspection…) with price ranges and duration.
- "My car status": this customer's open jobs (plate, car, job, status, ready_at, estimate). It only returns the person who is messaging.
- "Check free slots": booked appointments between two dates, to find free slots.
- "Book service": books a confirmed appointment. Use only after the customer confirms the car (make, model, year, plate), service, date and time.
- "Notify team": alerts our service advisor about bookings, approvals for extra work, complaints and questions you can't answer.

Rules:
- Quote only price ranges from the list, and say the final price comes after inspection.
- Never diagnose problems or promise repair times; describe what the inspection will check.
- If a customer approves or refuses extra work, pass it to the team with "Notify team"; don't change the job yourself.

Safety rules

Built into the prompt and the tools:

  • Never diagnoses or promises repair times
  • Only quotes price ranges, final price after inspection
  • Passes extra-work approvals to a person

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 questionCodeGarage agentAI AgentClaude modelAnthropic Chat Mo…◷MemorySimple MemoryGServices & pri…Google Sheets ToolGMy car statusGoogle Sheets ToolCCheck free slo…Google Calendar T…CBook serviceGoogle Calendar T…TNotify 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 (366 lines)
{
  "name": "Car service centre AI agent on WhatsApp (Flowngn)",
  "nodes": [
    {
      "parameters": {
        "content": "## Car service centre AI agent on WhatsApp\nCustomers ask \"is my car ready?\", get price ranges and book service slots on WhatsApp.\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": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -420,
        -60
      ]
    },
    {
      "parameters": {
        "updates": [
          "messages"
        ]
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Incoming message",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "webhookId": "2c528f90-83ec-4354-a019-950940e3b8ba"
    },
    {
      "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": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "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 assistant for YOUR_GARAGE, a car service centre. 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') }}. Opening hours: YOUR_HOURS. The customer's phone is {{ $('Get question').item.json.from }}.\n\nTools:\n- \"Services & prices\": our services (oil change, brakes, AC, inspection…) with price ranges and duration.\n- \"My car status\": this customer's open jobs (plate, car, job, status, ready_at, estimate). It only returns the person who is messaging.\n- \"Check free slots\": booked appointments between two dates, to find free slots.\n- \"Book service\": books a confirmed appointment. Use only after the customer confirms the car (make, model, year, plate), service, date and time.\n- \"Notify team\": alerts our service advisor about bookings, approvals for extra work, complaints and questions you can't answer.\n\nRules:\n- Quote only price ranges from the list, and say the final price comes after inspection.\n- Never diagnose problems or promise repair times; describe what the inspection will check.\n- If a customer approves or refuses extra work, pass it to the team with \"Notify team\"; don't change the job yourself."
        }
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Garage 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": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Claude model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        90,
        220
      ]
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Get question').item.json.from }}",
        "contextWindowLength": 10
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        260,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Returns our services with price ranges and durations.",
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Services",
          "mode": "name"
        },
        "options": {}
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Services & prices",
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.5,
      "position": [
        430,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Returns the open jobs of the customer who is messaging.",
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Jobs",
          "mode": "name"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "phone",
              "lookupValue": "={{ $('Get question').item.json.from }}"
            }
          ]
        },
        "options": {}
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "My car status",
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.5,
      "position": [
        600,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Lists booked appointments between two dates, so you can find free slots within opening hours.",
        "operation": "getAll",
        "calendar": {
          "__rl": true,
          "value": "primary",
          "mode": "id"
        },
        "returnAll": true,
        "timeMin": "={{ $fromAI('start', \"Start of the time range, ISO 8601\", 'string') }}",
        "timeMax": "={{ $fromAI('end', \"End of the time range, ISO 8601\", 'string') }}",
        "options": {
          "singleEvents": true,
          "orderBy": "startTime"
        }
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Check free slots",
      "type": "n8n-nodes-base.googleCalendarTool",
      "typeVersion": 1.3,
      "position": [
        770,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Books a confirmed service appointment.",
        "calendar": {
          "__rl": true,
          "value": "primary",
          "mode": "id"
        },
        "start": "={{ $fromAI('start', \"Appointment start, ISO 8601 with timezone\", 'string') }}",
        "end": "={{ $fromAI('end', \"Appointment end, ISO 8601 with timezone\", 'string') }}",
        "additionalFields": {
          "summary": "={{ $fromAI('title', \"Service and car, e.g. Oil change — Toyota Corolla 2019\", 'string') }}",
          "description": "=Phone: {{ $('Get question').item.json.from }}\n{{ $fromAI('details', 'Car plate and what the customer described', 'string') }}"
        }
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Book service",
      "type": "n8n-nodes-base.googleCalendarTool",
      "typeVersion": 1.3,
      "position": [
        940,
        220
      ]
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Alerts the service advisor about bookings, extra-work approvals, complaints 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": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "name": "Notify team",
      "type": "n8n-nodes-base.telegramTool",
      "typeVersion": 1.2,
      "position": [
        1110,
        220
      ]
    },
    {
      "parameters": {
        "operation": "send",
        "phoneNumberId": "YOUR_PHONE_NUMBER_ID",
        "recipientPhoneNumber": "={{ $('Get question').item.json.from }}",
        "textBody": "={{ $json.output }}"
      },
      "id": "2c528f90-83ec-4354-a019-950940e3b8ba",
      "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": "Garage agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Garage agent": {
      "main": [
        [
          {
            "node": "Reply on WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude model": {
      "ai_languageModel": [
        [
          {
            "node": "Garage agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Memory": {
      "ai_memory": [
        [
          {
            "node": "Garage agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Services & prices": {
      "ai_tool": [
        [
          {
            "node": "Garage agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "My car status": {
      "ai_tool": [
        [
          {
            "node": "Garage agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Check free slots": {
      "ai_tool": [
        [
          {
            "node": "Garage agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Book service": {
      "ai_tool": [
        [
          {
            "node": "Garage agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Notify team": {
      "ai_tool": [
        [
          {
            "node": "Garage agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}

Open in the playground to edit →

Tips

  • Update the status and ready_at columns when a job moves on; that's what customers ask about most.

Related flows