This workflow corresponds to n8n.io template #11077 — we link there as the canonical source.
This workflow follows the Agent → Error Trigger 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": "ecn0IJQWbj4pC6q0",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Generate GEO-optimized support replies from Gmail to Gmail and Slack",
"tags": [],
"nodes": [
{
"id": "b0441784-72d8-444f-8bdf-8c90eaaf0a66",
"name": "Extract Email Data",
"type": "n8n-nodes-base.set",
"position": [
160,
496
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1b2c3d4",
"name": "customer_email",
"type": "string",
"value": "={{ $json.From }}"
},
{
"id": "b2c3d4e5",
"name": "customer_subject",
"type": "string",
"value": "={{ $json.Subject }}"
},
{
"id": "c3d4e5f6",
"name": "customer_message",
"type": "string",
"value": "={{ $json.snippet }}"
}
]
}
},
"typeVersion": 3.3
},
{
"id": "a7fffc1e-77be-4364-a0c2-6d205ff1781b",
"name": "Notify Slack",
"type": "n8n-nodes-base.slack",
"position": [
2368,
736
],
"parameters": {
"text": "=AI replied to {{ $json.To }}\nGEO: {{ $json[\"Geo Used\"] }}\nSummary: {{ $json.Summary }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09GNB90TED",
"cachedResultName": "general-information"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "83e0cf98-e0bb-437c-a989-cb4530be7051",
"name": "Gmail Trigger",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-64,
496
],
"parameters": {
"filters": {
"labelIds": [
"INBOX"
],
"readStatus": "unread"
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "ab0f9d59-2017-47f7-9a79-89b05f49d646",
"name": "OpenAI Chat Model - GPT-4o-mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1072,
464
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "a7c2f203-5182-4bac-8e49-abe8f494c081",
"name": "Memory - Conversation Buffer",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1200,
464
],
"parameters": {
"sessionKey": "\"GEO Defined\"",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "6534c1cb-d7ff-4be3-aca3-9e292d30b393",
"name": "Output Parser - Structured JSON",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1328,
464
],
"parameters": {
"jsonSchemaExample": "{\n \"geo\": \"Canada\"\n}\n"
},
"typeVersion": 1.3
},
{
"id": "0d1a6951-d9ff-41b9-a715-dd6a47f4d7d8",
"name": "AI Agent - GEO Identifier",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1136,
240
],
"parameters": {
"text": "=Determine the most probable GEO region for this customer.\n\nEmail Address: {{$json[\"customer_email\"]}}\nMessage Text:\n{{$json[\"customer_message\"]}}\n\nReturn JSON only in this form:\n{\n \"geo\": \"string\"\n}\n",
"options": {
"systemMessage": "=You detect the customer's GEO region based on their email content, email address, language hints, currency mentions, city names, or spelling style.\n\nReturn ONLY one simple GEO label:\n\"US\", \"UK\", \"India\", \"Canada\", \"EU\", \"Australia\", \"UAE\", or \"Unknown\".\n\nRespond ONLY in valid JSON.\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "da1bf8d7-8557-4379-8451-d428921d67d2",
"name": "OpenAI Chat Model - GPT-4o-mini1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1536,
576
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "86f534a4-e3b7-49c2-9a76-7f1426081dae",
"name": "Memory - Conversation Buffer1",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1664,
576
],
"parameters": {
"sessionKey": "\"GEO Defined\"",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "1600c8ee-b52b-4c43-a36b-8a08fe7921a6",
"name": "Output Parser - Structured JSON1",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1792,
576
],
"parameters": {
"jsonSchemaExample": "{\n \"to\": \"user@example.com\",\n \"subject\": \"Re: Shipping to Canada?\",\n \"reply\": \"Hello Laura,\\n\\nYes, we do ship to Canada. Standard delivery takes 5\u20137 business days, and orders above CAD $70 qualify for free shipping. For other orders, shipping is CAD $12.\\n\\nIf you need help placing the order, I\u2019d be happy to assist.\\n\\nBest regards,\\nBrandX Support\",\n \"geo_used\": \"Canada\",\n \"summary\": \"Provided shipping info and fees for a customer in Canada.\"\n}\n"
},
"typeVersion": 1.3
},
{
"id": "04618d8b-e9fc-4753-996e-7eea2f194a65",
"name": "AI Agent - GEO-Optimized Support",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1600,
352
],
"parameters": {
"text": "=Prepare a GEO-optimized reply email.\n\nCustomer GEO: {{ $json.output.geo }}\nCustomer Email: {{ $('Extract Email Data').item.json.customer_email }}\nOriginal Subject: {{ $('Extract Email Data').item.json.customer_subject }}\nCustomer Message:\n{{ $('Extract Email Data').item.json.customer_message }}\n\nFollow the JSON format exactly and fill in all fields.\n\"subject\" should start with \"Re: \" + the original subject.\n\"to\" must be the customer's email address.\n",
"options": {
"systemMessage": "=You are an expert customer support agent.\n\nYour job:\nGenerate a GEO-optimized, ready-to-send support email reply AND return it in a clean structured JSON format.\n\nGEO Tone Rules:\n- US: direct, casual\n- UK: polite, formal\n- India: warm, guiding\n- Canada/EU: neutral, compliance-friendly\n- Australia: friendly, informal\n\nOutput Requirements:\n- ALWAYS respond with VALID JSON only.\n- No markdown.\n- No extra explanation.\n- No surrounding text.\n- The \"reply\" field must contain the full email body text.\n\nReturn JSON in this EXACT format:\n\n{\n \"to\": \"string\",\n \"subject\": \"string\",\n \"reply\": \"string (full email body)\",\n \"geo_used\": \"string\",\n \"summary\": \"short 1-line summary of the reply\"\n}\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "d0111e71-1b00-4dff-8c1b-015480149be5",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
2224,
256
],
"parameters": {
"sendTo": "={{ $json.To }}",
"message": "={{ $json.Reply }}",
"options": {},
"subject": "={{ $json.Subject }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "f5f13640-13f7-435a-82f9-2fd5a2363290",
"name": "Format Data For Email",
"type": "n8n-nodes-base.set",
"position": [
2000,
352
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a3692cf1-fc7f-4c80-9a89-6d0abd8a4868",
"name": "To",
"type": "string",
"value": "={{ $json.output.to }}"
},
{
"id": "c5211a41-8e40-4db3-a182-8f80a05a0ab8",
"name": "Reply",
"type": "string",
"value": "={{ $json.output.reply }}"
},
{
"id": "d3d6eb91-6a9d-4549-9f54-fe1258788144",
"name": "Geo Used",
"type": "string",
"value": "={{ $json.output.geo_used }}"
},
{
"id": "cfb5ed83-da8a-45e6-8a44-8cb6a4864403",
"name": "Summary",
"type": "string",
"value": "={{ $json.output.summary }}"
},
{
"id": "e7147507-4586-4b85-9e0b-8e29bb7400bc",
"name": "Subject",
"type": "string",
"value": "={{ $json.output.subject }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "8ed25d76-7e95-4059-a82d-4d6d62e0a5f4",
"name": "OpenAI Chat Model - GPT-4o-mini2",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
384,
720
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "9ef21678-32cf-48fb-91bc-cbbff5e2e21a",
"name": "Memory - Conversation Buffer2",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
512,
720
],
"parameters": {
"sessionKey": "\"GEO Defined\"",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "e79ed751-e504-4a1d-8238-fb0aaf0cb411",
"name": "Output Parser - Structured JSON2",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
640,
720
],
"parameters": {
"jsonSchemaExample": "{\n \"is_query\": true,\n \"category\": \"support\",\n \"reason\": \"The email asks about shipping availability\"\n}\n"
},
"typeVersion": 1.3
},
{
"id": "1e4fc6b8-3e24-4259-b57b-43546def4a3b",
"name": "AI Agent - Email Classification",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
448,
496
],
"parameters": {
"text": "=Classify this email:\n\nFrom: {{$json[\"customer_email\"]}}\nSubject: {{$json[\"customer_subject\"]}}\nMessage:\n{{$json[\"customer_message\"]}}\n",
"options": {
"systemMessage": "=You are a classification engine.\nYour job is to determine if an incoming email is a real customer support query.\n\nReturn ONLY JSON in this format:\n{\n \"is_query\": true/false,\n \"category\": \"support | sales | spam | internal | notification | other\",\n \"reason\": \"short explanation\"\n}\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "6292faa3-00f6-489d-b317-2602da417d58",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
848,
496
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "850c5b0c-daf3-45ab-a545-20870099aeea",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.output.is_query }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "eb607a31-2bc4-4699-a7ea-c616616704b6",
"name": "Manual Review",
"type": "n8n-nodes-base.slack",
"position": [
1200,
816
],
"parameters": {
"text": "=Manual Review Intevention:- \n\nCategory:-{{ $json.output.category }} \nReason{{ $json.output.reason }} \n\nPlease check your Inbox.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09GNB90TED",
"cachedResultName": "general-information"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "f32e607c-3c93-4899-a0b6-4202bef3d963",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-128,
-336
],
"parameters": {
"width": 480,
"height": 672,
"content": "## Real-Time GEO-Optimized Answer Engine \u2013 Overview\n\nThis workflow listens for incoming customer emails, classifies whether they are support queries, detects the customer's GEO region, and generates a GEO-appropriate reply using AI. If the email is a valid query, the engine composes a ready-to-send reply tailored to regional tone and rules, sends it via Gmail, and posts a Slack notification. Non-query or ambiguous messages are routed for manual review. The workflow uses structured output parsers to force strict JSON at each AI step, and stores a short summary and GEO used for reporting.\n\n### How it works\n1. Gmail trigger captures unread inbound emails. \n2. AI classifies whether message is a support query. \n3. If a query: AI infers GEO, then produces a GEO-optimized reply (JSON). \n4. Reply is formatted and sent via Gmail; Slack is notified. \n5. If not a query: sends a manual review alert to Slack.\n\n### Setup steps\n- Add Gmail, Slack, and OpenAI credentials. \n- Verify parser schemas and Gmail send permissions. \n- Test with a few sample emails.\n\n### Customization\nAdjust GEO labels, tone rules, classification thresholds, or add more locales.\n"
},
"typeVersion": 1
},
{
"id": "d0b721cf-7c8c-4536-8e67-ff7c4c2c9fac",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-128,
368
],
"parameters": {
"color": 2,
"width": 208,
"height": 288,
"content": "## Gmail Trigger\nPolls unread INBOX emails and passes raw message data into the workflow.\n"
},
"typeVersion": 1
},
{
"id": "973bac37-0d6d-40a1-a25c-2d9fac588b6a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2304,
608
],
"parameters": {
"color": 2,
"height": 320,
"content": "## Slack Notifications\nSends success confirmations and manual-review alerts to the selected Slack channel.\n"
},
"typeVersion": 1
},
{
"id": "c833bee6-583f-477d-a63f-742860928f86",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1936,
160
],
"parameters": {
"color": 2,
"width": 432,
"height": 336,
"content": "## Format & Send Email\nFormats AI output for Gmail and sends the reply; also stores summary and GEO used.\n"
},
"typeVersion": 1
},
{
"id": "7390b9aa-ccfe-4843-bb48-3c5c70172b83",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
128
],
"parameters": {
"color": 2,
"width": 416,
"height": 464,
"content": "## GEO Identifier\nAI infers customer GEO from email content, address hints, and language cues.\n"
},
"typeVersion": 1
},
{
"id": "3365fc8a-1bc4-4922-8f29-22f3d4926ce6",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1136,
704
],
"parameters": {
"color": 2,
"height": 256,
"content": "## Manual Review\nRoutes non-query or uncertain items to Slack for human review and triage.\n"
},
"typeVersion": 1
},
{
"id": "fd663e26-c674-497a-ac7e-8a7e41988cf8",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
368
],
"parameters": {
"color": 2,
"width": 400,
"height": 512,
"content": "## Email Classification\nDetermines if the message is a customer query and assigns a category and reason.\n"
},
"typeVersion": 1
},
{
"id": "c39ee14f-4565-4012-bcdf-9e491b342118",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
112,
368
],
"parameters": {
"color": 2,
"height": 288,
"content": "## Extract Email Data\nExtracts sender, subject, and snippet to prepare inputs for classification.\n"
},
"typeVersion": 1
},
{
"id": "42a0dd0c-9cfc-4215-87be-c9ba769d1020",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1488,
240
],
"parameters": {
"color": 2,
"width": 416,
"height": 496,
"content": "## GEO-Optimized Support Reply\nGenerates a ready-to-send reply with tone and content tailored to the detected GEO.\n"
},
"typeVersion": 1
},
{
"id": "c1d0553c-a903-4b8b-a05d-849f023e912e",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1568,
0
],
"parameters": {
"color": 3,
"height": 208,
"content": "## \u26a0\ufe0f Strict JSON Required\nAll AI agents MUST return valid JSON exactly matching the parser schema. Extra text will break downstream parsing and sending.\n"
},
"typeVersion": 1
},
{
"id": "1a27aeba-f2ef-48cf-90af-a92b35df8c12",
"name": "Error Handling",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
1264
],
"parameters": {
"color": 2,
"width": 584,
"height": 276,
"content": "## Error Handling\nCaptures workflow failures and sends details to Slack for quick debugging.\n"
},
"typeVersion": 1
},
{
"id": "b51ec034-35c4-4044-902e-ac05eab1d7c3",
"name": "Error Handler Trigger",
"type": "n8n-nodes-base.errorTrigger",
"position": [
32,
1376
],
"parameters": {},
"typeVersion": 1
},
{
"id": "5543b2cc-0d0c-4aa7-b0e3-bdf1c252e655",
"name": "Slack: Send Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
240,
1376
],
"parameters": {
"text": "=\u26a0\ufe0f *Error in API Error Catalog Workflow*\n*Node:* {{ $json.node.name }}\n*Message:* {{ $json.error.message }}\n*Time:* {{ $json.timestamp }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "="
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.3
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "02dc11ae-a53c-4e7c-ad18-c9a50ea660c0",
"connections": {
"If": {
"main": [
[
{
"node": "AI Agent - GEO Identifier",
"type": "main",
"index": 0
}
],
[
{
"node": "Manual Review",
"type": "main",
"index": 0
}
]
]
},
"Gmail Trigger": {
"main": [
[
{
"node": "Extract Email Data",
"type": "main",
"index": 0
}
]
]
},
"Send a message": {
"main": [
[]
]
},
"Extract Email Data": {
"main": [
[
{
"node": "AI Agent - Email Classification",
"type": "main",
"index": 0
}
]
]
},
"Error Handler Trigger": {
"main": [
[
{
"node": "Slack: Send Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Format Data For Email": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
},
{
"node": "Notify Slack",
"type": "main",
"index": 0
}
]
]
},
"AI Agent - GEO Identifier": {
"main": [
[
{
"node": "AI Agent - GEO-Optimized Support",
"type": "main",
"index": 0
}
]
]
},
"Memory - Conversation Buffer": {
"ai_memory": [
[
{
"node": "AI Agent - GEO Identifier",
"type": "ai_memory",
"index": 0
}
]
]
},
"Memory - Conversation Buffer1": {
"ai_memory": [
[
{
"node": "AI Agent - GEO-Optimized Support",
"type": "ai_memory",
"index": 0
}
]
]
},
"Memory - Conversation Buffer2": {
"ai_memory": [
[
{
"node": "AI Agent - Email Classification",
"type": "ai_memory",
"index": 0
}
]
]
},
"AI Agent - Email Classification": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model - GPT-4o-mini": {
"ai_languageModel": [
[
{
"node": "AI Agent - GEO Identifier",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Output Parser - Structured JSON": {
"ai_outputParser": [
[
{
"node": "AI Agent - GEO Identifier",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"AI Agent - GEO-Optimized Support": {
"main": [
[
{
"node": "Format Data For Email",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model - GPT-4o-mini1": {
"ai_languageModel": [
[
{
"node": "AI Agent - GEO-Optimized Support",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"OpenAI Chat Model - GPT-4o-mini2": {
"ai_languageModel": [
[
{
"node": "AI Agent - Email Classification",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Output Parser - Structured JSON1": {
"ai_outputParser": [
[
{
"node": "AI Agent - GEO-Optimized Support",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Output Parser - Structured JSON2": {
"ai_outputParser": [
[
{
"node": "AI Agent - Email Classification",
"type": "ai_outputParser",
"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.
gmailOAuth2openAiApislackApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Streamline customer support with a real-time, AI-powered answer engine that detects incoming support emails, classifies intent, identifies the customer’s GEO region, and generates a tailored reply ready to send. 📧
Source: https://n8n.io/workflows/11077/ — 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.
Automatically detect, classify, and document GitHub API errors using AI. This workflow connects GitHub, OpenAI (GPT-4o), Airtable, Notion, and Slack to build a real-time, searchable API error knowledg
Streamline Facebook Messenger inbox management with an AI-powered categorization and response system. 💬⚙️ This workflow automatically classifies new messages as Lead, Query, or Spam using GPT-4, route
This workflow automatically transforms your messy inbox into a neatly organized space while ensuring you never miss a critical message. It connects to your Gmail account and triggers for every new ema
Monitors your AP inbox for incoming invoices, extracts structured data with AI, runs duplicate and vendor history checks against Supabase, then scores each invoice for fraud risk — routing suspicious
Gmail users report spending significant time manually sorting email, so this tool helps alleviate that burden. Gmail Trigger monitors unread emails every 2 minutes Once an email arrives, the content i