Alchemy RecipeBeginnerworkflow

Customer support chatbot trained on your documentation and knowledge base

An AI chatbot that answers customer questions using your Notion docs and automatically escalates complex issues via email.

Time saved
Saves 5-10 hrs/week
Monthly cost
~~£75/mo/mo
Published

Your support inbox is overflowing. A customer asks how to reset their password. A second customer wants to know about your refund policy. A third asks the same password question. Your team answers these questions manually, over and over, even though the answers live in your Notion documentation. Each response takes five minutes. That's five minutes per customer, per day, multiplied across your team. What if those questions answered themselves? This workflow shows you how to build a customer support chatbot that reads directly from your Notion knowledge base, answers common questions instantly, and escalates anything complicated to your support team via email. No manual routing required. No customer waiting on hold. The chatbot sits behind a simple interface, available to customers 24/7. When it encounters a question it cannot answer confidently, it writes an email summary and sends it straight to your support inbox, so nothing falls through the cracks. Setup takes roughly 30 minutes and costs less than a few coffees per month.

What You'll Build - A conversational chatbot interface (deployed via n8n or Claude Code) that answers customer support questions instantly

  • Automated context retrieval from your Notion knowledge base, synced hourly to stay current
  • Confidence-based decision logic: questions the bot answers confidently are resolved immediately; uncertain queries trigger an email escalation
  • An escalation workflow that formats the customer question, includes relevant context snippets, and emails your support team with one click to reply
  • Support metrics tracking: logs of every question asked, answers given, and escalations triggered, stored in Notion for analysis
  • Zero manual handoff between the chatbot decision and the escalation email (or the customer getting their answer) This saves your support team roughly 15-20 hours per week on repetitive questions, depending on how many customers you have and how good your documentation is.

Prerequisites

You will need the following before starting: - A Notion workspace with a knowledge base or FAQ database (free Notion tier works, but Notion Plus recommended if you have more than 50 pages)

  • OpenAI API key (from https://platform.openai.com/account/api-keys); GPT-4o mini is sufficient for this workflow
  • Emailit account with API access (paid plan needed; free trial usually available)
  • An orchestration tool: Zapier (free tier works but with rate limits), n8n (self-hosted free or cloud paid), or Make (free tier available)
  • Basic familiarity with JSON, API calls, and webhooks
  • About 30 minutes to connect the tools and test end-to-end If you want to skip orchestration entirely, you can use Claude Code to build the integration yourself, though you will need to manage the hosting yourself.

The Automated Workflow

Step 1:

Sync Your Notion Knowledge Base to a Vector Database Before your chatbot can answer questions, it needs access to your documentation. You will sync your Notion pages into a searchable format using ChatGPT's embedding model via the OpenAI API. Start by extracting content from your Notion database using the Notion API. Set up a scheduled trigger (daily or hourly, depending on how often your docs change) in your orchestration tool.

GET https://api.notion.com/v1/databases/{DATABASE_ID}/query
Headers: Authorization: Bearer {NOTION_API_KEY} Notion-Version: 2022-06-28
Content-Type: application/json

For each page returned, fetch the full page content:

GET https://api.notion.com/v1/blocks/{PAGE_ID}/children
Headers: Authorization: Bearer {NOTION_API_KEY} Notion-Version: 2022-06-28

Parse the returned blocks and extract readable text. Pass this text to OpenAI's embedding endpoint to generate vector embeddings:

POST https://api.openai.com/v1/embeddings
Headers: Authorization: Bearer sk-{OPENAI_API_KEY} Content-Type: application/json { "input": "Your knowledge base text here", "model": "text-embedding-3-small"
}

Store the embeddings and original text in a simple JSON file, a PostgreSQL database, or a vector store like Pinecone (free tier available). For simplicity, store it as a JSON file in your orchestration tool's storage. Error handling: if the Notion API rate-limits you (500 requests per minute), add a 2-second delay between page fetches. If embedding fails, log the error and retry up to three times with exponential backoff before skipping that page.

Step 2:

Create a Customer-Facing Chat Interface The customer needs somewhere to ask their question. You have two options: build a simple webhook receiver in your orchestration tool, or use Claude Code to build a standalone web interface. For simplicity, use n8n's built-in "Chat Trigger" node (if using n8n) or set up a webhook in Zapier that accepts POST requests:

POST https://hooks.zapier.com/hooks/catch/{ZAPIER_WEBHOOK_ID}/
Content-Type: application/json { "customer_email": "user@example.com", "customer_message": "How do I reset my password?", "conversation_id": "conv_12345"
}

Alternatively, use Claude Code to build a React component that sends chat messages to an API endpoint you control. If you go this route, you will need to host it yourself (Vercel, Netlify, or your own server). The benefit is full control over styling and branding; the trade-off is you need to manage the hosting. For this guide, assume you are using n8n's Chat Trigger, which generates a shareable link automatically. Error handling: validate that customer_email is a valid email format before proceeding. If the conversation_id is missing, generate one using a UUID.

Step 3:

Retrieve Relevant Context from Your Knowledge Base When the customer message arrives, you need to find the most relevant sections of your Notion documentation. Use vector similarity search: convert the customer's question into an embedding, then find the closest matches in your stored embeddings.

POST https://api.openai.com/v1/embeddings
Headers: Authorization: Bearer sk-{OPENAI_API_KEY} Content-Type: application/json { "input": "How do I reset my password?", "model": "text-embedding-3-small"
}

This returns a vector. Compare it against your stored knowledge base embeddings using cosine similarity. Most programming languages have libraries for this (Python: scikit-learn, Node.js: brain.js). If you are using n8n, the "Function" node supports JavaScript; write a simple similarity function:

javascript
function cosineSimilarity(vecA, vecB) { const dotProduct = vecA.reduce((sum, a, i) => sum + a * vecB[i], 0); const magA = Math.sqrt(vecA.reduce((sum, a) => sum + a * a, 0)); const magB = Math.sqrt(vecB.reduce((sum, b) => sum + b * b, 0)); return dotProduct / (magA * magB);
} // Get top 3 matches from your knowledge base
const matches = storedEmbeddings .map(item => ({ ...item, similarity: cosineSimilarity(userQuestionEmbedding, item.embedding) })) .sort((a, b) => b.similarity - a.similarity) .slice(0, 3);

Extract the top 3 matching documents and their text. Pass these to the next step. Error handling: if no matches have a similarity score above 0.6, flag the question as "uncertain" and skip to the escalation step (Step 5). If embedding generation fails, retry once, then escalate.

Step 4:

Generate an Answer Using ChatGPT Now you have the customer's question and relevant context from your knowledge base. Send both to ChatGPT with a carefully written system prompt that instructs it to answer only based on the provided context.

POST https://api.openai.com/v1/chat/completions
Headers: Authorization: Bearer sk-{OPENAI_API_KEY} Content-Type: application/json { "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "You are a helpful customer support assistant. Answer the customer's question using ONLY the knowledge base excerpts provided below. If you cannot answer based on the provided information, respond with: 'I'm not sure about that. Let me connect you with our support team.' Do not make up information. Keep your answer concise (under 100 words).\n\nKnowledge base:\n{CONTEXT_HERE}" }, { "role": "user", "content": "How do I reset my password?" } ], "temperature": 0.3, "max_tokens": 200
}

Set temperature low (0.3) to keep responses factual and consistent. The API returns a completion. Extract the text content from the response. Now, here's the critical part: assess whether the bot is confident in its answer. If the response contains phrases like "I'm not sure", "Let me connect you", or if the knowledge base match similarity was below 0.6, mark this as an escalation case. Otherwise, mark it as resolved and proceed to send the answer back to the customer (Step 4b). Error handling: if the API returns a rate limit error (HTTP 429), wait 30 seconds and retry. If the API fails three times, escalate to your support team. If the response is empty or malformed, escalate.

Step 4b:

Send the Answer Back to the Customer If the bot is confident, format the response nicely and send it back via the same chat interface or via email, depending on your setup. If using n8n's Chat Trigger, the response goes back automatically. If you built a custom web interface, send a response JSON back to your frontend:

POST https://your-api.example.com/chat-response
Content-Type: application/json { "conversation_id": "conv_12345", "message": "To reset your password, click the 'Forgot Password' link on the login page. You'll receive an email with reset instructions within 2 minutes.", "resolved": true, "timestamp": "2026-03-15T14:23:00Z"
}

Log this in your Notion metrics database (see Step 6) so you can analyse which questions your bot handles well. Error handling: if the response fails to send, queue it for retry using your orchestration tool's built-in retry mechanism (typically 3 retries with exponential backoff).

Step 5:

Escalate Uncertain Questions to Your Support Team If the bot is not confident, or if no good matches were found, send an escalation email to your support team. Use Emailit for this.

POST https://api.emailit.io/v1/send
Headers: Authorization: Bearer {EMAILIT_API_KEY} Content-Type: application/json { "from": "support-bot@yourdomain.com", "to": "support@yourdomain.com", "subject": "ESCALATION: Customer Question - " + customer_question, "html": "<h2>Escalated Support Request</h2><p><strong>From:</strong> {CUSTOMER_EMAIL}</p><p><strong>Question:</strong> {CUSTOMER_QUESTION}</p><p><strong>Relevant Knowledge Base Excerpts:</strong></p><blockquote>{TOP_3_MATCHES}</blockquote><p><strong>Bot Confidence:</strong> Low</p><p><a href='mailto:{CUSTOMER_EMAIL}?subject=Re: Your Support Question'>Reply to Customer</a></p>", "reply_to": "support@yourdomain.com", "tags": ["escalation", "low-confidence"]
}

Include the customer's email, their question, and the top 3 knowledge base matches you found. This gives your support team context immediately, so they can respond faster without hunting for documentation. Error handling: if Emailit is down, queue the escalation in a JSON file within your orchestration tool and retry every 5 minutes for up to 1 hour. If it still fails, send an alert to your engineering team (see Pro Tips).

Step 6:

Log Every Interaction to Notion for Analytics Each conversation, whether resolved or escalated, should be recorded in Notion. This lets you analyse which questions your bot handles well and identify gaps in your documentation. Create a Notion database called "Support Bot Analytics" with the following columns: - Customer Email (text)

  • Question (text)
  • Answer (text)
  • Resolved (checkbox)
  • Confidence Score (number, 0-1)
  • Top Match (text, the highest-scoring knowledge base result)
  • Created At (date)
  • Conversation ID (text) After each conversation, write a record:
POST https://api.notion.com/v1/pages
Headers: Authorization: Bearer {NOTION_API_KEY} Notion-Version: 2022-06-28 Content-Type: application/json { "parent": { "database_id": "your-analytics-database-id" }, "properties": { "Customer Email": { "email": "user@example.com" }, "Question": { "title": [ { "text": { "content": "How do I reset my password?" } } ] }, "Answer": { "rich_text": [ { "text": { "content": "To reset your password..." } } ] }, "Resolved": { "checkbox": true }, "Confidence Score": { "number": 0.87 }, "Top Match": { "rich_text": [ { "text": { "content": "Password Reset - FAQ Section 3" } } ] }, "Created At": { "date": { "start": "2026-03-15T14:23:00.000Z" } }, "Conversation ID": { "rich_text": [ { "text": { "content": "conv_12345" } } ] } }
}

Error handling: if Notion write fails, log the record to a JSON backup file and retry asynchronously. Do not block the customer's experience waiting for analytics to write.

The Manual Alternative

If you prefer to test this workflow manually before automating it fully, you can do the following: Copy your Notion knowledge base content into a document. When a customer question arrives (via email or Slack), manually search your knowledge base for relevant answers. Compose a response using ChatGPT: paste the customer question and the relevant knowledge base excerpts into the ChatGPT interface directly, using the same system prompt described in Step 4. Read ChatGPT's response and decide if it is confident enough. If yes, email the customer. If no, forward the question to your support team with the relevant excerpts pasted in. This takes 5-10 minutes per question. It requires no setup, no API keys, and no technical knowledge beyond using ChatGPT. The trade-off is obvious: it does not scale. Once you are handling more than a few questions per day, the manual approach becomes unsustainable. Automation becomes cost-effective almost immediately. You can also run the workflow partially automated. For example, automate Steps 1-4 (sync knowledge base, retrieve context, generate answer) but manually review each answer before sending it to the customer. Use Slack as a checkpoint: n8n or Zapier sends a message to your support Slack channel with the customer question, the bot's answer, and a "Send" or "Escalate" button. A human clicks one, and the workflow continues. This is a good middle ground while you gain confidence in the bot's answers.

Pro Tips

Keep the knowledge base embeddings fresh. Re-embed your entire Notion database every 24 hours using a scheduled trigger. Do not rely on one-time embeddings; your docs will change, and stale context produces stale answers. Set the schedule to run at 2 AM in your timezone when customer volume is lowest, so there is no delay in the customer-facing chatbot. Batch API calls to reduce costs. Instead of calling the OpenAI embedding endpoint once per customer question, collect questions in a queue and embed 10 at a time every 5 minutes. This reduces the overhead of HTTP requests and can save 30-40% on API costs over time. For customer-facing responses, use synchronous single calls (which are faster), but for batch analytics and knowledge base syncing, always batch. Monitor escalation quality. Set up a Slack alert that triggers when more than 20% of questions are escalated to your support team in a 1-hour window. This indicates either a gap in your documentation or a poorly tuned confidence threshold. When the alert fires, review the last 10 escalated questions, update your knowledge base to cover them, and re-run the embeddings. Iterate weekly. Set a confidence threshold and adjust it based on real data. Start with 0.65 (cosine similarity between the question embedding and the best match). After two weeks, review your escalations and your "customer satisfaction" ratings (if you collect them). If customers are frustrated with low-quality answers, raise the threshold to 0.75. If too many questions are escalated, lower it to 0.55. This tuning takes time but is the difference between a chatbot that helps and a chatbot that frustrates. Store your OpenAI API key and Emailit API key in your orchestration tool's environment variables, never hardcoded in workflows. Most tools (n8n, Zapier, Make) support secure credential storage. Use it. Rate-limit your Notion API calls. The Notion API allows 3 requests per second. If you are syncing a large knowledge base (500+ pages), you will hit this limit. Add a 500-millisecond delay between page fetches. For OpenAI, the free tier allows 3 requests per minute; paid tiers allow higher limits. Check your plan and add appropriate delays.

Cost Breakdown

ToolPlan NeededMonthly CostWhat You Get
ChatGPT / OpenAI APIPay-as-you-go (typical usage £10-30/month)£15 (estimate)GPT-4o mini API access, text-embedding-3-small access, 1M tokens included, overage at £0.003 per 1K input tokens
EmailitStarter (1,000 emails/month)£20Transactional email sending, API access, basic templates, webhook support
Notion AINotion Plus (if you don't have it already)£8Optional; you can sync Notion free, but Plus gives better reliability and higher API limits (500 requests/min instead of 100)
n8n (self-hosted)Self-hosted free or cloud pro£0-50Workflow orchestration, scheduling, storage, no transaction limits on self-hosted
Make (Integromat)Free tier (1,000 operations/month)£0 (or £10+ for paid)Scenario builder, webhook triggers, HTTP requests, reasonable free tier for this workflow
Total (recommended)£43-80/monthNotion Plus, n8n cloud, ChatGPT API, Emailit

Tool Pipeline Overview

How each tool connects in this workflow

1
ChatGPT

ChatGPT

AI-powered conversational assistant by OpenAI

2
E

Emailit

Send transactional and marketing emails easily with built-in campaigns, SMTP, and REST API

3
Notion AI

Notion AI

AI-powered writing and knowledge management

More Recipes