One Agent, Many Clients: Whose Memory Is Whose?
One Agent, Many Clients: Whose Memory Is Whose? You run automations for clients. One nightly workflow researches leads for six of them: same agent, same prompt, six different inboxes. Tuesday morning the summary for Client B opens with "following up on the pricing change you mentioned last week." Client B never mentioned a pricing change. Client A did. Nothing broke. The workflow ran green, the research was solid, the email went out on time. The agent simply reached into a memory that had no w
One Agent, Many Clients: Whose Memory Is Whose?
You run automations for clients. One nightly workflow researches leads for six of them: same agent, same prompt, six different inboxes. Tuesday morning the summary for Client B opens with "following up on the pricing change you mentioned last week." Client B never mentioned a pricing change. Client A did.
Nothing broke. The workflow ran green, the research was solid, the email went out on time. The agent simply reached into a memory that had no walls and pulled out somebody else's facts.
This is the failure mode nobody demos. Every tutorial shows one agent serving one user. The moment one agent serves many clients, memory stops being a convenience and becomes a liability question: whose memory is whose?
Why sharing is the default
Memory nodes in automation platforms are keyed by session, and the default session is the workflow, not the client. In n8n, an AI Agent's memory node stores conversation turns against a session key. Scope that key per client and each client gets their own thread. Leave one key for the whole workflow, or forget to thread the client id through, and every client's facts land in the same bucket. The agent cannot tell them apart because you never told it they were apart.
The DIY setups have the same trap in a different shape. A shared Postgres table or vector store with a client_id column works until one query forgets the filter. And the big platforms' AI steps reset between runs anyway, so operators compensate with shared knowledge sources that are, by design, visible to everything the agent does. Shared by default, isolated by effort. Most teams never put in the effort until the first leak.
The loop bleed
Scheduled runs make it worse in a way that is easy to miss. Picture the nightly workflow looping over clients: it processes Client A, then Client B, then Client C, all inside one execution. The agent's context window carries forward. By the time it drafts Client C's summary, it is still "remembering" details from Client A's turn. No memory node was even involved. The bleed happened in the working context itself.
The fix is a discipline, not a feature: isolate each client iteration. Flush or reset the agent's context between clients, key every memory read and write by client id, and never let one client's turn inherit another's scratch state. If your loop cannot reset between iterations, split it into one execution per client. It costs a few more runs. It costs far less than an apology email.
Two buckets, deliberately
Not everything should be isolated. There are exactly two kinds of memory in a multi-client setup, and they want opposite treatment:
Per-client memory must never cross. Preferences, pricing, contacts, conversation history, anything the client told you in confidence. This is the bucket where a leak is a breach of trust, and sometimes a breach of contract.
Playbook memory should be shared. The follow-up cadence that converts, the triage rules that catch bad leads, the objections that come up every time and the answers that work. When Client D benefits from what you learned serving Clients A through C, that is the whole point of running one operation instead of six disconnected ones.
The mistake is keeping one bucket and hoping the agent sorts it out. It will not. Name the two scopes explicitly, in the system prompt and in the storage, and decide at write time which bucket each fact belongs in. "Client B prefers invoicing on the 15th" goes in the client bucket. "Invoicing on the 15th reduces late payments" goes in the playbook.
A filter you can forget is not isolation
Here is the rule that separates setups that leak from setups that do not: if the client boundary lives in a query filter, it will eventually be forgotten. One new workflow, one rushed Friday deploy, one intern's first agent, and the filter is missing from a single read. The leak does not announce itself. You find out from the client.
Tenant identity should be a hard boundary enforced by the store, not a suggestion in the prompt. Separate namespaces per client, enforced at the storage layer, where there is no query that can accidentally span them. Filters are fine for organizing inside a boundary. They are not the boundary.
Run the leak test
You cannot review your way to confidence here. Seed a distinctive, harmless fact for one client, something like "Client A invoices on the 15th," and let the agent work. Then ask it about Client B, Client C, anyone else. If the seeded fact ever surfaces outside Client A's scope, the boundary is broken and you now know exactly where. Run this monthly, and run it again after every change to the memory plumbing. It takes ten minutes. The alternative is finding out from a client.
Where a memory layer fits
This is the part where the plumbing matters more than the platform. Vilix AI is a cloud-hosted memory layer your agents reach over MCP, so there is nothing to self-host and no database to babysit. Each client's facts live in their own isolated scope, your shared playbooks live in another, and the same memory follows the agent across every tool it runs in, not just the one where the memory node happens to sit. It stores full conversation history, not just extracted facts, and retrieval is semantic plus keyword, so "invoice on the 15th" is found whether the agent asks by meaning or by exact phrase. There is a free plan that stays free, a 7-day Pro trial with no credit card, and you can export everything or delete it anytime from the dashboard at app.vilix.ai. Learn more at vilix.ai.
The checklist
One agent, many clients, zero leaks:
- Scope every memory read and write by client id. No unscoped defaults.
- Flush agent context between clients inside looped runs, or run one execution per client.
- Keep two buckets: per-client facts that never cross, playbook lessons that always do.
- Enforce the boundary in the store, not in a filter someone can forget.
- Run the leak test monthly and after every plumbing change.
Memory without walls is just gossip with extra steps. Build the walls first, and the agent can serve ten clients without ever confusing one for another.