Your support team is drowning in repetitive tickets while customers wait hours for answers that already exist in your knowledge base. Password resets, shipping questions, “how do I cancel” — the same 20 questions eating up 80% of your agents’ time. What if every new Zendesk ticket got an accurate, knowledge-base-backed AI reply within seconds, and only the genuinely tricky ones reached a human?
That’s exactly what you’ll build in this guide. Using n8n, OpenAI, Supabase, and a RAG (Retrieval-Augmented Generation) pipeline, you’ll create a workflow that reads every incoming Zendesk ticket, searches your knowledge base for relevant answers, generates a professional reply, and posts it directly to the ticket — automatically. When the AI doesn’t have a confident answer, it escalates to your human team with a clear tag so nothing falls through the cracks.
Prefer to skip the setup? Grab the ready-made template and be up and running in under 10 minutes.
What You’ll Build
- A new ticket arrives in Zendesk — the workflow fires instantly via webhook.
- The AI agent searches your Supabase-hosted knowledge base using vector similarity (RAG) and drafts a response grounded in your actual documentation.
- If the knowledge base has a solid answer, the AI posts the reply directly to the Zendesk ticket and tags it
ai_reply. - If the AI can’t find relevant information, it tags the ticket
human_requestedso your team picks it up — no guessing, no hallucinations. - Every conversation is stored in Postgres memory, so follow-up tickets from the same customer retain context.
How It Works — The Big Picture
The entire workflow is a single n8n pipeline with a smart routing branch at the end. Here’s the flow from ticket to resolution:
┌──────────────────────────────────────────────────────────────────────────────┐ │ AI-POWERED ZENDESK SUPPORT WITH RAG │ │ │ │ [Zendesk Webhook] → [Extract Ticket Data] → [RAG AI Agent] │ │ │ │ │ ┌────────────┴────────────┐ │ │ │ Check If Escalation │ │ │ │ Needed │ │ │ └────┬──────────┬─────────┘ │ │ YES ↓ ↓ NO │ │ [Tag: human_ [Post AI Reply] │ │ requested] ↓ │ │ [Tag: ai_reply] │ │ │ │ Sub-components of the RAG AI Agent: │ │ ┌──────────────────────────────────────────────┐ │ │ │ [OpenAI GPT-4o-mini] [Postgres Memory] │ │ │ │ [Knowledge Base Tool → Supabase Vectors] │ │ │ │ [OpenAI Embeddings] │ │ │ └──────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────┘
What You’ll Need
- n8n — self-hosted or n8n Cloud (any plan)
- Zendesk — any plan with API access and trigger/webhook support
- OpenAI API key — for GPT-4o-mini (chat) and text-embedding-3-small (embeddings)
- Supabase account — free tier works; you’ll need a project with pgvector enabled for the vector store
- PostgreSQL database — Supabase’s built-in Postgres works, or any external Postgres instance for conversation memory
- Your knowledge base content — FAQ articles, product docs, troubleshooting guides already written and ready to embed
Estimated build time: 45–60 minutes from scratch, or under 10 minutes with the template.
Part 1 — Receiving and Parsing Zendesk Tickets
1 Receive New Ticket (Webhook)
This node listens for incoming HTTP POST requests from Zendesk. Every time a new ticket is created, Zendesk’s trigger sends the ticket data to this webhook URL.
- Add a Webhook node to your canvas.
- Set the HTTP Method to
POST. - Set the Path to
zendesk-new-ticket(or any slug you prefer). - Copy the generated webhook URL — you’ll paste this into Zendesk’s trigger configuration.
When a ticket arrives, the webhook receives a JSON payload like this:
{
"body": {
"ticket_id": "48291",
"ticket_status": "new",
"requester_name": "Sarah Thompson",
"requester_email": "sarah.thompson@gmail.com",
"subject": "Can't reset my password",
"description": "Hi, I've been trying to reset my password for the last hour but the reset email never arrives. I've checked spam. Can you help?"
}
}
Tip: In Zendesk, go to Admin Center → Objects and rules → Triggers. Create a trigger that fires when “Ticket is Created” and set the action to “Notify active webhook” with your n8n webhook URL. Include ticket_id, subject, description, requester_name, requester_email, and ticket_status as JSON fields in the webhook body.
2 Extract Ticket Data (Set Node)
The raw webhook payload is nested inside body. This Set node extracts the fields you need into clean, top-level variables that the rest of the workflow can reference easily.
- Add a Set node after the Webhook.
- Create assignments for:
ticket_id,ticket_status,requester_name,requester_email,subject,description, andtimestamp. - For
description, use the expression{{ ($json.body.description || '').split('\n\n').slice(-1)[0].trim() }}— this strips quoted reply chains and keeps only the customer’s latest message. - For
timestamp, use{{ $now.format('yyyy-MM-dd HH:mm') }}so you have a record of when the workflow processed the ticket.
After this node, the data flowing forward looks like:
{
"ticket_id": "48291",
"ticket_status": "new",
"requester_name": "Sarah Thompson",
"requester_email": "sarah.thompson@gmail.com",
"subject": "Can't reset my password",
"description": "I've been trying to reset my password for the last hour but the reset email never arrives. I've checked spam. Can you help?",
"timestamp": "2026-04-10 14:23"
}
Part 2 — The RAG AI Agent
This is the brain of the workflow. The AI Agent node connects to three sub-components: a language model (GPT-4o-mini), a conversation memory (Postgres), and a knowledge base retrieval tool (Supabase vector store). Together, they form a RAG pipeline that grounds every response in your actual documentation.
3 Generate AI Response (AI Agent)
The Agent node receives the customer’s ticket and orchestrates the entire reasoning process. It decides whether to search the knowledge base, reads the results, and composes a professional reply.
- Add an AI Agent node.
- Set the Prompt Type to Define.
- Set the input text to:
Customer: {{ $json.requester_name }}
Subject: {{ $json.subject }}
Message: {{ $json.description }} - In the System Message, paste the following instructions that tell the agent how to behave:
You are a professional, empathetic customer support agent. Your job is to help
customers by answering their questions accurately using ONLY the information
from the retrieved knowledge base documents.
Rules:
1. Always be polite, professional, and concise.
2. If the knowledge base contains a clear answer, provide it with step-by-step
instructions when appropriate.
3. If the knowledge base does NOT contain relevant information, respond with
EXACTLY: "I will escalate this to our support team who will get back to
you shortly."
4. Never make up information. Never guess. Only use verified KB content.
5. Sign off with: "Best regards, Support Team"
The exact escalation phrase — “will escalate this” / “get back to you shortly” — is critical. The routing node downstream checks for these phrases to decide whether to post the reply or tag for human review. Don’t change this wording unless you also update the IF condition.
4 OpenAI Chat Model (Sub-node)
This is the language model that powers the agent’s reasoning. It connects to the Agent node’s ai_languageModel input.
- Add an OpenAI Chat Model node below the Agent.
- Select
gpt-4o-minias the model — it’s fast, cheap, and accurate enough for support responses. - Set temperature to
0.3— low enough to keep answers factual, high enough to sound natural. - Set max tokens to
1024— more than enough for a support reply. - Connect your OpenAI API credential.
Tip: If you need higher-quality reasoning for complex product questions, swap to gpt-4o. The cost goes up roughly 10x per token, but accuracy improves noticeably for technical troubleshooting.
5 Ticket Conversation Memory (Postgres)
This memory node stores the conversation history for each ticket ID in a Postgres table called zendesk_ticket_histories. If a customer sends a follow-up message on the same ticket, the AI remembers what was discussed before.
- Add a Postgres Chat Memory node.
- Set the table name to
zendesk_ticket_histories. - Set the Session Key to
{{ $('Extract Ticket Data').item.json.ticket_id }}— this groups messages by ticket. - Connect your Postgres credential (Supabase’s built-in Postgres works perfectly here).
The table is created automatically on first run. It stores each message exchange so the agent has full context for multi-message tickets.
6 Knowledge Base Retrieval Tool (Vector Store)
This is the RAG component. The tool searches your Supabase vector store for the most relevant knowledge base articles and feeds them to the AI agent as context.
- Add a Vector Store Tool node and name it “Retrieve Knowledge Base”.
- Set the tool name to
knowledge_base. - Set Top K to
5— the agent will receive the 5 most relevant document chunks. - Write a clear description: “Contains all company knowledge base articles, FAQs, product documentation, and troubleshooting guides.”
7 Supabase Vector Store + OpenAI Embeddings
The Vector Store Tool needs two sub-components: a vector store (where your documents live) and an embedding model (to convert the search query into a vector).
- Add a Supabase Vector Store node. Set the table to
documentsand the query function tomatch_documents. - Add an OpenAI Embeddings node. Set the model to
text-embedding-3-smallwith 1536 dimensions. - Wire the Embeddings node into the Vector Store’s
ai_embeddinginput. - Wire the Vector Store into the Retrieve Knowledge Base tool’s
ai_vectorStoreinput.
Tip: To populate your Supabase vector store, create a separate n8n workflow that reads your KB articles (from Google Docs, Notion, or markdown files), splits them into chunks of ~500 tokens, generates embeddings with the same model (text-embedding-3-small), and inserts them into the documents table. This only needs to run once (or whenever you update your docs).
Part 3 — Smart Routing and Zendesk Actions
After the AI generates a response, the workflow needs to decide: was the response a confident answer, or did the AI punt because it couldn’t find relevant information?
8 Check If Escalation Needed (IF Node)
This IF node inspects the AI’s output text. If it contains the escalation phrases (“will escalate this” or “get back to you shortly”), the ticket goes to the human escalation path. Otherwise, it proceeds to auto-reply.
- Add an IF node after the AI Agent.
- Set the condition combinator to OR.
- Condition 1:
{{ $json.output }}containswill escalate this - Condition 2:
{{ $json.output }}containsget back to you shortly - Set case sensitivity to false.
The True branch (escalation needed) goes to the human tagging node. The False branch (AI answered) goes to the reply-posting node.
9 Tag as Human Escalation (True Branch)
When the AI can’t find an answer, this HTTP Request node calls the Zendesk API to tag the ticket with human_requested and ai_escalated. Your support team can create a Zendesk view filtered by these tags to see exactly which tickets need human attention.
- Add an HTTP Request node on the True output.
- Set Method to
PUT. - Set URL to:
https://YOUR_ZENDESK_DOMAIN.zendesk.com/api/v2/tickets/{{ $('Extract Ticket Data').first().json.ticket_id }}/tags.json - Set the JSON body to:
{ "tags": ["human_requested", "ai_escalated"] } - Set authentication to Predefined Credential Type → Zendesk API.
10 Post AI Reply to Ticket (False Branch)
When the AI has a confident answer, this node posts it as a public comment on the Zendesk ticket and sets the ticket status to “pending” (awaiting customer confirmation).
- Add an HTTP Request node on the False output.
- Set Method to
PUT. - Set URL to:
https://YOUR_ZENDESK_DOMAIN.zendesk.com/api/v2/tickets/{{ $('Extract Ticket Data').first().json.ticket_id }}.json - Set the JSON body to:
{
"ticket": {
"comment": {
"body": "{{ AI agent's output text }}",
"public": true
},
"status": "pending"
}
}
The "public": true flag means the customer sees this reply in their email and in the Zendesk portal. Setting status to "pending" tells Zendesk to wait for the customer’s next response.
11 Tag as AI Reply
After posting the reply, this final node tags the ticket with ai_reply and auto_resolved. This lets you track how many tickets the AI handles versus humans, and gives you data for measuring automation ROI.
- Add one more HTTP Request node after the reply node.
- Same pattern:
PUTto the/tags.jsonendpoint. - Body:
{ "tags": ["ai_reply", "auto_resolved"] }
The Data Structure
The workflow relies on two persistent data stores: the Supabase vector store for knowledge base content, and the Postgres table for conversation memory.
Supabase documents Table
| Column | Type | Example | Description |
|---|---|---|---|
id |
bigint | 1 | Auto-incrementing primary key |
content |
text | To reset your password, go to Settings → Security → Change Password… | The raw text chunk from your KB article |
metadata |
jsonb | {“source”: “password-reset-guide”, “section”: “steps”} | Source tracking — which article and section this chunk came from |
embedding |
vector(1536) | [0.0023, -0.0119, …] | Vector embedding generated by text-embedding-3-small |
Postgres zendesk_ticket_histories Table
| Column | Type | Example | Description |
|---|---|---|---|
session_id |
text | 48291 | The Zendesk ticket ID — groups all messages for one ticket |
message |
text | {“type”:”human”,”content”:”I can’t reset my password…”} | Individual message in the conversation |
created_at |
timestamp | 2026-04-10 14:23:00 | When the message was stored |
The zendesk_ticket_histories table is created automatically by n8n’s Postgres Chat Memory node on first execution. You don’t need to create it manually. The documents table and its match_documents function must be set up in Supabase before the workflow will work — see the Credentials Guide for full setup steps.
Full System Flow
┌─────────────────────────────────────────────────────────────────────────────┐ │ END-TO-END: TICKET ARRIVES → RESOLUTION │ │ │ │ Customer creates ticket in Zendesk │ │ ↓ │ │ Zendesk Trigger fires webhook POST │ │ ↓ │ │ [Receive New Ticket] — n8n webhook catches the request │ │ ↓ │ │ [Extract Ticket Data] — pull ticket_id, subject, description, etc. │ │ ↓ │ │ [Generate AI Response] ← GPT-4o-mini + Postgres Memory │ │ │ ← Knowledge Base Tool │ │ │ ↑ │ │ │ [Supabase Vectors] ← [OpenAI Embeddings] │ │ ↓ │ │ [Check If Escalation Needed] │ │ │ │ │ YES ├──→ [Tag: human_requested] → Human agent picks up ticket │ │ │ │ │ NO └──→ [Post AI Reply to Ticket] → Customer gets instant answer │ │ ↓ │ │ [Tag: ai_reply] → Track AI resolution rate │ └─────────────────────────────────────────────────────────────────────────────┘
Testing Your Workflow
- Activate the workflow in n8n (toggle the Active switch).
- Create a test ticket in Zendesk with a question your knowledge base can answer — for example, “How do I reset my password?”
- Check the n8n execution log — you should see the webhook trigger, data extraction, AI agent processing, and the reply being posted.
- Open the Zendesk ticket — verify the AI’s reply appears as a public comment and the ticket has the
ai_replytag. - Create a second test ticket with a question your KB does NOT cover — like “Can I get a refund for my order #12345?”
- Verify escalation — the ticket should have the
human_requestedtag and no AI reply posted.
| Problem | Likely Cause | Fix |
|---|---|---|
| Webhook never fires | Zendesk trigger not configured or wrong URL | Double-check the webhook URL in Zendesk Admin → Triggers. Make sure the trigger condition is “Ticket is Created.” |
| AI returns generic/wrong answers | Knowledge base not populated or embeddings mismatch | Verify your documents table has content. Ensure you used text-embedding-3-small with 1536 dimensions when inserting docs. |
| AI always escalates | Vector search returns no results | Check that the match_documents Postgres function exists in Supabase and the table name matches exactly. |
| Reply not appearing on ticket | Zendesk API auth error or wrong domain | Verify your Zendesk API credential has write access and the domain in the URL matches your subdomain (e.g., mycompany.zendesk.com). |
| “401 Unauthorized” on tag update | Zendesk credential lacks admin scope | The API token needs to be created by an admin user. Go to Admin → Channels → API and generate a new token. |
Frequently Asked Questions
How much does it cost to run this per ticket?
With GPT-4o-mini and text-embedding-3-small, the average cost is about $0.002–$0.005 per ticket (input + output tokens combined). If you process 1,000 tickets per month, that’s roughly $2–$5/month in OpenAI costs. Supabase’s free tier handles up to 500MB of vector data, which is plenty for most knowledge bases.
Can I use this with Zendesk’s free plan?
No — you need API access and the ability to create triggers/webhooks, which requires Zendesk Suite Team or higher. The trigger feature that sends webhook notifications on ticket creation is not available on the free/lite plans.
What happens if the AI gives a wrong answer?
Since the agent is configured with strict RAG-only instructions and a low temperature (0.3), hallucinations are rare. But they can happen. We recommend reviewing AI-tagged tickets weekly during the first month and adjusting your KB content where gaps appear. You can also lower the temperature to 0.1 for even more conservative responses.
Can I add more languages to the knowledge base?
Yes. OpenAI’s embedding model supports 100+ languages natively. If your KB articles are in Spanish or French, the vector search will still work — the embedding model handles cross-lingual similarity. Just make sure your system prompt tells the agent to reply in the customer’s language.
How do I update the knowledge base when we add new articles?
Create a second n8n workflow that watches your documentation source (Google Drive, Notion, or a webhook from your CMS). When a document changes, the workflow re-chunks it, generates new embeddings, and upserts them into the Supabase documents table. This keeps your AI current without manual intervention.
Does this work with Freshdesk, Intercom, or other helpdesks?
The core RAG pipeline (AI Agent + Supabase + Embeddings) works with any helpdesk that has a webhook or API. You’d swap the Zendesk-specific webhook trigger and HTTP Request nodes for the equivalent in your helpdesk. The logic is identical — only the API endpoints change.
Get the AI Zendesk Support Template
Skip the 60-minute build. Get the complete workflow JSON, Supabase setup instructions, and a step-by-step credentials guide — paste your API keys and go live in under 10 minutes.
Instant download · Works on n8n Cloud and self-hosted
What’s Next?
- Add a satisfaction survey — after the AI replies, send a follow-up asking the customer to rate the response. Use the rating to fine-tune your KB.
- Build a KB ingestion pipeline — automate the process of embedding new documentation into Supabase whenever you publish a new help article.
- Add Slack notifications for escalations — when a ticket is tagged
human_requested, send a Slack message to your support channel so agents can pick it up immediately. - Track AI resolution rate — build a simple dashboard (Google Sheets or Metabase) that counts
ai_replyvshuman_requestedtags over time to measure your automation ROI.