I’m building a Voice AI Receptionist (Vapi/ElevenLabs → n8n Webhook) and need advice on handling state across multiple executions.
For a booking use case, I don’t want to rely on “Simple Memory” (which feels too “fuzzy”). I need a deterministic way to track things like date_selected, availability_checked, and confirmed_status.
The approach I’m considering:
Start: Fetch session data from n8n Data Tables or a DB via sessionId.
Process: Pass this state into the AI prompt to guide the conversation.
End: Update the DB/Table with new variables before the workflow finishes.
My Questions:
Is an external DB/Data Table the standard way to handle “hard” state in n8n, or is there a more “native” way to pass variables between executions?
Should I keep the logic in one stateful workflow, or is it better to move the logic into Tools (e.g., the AI calls a “Book Appointment” workflow)?
Does anyone have a simple template or example of this “Load → Process → Save” pattern?
I’m trying to avoid over-engineering, but I need the booking process to be bulletproof. Thanks for any guidance!
@wilson3 a colleague of mine has built a few voice assistants in n8n and ran into this exact issue, the per-message webhook starting fresh every time kills any built-in memory.
They ended up using a Postgres table for session state. The logic was to key it by the Call ID, load the entire context at the start of the workflow, and feed it to the AI along with the new transcript. They then updated the row before the execution finished. It’s a solid approach because it doesn’t rely on the LLM to “remember” steps correctly, and it allows you to add fallback logic in n8n if the AI attempts to update the state incorrectly.
This is super helpful, thank you that’s exactly the conclusion I was starting to reach as well.
Feeding the full context plus the new transcript into the AI, then updating state after, makes a lot more sense than relying on memory.
Quick question: did your colleague mainly store structured state (fields / flags), or did he also keep a running conversation summary? And how did he handle cases where the user wanted to change details after the booking went through?
He actually used a hybrid approach within the Postgres table. If you’re looking at the Postgres node schema, it usually looked like this:
Structured Fields: Specific columns like appointment_date, service_type, and guest_count. These are “hard” values that n8n uses to trigger the final booking API or check availability.
The “Context” Column: A JSONB or TEXT column that stored a brief, rolling summary of the conversation.
Why both? The structured fields are for the logic (deterministic), while the summary helps the AI keep the “vibe” and specific details that don’t have a column, like “User mentioned they are nervous about needles” or “Prefers the window seat.” In the AI Agent node, he would pull both and inject them into the System Prompt so the AI felt like it had a continuous memory.