WhatsApp + OpenAI: faster replies with voice and PDFs
Your WhatsApp inbox turns into a messy mix of “quick question” texts, voice notes you can’t search, and PDFs you have to open just to find one line. Then you reply. Then you reply again. And again. Same info, slightly different wording, every day.
This WhatsApp OpenAI automation hits support leads first, honestly. But consultants answering client questions and small business owners handling sales DMs feel it too. The outcome is simple: consistent answers with context, delivered faster, even when the customer sends voice or documents.
This workflow turns WhatsApp messages into an AI-assisted conversation that can transcribe audio, read PDFs, remember prior messages, and pull answers from a knowledge base. You’ll see what it does, what you need, and where teams usually trip up.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: WhatsApp + OpenAI: faster replies with voice and PDFs
flowchart LR
subgraph sg0["OpenAI Embeddings B Flow"]
direction LR
n0@{ icon: "mdi:brain", form: "rounded", label: "ChatGPT Model Core", pos: "b", h: 48 }
n20@{ icon: "mdi:vector-polygon", form: "rounded", label: "OpenAI Embeddings B", pos: "b", h: 48 }
n21@{ icon: "mdi:brain", form: "rounded", label: "ChatGPT Model RAG", pos: "b", h: 48 }
n23@{ icon: "mdi:wrench", form: "rounded", label: "Scheduling Tool", pos: "b", h: 48 }
n25["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Fetch Prompt"]
n26@{ icon: "mdi:memory", form: "rounded", label: "Postgres Chat Memory Main", pos: "b", h: 48 }
n36["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>RAG Summaries"]
n37@{ icon: "mdi:cog", form: "rounded", label: "Aggregate DB Data B", pos: "b", h: 48 }
n38@{ icon: "mdi:cube-outline", form: "rounded", label: "Supabase Vector Store B", pos: "b", h: 48 }
n39@{ icon: "mdi:wrench", form: "rounded", label: "Remove RAG File", pos: "b", h: 48 }
n40@{ icon: "mdi:wrench", form: "rounded", label: "Email Tool", pos: "b", h: 48 }
n41@{ icon: "mdi:wrench", form: "rounded", label: "Add Knowledge Tool", pos: "b", h: 48 }
n42@{ icon: "mdi:wrench", form: "rounded", label: "Search Knowledge Tool", pos: "b", h: 48 }
n48["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Combine Streams"]
n49@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Condition Router", pos: "b", h: 48 }
n50@{ icon: "mdi:cog", form: "rounded", label: "Run Sub-Workflow (Configure ..", pos: "b", h: 48 }
n51@{ icon: "mdi:swap-vertical", form: "rounded", label: "Process Handling", pos: "b", h: 48 }
n53@{ icon: "mdi:robot", form: "rounded", label: "Assistant Agent", pos: "b", h: 48 }
n54@{ icon: "mdi:robot", form: "rounded", label: "Intent Classifier", pos: "b", h: 48 }
n56@{ icon: "mdi:wrench", form: "rounded", label: "Remove Knowledge Tool", pos: "b", h: 48 }
n58@{ icon: "mdi:swap-vertical", form: "rounded", label: "Client Message", pos: "b", h: 48 }
n61@{ icon: "mdi:memory", form: "rounded", label: "Postgres Chat Memory Aux", pos: "b", h: 48 }
n63@{ icon: "mdi:wrench", form: "rounded", label: "RAG Tool Node", pos: "b", h: 48 }
n63 -.-> n53
n48 --> n54
n49 --> n51
n49 --> n53
n40 -.-> n53
n51 --> n50
n23 -.-> n53
n25 --> n48
n58 --> n25
n58 --> n36
n20 -.-> n38
n0 -.-> n53
n0 -.-> n54
n21 -.-> n63
n42 -.-> n53
n39 -.-> n53
n37 --> n48
n26 -.-> n53
n56 -.-> n53
n61 -.-> n54
n38 -.-> n63
n41 -.-> n53
n54 --> n49
end
subgraph sg1["OpenAI Connector Flow"]
direction LR
n1@{ icon: "mdi:cog", form: "rounded", label: "Generate File Output", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-vertical", form: "rounded", label: "Map Fields A", pos: "b", h: 48 }
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "Map Fields B", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Authorization Check", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/redis.svg' width='40' height='40' /></div><br/>Message List Cache"]
n11@{ icon: "mdi:robot", form: "rounded", label: "OpenAI Connector", pos: "b", h: 48 }
n16@{ icon: "mdi:swap-vertical", form: "rounded", label: "File Identifier", pos: "b", h: 48 }
n17["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Remove Old Files"]
n43@{ icon: "mdi:cog", form: "rounded", label: "Generate File Output B", pos: "b", h: 48 }
n44@{ icon: "mdi:swap-vertical", form: "rounded", label: "Base Payload", pos: "b", h: 48 }
n45@{ icon: "mdi:swap-vertical", form: "rounded", label: "Adjust Fields A", pos: "b", h: 48 }
n46@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Message Type Switch", pos: "b", h: 48 }
n47@{ icon: "mdi:robot", form: "rounded", label: "OpenAI Connector B", pos: "b", h: 48 }
n52["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Incoming Webhook Trigger"]
n57@{ icon: "mdi:swap-vertical", form: "rounded", label: "Configuration Set", pos: "b", h: 48 }
n59@{ icon: "mdi:swap-vertical", form: "rounded", label: "Initial Client Message", pos: "b", h: 48 }
n4 --> n46
n44 --> n43
n2 --> n59
n3 --> n59
n11 --> n2
n57 --> n4
n47 --> n45
n52 --> n57
n16 --> n17
n45 --> n59
n46 --> n16
n46 --> n1
n46 --> n44
n46 --> n3
n1 --> n11
n43 --> n47
n59 --> n9
end
subgraph sg2["Default Document Loa Flow"]
direction LR
n13@{ icon: "mdi:robot", form: "rounded", label: "Default Document Loader", pos: "b", h: 48 }
n14@{ icon: "mdi:vector-polygon", form: "rounded", label: "OpenAI Embeddings A", pos: "b", h: 48 }
n15@{ icon: "mdi:robot", form: "rounded", label: "Recursive Text Splitter", pos: "b", h: 48 }
n18@{ icon: "mdi:cog", form: "rounded", label: "Extract PDF Text", pos: "b", h: 48 }
n19@{ icon: "mdi:swap-vertical", form: "rounded", label: "Output Text", pos: "b", h: 48 }
n22@{ icon: "mdi:cube-outline", form: "rounded", label: "Supabase Vector Store", pos: "b", h: 48 }
n28@{ icon: "mdi:cog", form: "rounded", label: "Convert File A", pos: "b", h: 48 }
n29@{ icon: "mdi:swap-vertical", form: "rounded", label: "Base64 Prep", pos: "b", h: 48 }
n30@{ icon: "mdi:swap-horizontal", form: "rounded", label: "File Type Router", pos: "b", h: 48 }
n29 --> n28
n18 --> n19
n30 --> n18
n19 --> n22
n28 --> n30
n14 -.-> n22
n13 -.-> n22
n15 -.-> n13
end
subgraph sg3["Generate Summary Flow"]
direction LR
n31@{ icon: "mdi:brain", form: "rounded", label: "ChatGPT Summary Model", pos: "b", h: 48 }
n33@{ icon: "mdi:robot", form: "rounded", label: "Generate Summary", pos: "b", h: 48 }
n35["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Update File List"]
n60["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Delete File Record"]
n33 --> n35
n60 --> n33
n31 -.-> n33
end
subgraph sg4["Flow 5"]
direction LR
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/redis.svg' width='40' height='40' /></div><br/>Retrieve Messages"]
n7@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Conditional Gate 1", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Adjust Fields B", pos: "b", h: 48 }
n7 --> n10
n6 --> n7
end
subgraph sg5["Flow 6"]
direction LR
n55@{ icon: "mdi:cog", form: "rounded", label: "Aggregate DB Data C", pos: "b", h: 48 }
end
subgraph sg6["Flow 7"]
direction LR
n34["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Create RAG Control"]
end
subgraph sg7["Flow 8"]
direction LR
n32@{ icon: "mdi:cog", form: "rounded", label: "Aggregate DB Data A", pos: "b", h: 48 }
end
subgraph sg8["Flow 9"]
direction LR
n62["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Delete Knowledge Entry"]
end
subgraph sg9["Flow 10"]
direction LR
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Create Knowledge DB"]
end
subgraph sg10["Flow 11"]
direction LR
n27["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Clear All Messages"]
end
subgraph sg11["Flow 12"]
direction LR
n12["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Init Vector Tables"]
end
subgraph sg12["Flow 13"]
direction LR
n5@{ icon: "mdi:cog", form: "rounded", label: "Delay Message Send", pos: "b", h: 48 }
end
subgraph sg13["Flow 14"]
direction LR
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/redis.svg' width='40' height='40' /></div><br/>Redis Store"]
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n53,n54,n11,n47,n13,n15,n33 ai
class n0,n21,n31 aiModel
class n23,n39,n40,n41,n42,n56,n63 ai
class n26,n61 ai
class n38,n22 ai
class n20,n14 ai
class n49,n4,n46,n30,n7 decision
class n25,n36,n9,n35,n60,n6,n34,n62,n24,n27,n12,n8 database
class n52 api
classDef customIcon fill:none,stroke:none
class n25,n36,n48,n9,n17,n52,n35,n60,n6,n34,n62,n24,n27,n12,n8 customIcon
The Challenge: Fast Replies When Messages Aren’t “Readable”
Most WhatsApp support and sales conversations don’t come in neatly. A customer sends a voice note while driving. Another drops a PDF invoice and says “can you check page 3.” Someone else asks a question you answered yesterday, but you can’t remember what you said, and scrolling back through chat history feels like a punishment. Even worse, you reply quickly but inconsistently, so your “official” answer changes depending on who’s holding the phone that day.
The friction compounds. Not because one message is hard, but because you repeat the same micro-tasks dozens of times.
- Voice notes force you to stop, listen, replay, and guess what the person meant.
- PDFs and documents slow everything down since the answer is inside a file, not the chat.
- Without memory, you ask customers to repeat themselves, which makes you look disorganized.
- Copy-paste “templates” drift over time, and your team ends up sending conflicting information.
The Fix: An AI WhatsApp Assistant That Reads, Listens, and Remembers
This workflow starts when a message hits your WhatsApp webhook (commonly through a provider like Evolution API). It checks authorization settings first, so you can limit responses to an admin number during testing or keep it open for customer support later. From there, it routes the message by type: text goes one way, voice notes get transcribed with OpenAI, and documents like PDFs get processed so the content becomes searchable text. Once the message is “understandable,” an AI agent (GPT-4o via OpenAI’s chat model) uses your saved prompt plus chat memory stored in Postgres to respond consistently and in context.
When a user sends a document, the workflow can also index it into a Supabase vector database (RAG) so future questions can be answered from that file without you re-opening it. Finally, the automation sends the response back through the same WhatsApp channel, with optional delays to bundle messages so replies feel natural instead of spammy.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say your inbox gets 30 WhatsApp messages a day. If 10 are voice notes (about 3 minutes each to listen and replay), and another 10 involve PDFs or attachments (maybe 5 minutes each to open, search, and respond), that’s roughly 80 minutes of pure “decode the message” work. With this workflow, you skim transcriptions and AI-drafted answers instead. You might spend 10 minutes reviewing and correcting, then hit send. That’s about an hour back on a normal day.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- WhatsApp provider (Evolution API) to receive and send WhatsApp messages
- OpenAI for GPT-4o responses and Whisper transcription
- Supabase to store embeddings for document Q&A (RAG)
- PostgreSQL for chat memory and prompt storage
- Redis to buffer and group incoming messages
- OpenAI API key (get it from your OpenAI dashboard)
Skill level: Intermediate. You’ll be comfortable adding credentials, running SQL once, and testing webhooks end-to-end.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
A WhatsApp message triggers the workflow. Your provider calls an n8n webhook, then the workflow loads configuration (like the admin number and API key settings) and checks if this sender is allowed.
The message gets normalized. A router detects if it’s text, audio, or a file. Audio becomes text via OpenAI transcription, and documents are converted into plain text so the assistant can actually “read” them.
AI responds with context. The workflow pulls your current system prompt from Postgres, loads conversation memory for that user session, and sends everything into an AI agent. If the question needs knowledge lookup, it uses the Supabase vector store to retrieve relevant snippets before generating a reply.
Replies go back to WhatsApp (and your data stores stay updated). The assistant response is formatted for sending, optionally delayed to avoid rapid-fire messages, then delivered through your WhatsApp API. If a new document came in, the workflow also saves a summary and indexing metadata so it becomes usable later.
You can easily modify the authorization rules to handle all customers instead of admin-only, based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Webhook Trigger
Set up the entry point for incoming requests so the workflow can receive and validate messages before any processing begins.
- Add the Incoming Webhook Trigger node and copy its production URL for external calls.
- Connect Incoming Webhook Trigger to Configuration Set to initialize base parameters.
Step 2: Connect Core Datastores and Caches
This workflow relies on Redis, Postgres, and Supabase for message history, configuration, and vector storage. Connect these services early to avoid downstream failures.
- Open each Redis node (Retrieve Messages, Redis Store, Message List Cache) and connect your Redis instance.
- Open each Postgres node used for data operations (Init Vector Tables, Create Knowledge DB, Fetch Prompt, Clear All Messages, Create RAG Control, Update File List, RAG Summaries, Delete File Record, Delete Knowledge Entry) and connect your Postgres database.
- Open Remove Old Files and connect your Supabase credentials for file cleanup.
- Open Supabase Vector Store and Supabase Vector Store B and connect your Supabase credentials for vector database operations.
Step 3: Configure Message Intake, Authorization, and Routing
This step ensures the workflow properly validates incoming payloads and routes messages to the correct processing branch.
- In Configuration Set, map incoming webhook fields into a standardized payload.
- Connect Configuration Set to Authorization Check to validate allowed senders or tokens.
- From Authorization Check, route approved messages into Message Type Switch for branching.
- Ensure Message Type Switch outputs to File Identifier, Generate File Output, Base Payload, and Map Fields B for the supported message types.
- Connect Retrieve Messages → Conditional Gate 1 → Adjust Fields B to control message list retrieval logic.
Step 4: Set Up File Handling and RAG Ingestion
These nodes handle file conversion, text extraction, and vector storage for retrieval-augmented generation (RAG).
- Connect Base64 Prep → Convert File A → File Type Router to normalize incoming file payloads.
- Route file text extraction through File Type Router → Extract PDF Text → Output Text.
- Connect Output Text to Supabase Vector Store to index the extracted text for RAG.
- Use File Identifier → Remove Old Files to clean up outdated Supabase files.
- Ensure the cleanup and summary flow is connected: Delete File Record → Generate Summary → Update File List.
Step 5: Configure AI Models, Embeddings, and Memory
These AI components power classification, summarization, and assistant responses.
- Connect OpenAI credentials to ChatGPT Model Core, ChatGPT Model RAG, and ChatGPT Summary Model for language model access.
- Connect OpenAI credentials to OpenAI Embeddings A and OpenAI Embeddings B to generate vector embeddings.
- Verify Recursive Text Splitter → Default Document Loader → Supabase Vector Store for document chunking and ingestion.
- Ensure Postgres Chat Memory Main is connected to Assistant Agent and Postgres Chat Memory Aux is connected to Intent Classifier to preserve chat history.
- Confirm OpenAI Connector → Map Fields A and OpenAI Connector B → Adjust Fields A for AI-driven payload preparation.
Step 6: Configure Intent Classification, Parallel Prompting, and Merging
This stage merges prompt context with cached data and routes by intent.
- Ensure Initial Client Message writes to Message List Cache after processing Map Fields A, Map Fields B, and Adjust Fields A.
- Client Message outputs to both Fetch Prompt and RAG Summaries in parallel.
- Combine the parallel outputs using Aggregate DB Data B → Combine Streams.
- Route the merged output to Intent Classifier and then to Condition Router for downstream decision-making.
Step 7: Configure Assistant Tools and Sub-Workflow Execution
These tools extend the assistant’s capabilities and trigger external workflows.
- Connect Condition Router to Process Handling, then to Run Sub-Workflow (Configure Required) to execute downstream actions.
- Attach tools to Assistant Agent: Scheduling Tool, Email Tool, Add Knowledge Tool, Search Knowledge Tool, Remove Knowledge Tool, and Remove RAG File.
- Attach RAG Tool Node to Assistant Agent for vector search capabilities.
- Ensure Postgres Chat Memory Main is connected to Assistant Agent and Postgres Chat Memory Aux is connected to Intent Classifier for memory support.
Step 8: Test and Activate Your Workflow
Validate the workflow end-to-end before turning it on in production.
- Use Incoming Webhook Trigger to send a sample payload and click Execute Workflow.
- Confirm successful routing through Authorization Check, Message Type Switch, and the parallel branches from Client Message.
- Verify vector ingestion by checking outputs from Supabase Vector Store and Supabase Vector Store B.
- Check that Assistant Agent produces a response and that any tool outputs are triggered as expected.
- Once validated, toggle the workflow to Active for production use.
Watch Out For
- Evolution API credentials can expire or need specific permissions. If things break, check your Evolution API key and webhook delivery logs first.
- If you’re using Wait nodes or external processing (like file conversion), processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Common Questions
Plan for an afternoon if you already have your WhatsApp provider, OpenAI key, and databases ready.
Yes, but you will want one technical person for the first setup. The SQL initialization, credentials, and webhook testing are the parts that usually need help.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API costs (often a few dollars a month at low volume, more if you transcribe lots of audio or process many documents).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
You can adjust the Configuration Set and Authorization Check logic to control who the assistant responds to, and tune the assistant’s behavior by editing the prompt stored in Postgres (the workflow fetches it before responding). Common customizations include changing your brand tone, adding a stricter “only answer from approved docs” rule, and swapping the retrieval source (Supabase RAG vs. a simpler FAQ table) depending on how sensitive your answers are.
Usually it’s an invalid key or the webhook isn’t reaching n8n. Confirm the provider is sending requests to the correct webhook URL, then update the Evolution API token in the workflow’s config and re-test with a fresh message. If it works for a few minutes and then stops, look for rate limits or blocked outbound requests from your hosting environment.
It depends more on your hosting and OpenAI rate limits than the workflow itself.
For this workflow, n8n has a few advantages: you can self-host for unlimited executions, handle branching logic without paying more for “paths,” and run database-backed memory plus RAG in one place. Zapier and Make can connect WhatsApp to AI, sure, but they get awkward fast when you add voice transcription, file handling, and a knowledge base that needs indexing. Also, running webhooks and long-running flows is generally smoother in n8n. If you only need “incoming message → AI → reply” and nothing else, simpler tools can be enough. Talk to an automation expert if you’re not sure which fits.
Once this is running, your inbox stops being a memory test. The workflow handles the repetitive decoding and drafting, so you can focus on the few messages that actually need a human.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.