{
  "name": "AI Agent - Lead Capture & Booking",
  "nodes": [
    {
      "parameters": {
        "public": true,
        "initialMessages": "Hi there! \ud83d\udc4b\nMy name is Nation your AI automation assistant. How can I assist you today?",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1.4,
      "position": [
        -256,
        -80
      ],
      "id": "c4a9dfa9-56fb-432b-903c-a07628981f4c",
      "name": "When chat message received"
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "=You are the AI assistant for Insight Analytics, an AI and automation consultancy based in Lusaka, Zambia, serving Zambian SMEs.\n\nYour role:\n- Greet visitors warmly and find out what business problem they're trying to solve (e.g. manual processes, slow customer response, disorganized records, repetitive admin work).\n- Briefly explain how Insight Analytics can help: custom automation workflows, AI-powered tools (like resume screening, invoicing, WhatsApp assistants), and Excel-based systems tailored to their business.\n- Keep responses short and conversational \u2014 this is a WhatsApp-style chat, not an essay. 2-4 sentences per reply unless asked for detail.\n- Use simple, clear language. Avoid technical jargon unless the user demonstrates technical familiarity.\n- If pricing comes up, explain that engagements are retainer-based and mention that a quick call is the best way to scope their specific needs \u2014 don't quote numbers.\n- Always try to capture the lead's name, business name, and the problem they want solved, so it can be logged.\n- If you don't know something specific about current projects or pricing, say a team member will follow up rather than guessing.\n- Stay professional but friendly \u2014 reflect a local, approachable tone rather than a generic corporate one.\n\nNever invent client names, case studies, or pricing figures that haven't been provided to you."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        160,
        -80
      ],
      "id": "9c7bde19-eccf-459b-8d91-9e3d91ded781",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini"
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        -32,
        144
      ],
      "id": "58514c5d-6bd1-4c08-9e15-4374a0821054",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "contextWindowLength": 20
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.4,
      "position": [
        96,
        144
      ],
      "id": "868c9fa6-e5c7-4bc7-8eb8-da36a3de46a2",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "description": "use this tool to specify unique data",
        "jsCode": "// Code Tool: extract structured lead data from the agent's query\n// Fields: name, email, query, appointment, status, buyer type\n// Input: `query` (string) \u2014 either a JSON string or free/labeled text\n// Output: a single JSON string the agent can read back\n\nfunction extractField(text, labels) {\n  for (const label of labels) {\n    const regex = new RegExp(label + \"\\\\s*[:\\\\-]\\\\s*([^\\\\n,;]+)\", \"i\");\n    const match = text.match(regex);\n    if (match) return match[1].trim();\n  }\n  return null;\n}\n\nlet result;\n\n// Case 1: agent already sent structured JSON\ntry {\n  const parsed = JSON.parse(query);\n  result = {\n    name: parsed.name ?? null,\n    email: parsed.email ?? null,\n    query: parsed.query ?? null,\n    appointment: parsed.appointment ?? null,\n    status: parsed.status ?? null,\n    buyer_type: parsed.buyer_type ?? parsed.buyerType ?? null,\n  };\n} catch (e) {\n  // Case 2: fall back to parsing free/labeled text\n  const text = query;\n\n  const emailMatch = text.match(/[\\w.+-]+@[\\w-]+\\.[\\w.-]+/);\n\n  result = {\n    name: extractField(text, [\"name\"]),\n    email: emailMatch ? emailMatch[0] : extractField(text, [\"email\"]),\n    query: extractField(text, [\"query\", \"message\", \"inquiry\"]),\n    appointment: extractField(text, [\"appointment\", \"appt\", \"date\", \"meeting\"]),\n    status: extractField(text, [\"status\"]),\n    buyer_type: extractField(text, [\"buyer type\", \"buyer\", \"type\"]),\n  };\n}\n\n// Basic validation flags \u2014 helps the agent know what's still missing\nresult.missing_fields = Object.entries(result)\n  .filter(([key, val]) => key !== \"missing_fields\" && !val)\n  .map(([key]) => key);\n\nreturn JSON.stringify(result);"
      },
      "type": "@n8n/n8n-nodes-langchain.toolCode",
      "typeVersion": 1.3,
      "position": [
        224,
        144
      ],
      "id": "fb9a10f7-946c-45ee-a41f-b2099ef7fcc0",
      "name": "Code Tool"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "REPLACE_WITH_YOUR_GOOGLE_SHEET_ID",
          "mode": "list",
          "cachedResultName": "Leads",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/REPLACE_WITH_YOUR_GOOGLE_SHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/REPLACE_WITH_YOUR_GOOGLE_SHEET_ID/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Name": "={{ $fromAI('username') }}",
            "Email": "={{ $fromAI('useremailaddress') }}",
            "Query ": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Query_', `let the model define the parameters `, 'string') }}",
            "Appointment status ": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Appointment_status_', `let the model define the client plan whether to come to the office or schedule the meeting online `, 'string') }}",
            "Buyer type ": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Buyer_type_', `let the model analyze their purpose and classify them into serious and unserious buyers \n`, 'string') }}"
          },
          "matchingColumns": [
            "Email"
          ],
          "schema": [
            {
              "id": "Name",
              "displayName": "Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "displayName": "Email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Query ",
              "displayName": "Query ",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Appointment status ",
              "displayName": "Appointment status ",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Buyer type ",
              "displayName": "Buyer type ",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.7,
      "position": [
        352,
        144
      ],
      "id": "c1ab93e2-bd35-4cfe-80be-674748ffde85",
      "name": "Append or update row in sheet in Google Sheets",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "calendar": {
          "__rl": true,
          "value": "your-email@example.com",
          "mode": "list",
          "cachedResultName": "your-email@example.com"
        },
        "start": "={{ $fromAI('startdate') }}",
        "end": "={{ $fromAI('enddate') }}",
        "additionalFields": {
          "attendees": [
            "={{ $fromAI('useremailaddress') }}",
            "your-email@example.com"
          ],
          "summary": "={{ $fromAI('summary') }}"
        }
      },
      "type": "n8n-nodes-base.googleCalendarTool",
      "typeVersion": 1.3,
      "position": [
        480,
        144
      ],
      "id": "ccf52e00-62e5-406d-a891-94416c82cfcd",
      "name": "Create an event in Google Calendar",
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Code Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Append or update row in sheet in Google Sheets": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Create an event in Google Calendar": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}