How to Keep AI Agent Memory Separate for Each User (4 Isolation Patterns)
Your scheduled agent runs fine for months. Then one Monday it greets Client B with Client A's pricing, quotes a discount only Client A got, and summarizes a deal you discussed with Client A last week. Nobody changed the prompt. Nobody touched the workflow. The memory just bled across the boundary between two users.
This is the multi-tenant memory problem, and scheduled automations are where it bites hardest. A chatbot session is at least anchored to one conversation. A scheduled agent wakes up on a cron trigger, pulls from a shared store, and runs with whatever it finds. If that store has no per-user boundary, every run is a potential cross-contamination event. The good news: isolation is a solved problem at the pattern level. Here are the four patterns operators actually use, in order of strength.
Pattern 1: Namespace every key
The cheapest fix, and the one most people reach for first: put the user (or tenant, or client) into every memory key and every query filter.
If you keep facts in Postgres, every row carries a user_id, and every SELECT filters on it. If you use Redis, keys look like memory:{user_id}:{topic} instead of memory:{topic}. If you keep summaries in files, the directory structure mirrors the tenant structure. The rule: a memory lookup that does not mention the user can return someone else's memory.
The trap is that this is a convention, not a guarantee. It works only as long as every workflow, every helper, and every future version of your agent remembers to apply the filter. One query written in a hurry without the WHERE user_id = ... clause, one new automation that reuses the shared connection string without the prefix, and the boundary is gone. Namespacing is retroactive-blind: if the store already holds unscoped memories from before you added the convention, those memories are effectively global.
Use it when you are a solo operator serving a handful of users and you control every query path. The moment a second person edits the workflows, move up.
Pattern 2: Separate stores per tenant
Stronger, and correspondingly heavier: give each tenant their own physical store. One database schema per client. One Redis database index per client. One collection per client in your vector store. The isolation stops being a filter and becomes an address.
The advantage is that the common failure modes disappear. A forgotten filter cannot leak data because the data is not there to be filtered out. A new automation cannot accidentally read the wrong tenant's memories because it cannot reach the wrong tenant's store. Deletion becomes predictable too: when a client leaves, you drop their schema instead of hunting for scattered rows across a shared table.
The price is operations: connection pools, backups, and schema migrations all multiply. Fifty clients means fifty stores. For n8n or Make, it usually means one workflow per client instead of one workflow serving all clients, which is a bigger commitment than it sounds.
Use pattern 2 when the data is sensitive enough that a leak is a contract breach, not just an embarrassment: financial data, health-adjacent data, anything under an NDA. Accept the ops cost as the price of a guarantee.
Pattern 3: Scope the session key per user
If your agent framework has a built-in memory node, this pattern lives in one field: the session key. In n8n's memory nodes, the session key defaults to the execution ID, which means every run starts blank; operators who want continuity change it to a stable value like the workflow name. The isolation version of that fix is a stable key that is also user-scoped: client-acme-support, client-beta-support.
You get per-user continuity inside one workflow: one schedule, many clients, each with their own memory. It also has the sharpest edge of the four patterns. A session key shared across users mixes their histories; a session key that changes every run forgets everything. The failure mode is silent in both directions: nothing errors, the agent starts quoting the wrong client or starts from zero.
Guard it with a startup check: before the agent acts, have it retrieve one known fact about the current user and confirm it matches the run's context. If the fact belongs to someone else, halt the run.
Use pattern 3 when one scheduled workflow genuinely serves many users and you need per-user continuity without rebuilding your infrastructure.
Pattern 4: Use a memory layer with isolation built in
The DIY patterns above all share a weakness: the boundary is something you built, and something you built can be broken by the next person who edits the workflow. Pattern 4 outsources the boundary to a system whose job is memory and nothing else.
A hosted memory layer sits between your agents and their recollection. Your scheduled agents read and write through it, and the isolation rule lives in the service rather than in your queries. This is where the tradeoff flips: you give up control over the exact mechanism, and in exchange the "forgot the filter" failure mode disappears because there is no filter for you to forget.
Vilix AI is built this way. It is cloud-hosted and reached over MCP, so there is nothing to run. The isolation boundary is the account: data is isolated per user, and every connected AI tool reads the same memory through the same account. For a solo operator, that is the shape you want: your n8n workflows, your coding agents, and your phone assistant all share one memory, and there is exactly one tenant in the system, so there is nothing to leak across.
The honest tradeoff: because the boundary is per account, an agency running scheduled agents for many clients from one account does not get per-client namespaces inside that account. The isolation mechanism is one account per client. That is heavier than a user_id filter, and also harder to break by accident.
It stores full conversation history, not just extracted facts, and retrieval combines semantic and keyword matching, so the agent finds what it meant, not just what it typed. The plan structure is straightforward: a free plan forever, a 7-day Pro trial with no credit card, and you can export everything or wipe the account instantly. The product page has the current pricing if you want the numbers.
The leak test you should run this week
Whichever pattern you use, verify it the same way. Pick a fact that exists in exactly one user's memory, then run the agent in a different user's context and ask about it. If the agent knows, the boundary is broken. This is a five-minute test, and it catches the two most common real-world failures: the filter someone forgot in a new workflow, and the session key that quietly stopped being user-scoped after a workflow edit.
Scheduled agents forget everything between runs by default. That is a fixable problem. What is not acceptable is an agent that remembers, but remembers the wrong user's data. Isolation is the part of agent memory that is about trust, not convenience, and it is worth getting right before the first leak instead of after.
Top comments (0)