Zapier's OpenAI and ChatGPT actions are stateless by design. Each Zap run is independent — the AI receives exactly what you put in the prompt for that run and nothing more. No memory of previous runs, no knowledge of who this person is, no context beyond the current trigger data.
For most Zaps this is fine. For AI workflows that handle the same customers repeatedly — support, sales, onboarding — it means every interaction starts from zero. This tutorial shows how to fix that.
What You Need
- Zapier Starter plan or above (multi-step Zaps)
- retainr account — free at retainr.dev/dashboard (1,000 ops/month free)
- An existing Zap with an OpenAI or ChatGPT action step
The Architecture
Adding memory to a Zapier OpenAI Zap requires two additional steps:
Trigger
→ Webhooks GET (retrieve memory before AI)
→ Formatter (optional: join array to string)
→ OpenAI action (prompt includes memory context)
→ Webhooks POST (store this interaction after AI)
→ [rest of your Zap]
The two Webhooks steps are the memory layer. Everything else stays the same.
Step 1: Add the Webhooks GET action
Before your OpenAI action, add a Webhooks by Zapier action:
Setup tab:
- Action Event: GET
- URL:
https://api.retainr.dev/v1/memories/search
Query string params (add each as a separate row):
namespace→ map the customer identifier from your trigger (e.g., email field)q→ map the subject, question, or current contextlimit→5
Headers:
Authorization→Bearer YOUR_API_KEY
Leave all other fields at defaults. Test the step — for a new customer it returns {"results":[]}. That is correct.
Step 2: Add the Formatter step (if needed)
Zapier's OpenAI action expects text inputs. The Webhooks GET returns a JSON array. If you need to inject multiple memories into the prompt, add a Formatter by Zapier step:
- Transform: Utilities
- Transform: Line Formatter
- Input: map the
Resultsarray from the Webhooks GET - Separator:
\n
This produces a single text block you can drop into the OpenAI system prompt.
If you only need the first result, skip this step and map Results: (1) Content directly.
Step 3: Update your OpenAI action
In your existing OpenAI action, update the System or User Message field to include the memory:
System message:
You are a helpful assistant.
Prior context for this customer:
[map Formatter output or Webhooks GET Results here]
If no prior context exists, treat this as a first interaction.
Map the Formatter output (or Webhooks GET result) into the prompt. The AI now receives relevant customer history before generating every response.
Step 4: Add the Webhooks POST action
After your OpenAI action, add another Webhooks by Zapier action:
Setup tab:
- Action Event: POST
- URL:
https://api.retainr.dev/v1/memories
Data (payload):
namespace→ same value you used in the GET stepcontent→ a summary of this interaction (map from your trigger + OpenAI output)
Headers:
Authorization→Bearer YOUR_API_KEYContent-Type→application/json
Payload Type: JSON
Store 1-3 sentences — the topic and a summary of the AI response. Avoid storing full AI outputs verbatim; concise summaries retrieve better on future searches.
Namespace Examples
The namespace field is how retainr scopes memory. Use any stable unique identifier:
| Trigger | Namespace to use |
|---|---|
| Gmail — new email | email:{{From Email}} |
| HubSpot — contact update | hubspot:{{Contact ID}} |
| Typeform — new response | user:{{Respondent Email}} |
| Zendesk — new ticket | zendesk:{{Requester Email}} |
| Airtable — record update | airtable:{{Record ID}} |
| Webhook trigger | user:{{any unique field}} |
Real-World Example: Customer Support Zap
Before (without memory):
- Zendesk — New Ticket
- OpenAI — Draft reply (generic, no customer context)
- Zendesk — Add reply
After (with memory):
- Zendesk — New Ticket
- Webhooks GET — search
zendesk:{{requester_email}}for past tickets - Formatter — join results into text
- OpenAI — Draft reply with customer history in system prompt
- Webhooks POST — store this ticket's topic and resolution
- Zendesk — Add reply
The AI now knows this customer opened three billing tickets over the past six months. It can acknowledge the pattern, escalate appropriately, or offer a proactive fix.
Debugging Common Issues
"The AI is ignoring the memory context" Put the memory in the System message, not the User message. System prompt instructions have higher weight. Also ensure the memory block isn't empty — test with a customer who has existing memories.
"Getting [object Object] instead of text"
The Webhooks GET returns JSON. If you map the array directly to a text field, Zapier renders it as [object Object]. Add the Formatter step to convert the array to a newline-separated string.
"No results returned on GET"
Check the namespace is identical in both GET and POST steps. A mismatch means the search looks in the wrong memory bucket. Also verify the Authorization header is set correctly with Bearer (including the space) before your API key.
"Zap is too slow" The Webhooks GET adds ~50-100ms. The Formatter adds ~0ms (client-side transform). If your Zap feels slow, the bottleneck is the OpenAI step, not the memory layer.
Give your AI agents a real memory
Free plan includes 1,000 memory operations/month. No credit card required.
Add memory to your Zapier OpenAI Zap — free plan →Frequently Asked Questions
Does this work with Zapier's native AI by Zapier actions? Yes. The same Webhooks GET and POST pattern works with any Zapier AI action. The memory layer is model-agnostic.
Can I use retainr across multiple Zaps for the same customer? Yes. Any Zap that uses email:{customer_email} as the namespace reads and writes to the same memory pool. A support Zap and a sales Zap share the same customer history if they use the same namespace.
What happens if retainr is down? Add an error handler to your Zap. Use Zapier's Error Handler step or a Filter step after the Webhooks GET: if the response status is not 200, continue with an empty context rather than halting. Your Zap should always fail open — generate a response without memory rather than fail entirely.
How do I delete a customer's memory? Add a Webhooks DELETE action to https://api.retainr.dev/v1/memories?namespace={namespace}. Map the namespace from your trigger. Use this in a GDPR deletion Zap or a user-initiated reset flow.
Add memory to any Zapier Zap
Working with a specific app? These guides cover the exact setup:
- Zapier Gmail AI Memory — Per-sender memory for Gmail Zaps
- Zapier HubSpot AI Memory — CRM-aware AI memory for HubSpot Zaps
- Zapier Zendesk AI Memory — AI memory for Zendesk support Zaps
- Zapier Airtable AI Memory — Persistent memory for Airtable Zaps
- Zapier WhatsApp AI Memory — Persistent memory for WhatsApp Zaps