Full Pro free for 7 days, no credit card. Start free →
← All posts
September 28, 2026 · 6 min read

One Agent, Many Clients: Stopping Scheduled Agent Memory From Leaking Across Users

One Agent, Many Clients: Stopping Scheduled Agent Memory From Leaking Across Users Agencies and solo operators love the economics of scheduled agents: one workflow, one schedule, many clients served. A Monday-morning briefing agent that summarizes the weekend's support tickets. A nightly lead-research agent that enriches new signups. Build it once, aim it at every client. There is a catch that does not show up in the demo. A scheduled agent with memory serves whoever its memory serves. The mom

One Agent, Many Clients: Stopping Scheduled Agent Memory From Leaking Across Users

Agencies and solo operators love the economics of scheduled agents: one workflow, one schedule, many clients served. A Monday-morning briefing agent that summarizes the weekend's support tickets. A nightly lead-research agent that enriches new signups. Build it once, aim it at every client.

There is a catch that does not show up in the demo. A scheduled agent with memory serves whoever its memory serves. The moment the same memory store holds facts about two different clients, you have a leak waiting for a trigger. And because scheduled agents wake up on timers instead of in conversations, the leak does not announce itself. It shows up as Client B's weekly summary mentioning Client A's launch date, or as an enrichment note attached to the wrong account. By the time anyone notices, the wrong data has been sitting in the wrong place for weeks.

Keeping memories apart per user is a different job from giving agents memory at all. Memory is about recall. Isolation is about boundaries. Here is how to build the boundary.

Why scheduled agents are the worst case

A chat agent is anchored to a user by the conversation itself. The request arrives with a user attached, and the memory lookup inherits that context. A scheduled agent starts from a clock. The trigger carries no user, no tenant, no conversation. The agent must decide whose memory to load based on whatever the workflow passes in, and if the workflow passes in nothing, the agent reaches for the whole store.

Two common setups make this worse. The first is the single shared workflow: one Make.com scenario or one n8n workflow that loops over clients and runs the agent per client, all against one memory connection. The second is the generic agent prompt: the same instructions for every client, with the memory injected wholesale at the top of the context. Both are fine for one tenant. Both are silent contamination machines for many.

Start by mapping who can see what

Before choosing a mechanism, draw the boundary on paper. For each memory your agent stores, answer three questions:

  1. Which user does this memory belong to?
  2. Which users are allowed to see it?
  3. What happens when the agent cannot tell whose memory it is holding?

The third is the one most designs skip. A memory store full of facts with no owner is not a memory store; it is a rumor mill. If a record cannot answer "whose is this?", it should not be readable by anyone until it can.

Most operators land on one of three scoping models. Per-user scoping gives every end user their own memory: the support agent remembers each customer's own history. Per-client scoping groups users under a client: the agency's agent keeps each client's data together but apart from other clients. Shared-plus-private keeps one layer of common knowledge (product docs, public procedures) plus a private layer per user. The shared layer is where teams get burned: a "common knowledge" store that someone quietly started writing client-specific facts into becomes a cross-tenant channel with a friendly name.

Make the boundary structural, not conventional

The DIY answer most people build first is a filter: every memory row gets a user_id or client_id, and every query filters on it. This works, and it is also the boundary most likely to fail at 2 AM six months from now. Filters are conventions. Conventions depend on every future workflow, helper, and teammate remembering to apply them. The failure mode is one unfiltered query in a new automation, and nothing in the system will flag it.

Structural boundaries are harder to build and harder to break. Separate databases, separate schemas, or separate collections per client mean the wrong data is not merely filtered out; it is unreachable. Session keys scoped per user inside the agent framework give per-user continuity in one workflow: the agent for client-acme and the agent for client-beta read different histories by construction. The test for a structural boundary is simple: take away every convention, every careful query, every disciplined teammate, and check whether a leak is still impossible. If it is only unlikely, it is not structural.

Fifty clients times fifty stores is real operations work: connection pools, backups, migrations, all multiplied. The honest rule of thumb: make the boundary as strong as the data is sensitive. A leak of support-ticket summaries is embarrassing. A leak of pricing, contract terms, or customer lists is a contract problem. Spend the ops budget where the consequences live.

Let a hosted layer carry the boundary

There is a middle path between a hand-rolled filter and fifty databases: a memory service whose job is to hold the boundary for you. Your scheduled agents read and write through it, and the isolation lives in the service rather than in your workflow code. The failure mode you are eliminating is the human one: nobody has to remember the filter because there is no filter to remember.

Vilix AI takes this approach. It is cloud-hosted and reached over MCP, so your agents get memory without you running anything: no database, no schema migrations, no connection pools. The isolation boundary is the account itself. Data is isolated per user, and every AI tool you connect to the same account shares the same memory. For an operator running their own automations, this is the shape that fits: one tenant, many tools, one memory, nothing that can leak sideways.

The tradeoff: because the boundary is per account, two clients' memories stay apart via two accounts, not a client_id filter inside one. That is a heavier mechanism than namespacing, and deliberately so; it cannot be undone by a forgotten WHERE clause in a Friday-afternoon workflow edit.

The memory itself is full conversation history, not just extracted facts, and retrieval combines semantic search with keyword matching, so exact strings like order IDs and policy names match literally. It is free to start, with a free plan forever and a 7-day Pro trial that asks for no credit card. If you ever want out, you can export everything in a portable format or wipe the account instantly.

The audit that takes an afternoon

Here is a practical sequence for an operator who suspects the boundary is soft:

  1. List every scheduled agent that reads or writes memory, and note which of them touches more than one user or client.
  2. For each of those, check what identifies the tenant at read time. A stable, user-scoped session key or an explicit tenant filter counts. "The workflow knows" does not.
  3. Run the leak test: plant a fact in one user's memory, then ask for it from another user's context. If it surfaces, the boundary is decorative.
  4. Fix the structural gaps first (unscoped stores, shared session keys), then the conventional ones (missing filters).

Agents that forget between runs are a solved problem. Agents that remember the wrong user's data are a trust problem, and trust problems do not get second chances with clients. Build the boundary before the first leak, while it is still a design decision and not an apology.

Try Vilix Pro free for 7 days

Persistent memory across ChatGPT, Claude, and the AI tools you already use in Vilix AI.

Get started free
Keep reading
Your Agent Believes Everything the Internet Tells It. That Is the Attack.

Every part of your automation stack got a security review. The API keys are in a vault. The webhooks are signed. The n8n instance sits behind auth. And then, every night, your scheduled agent reads a pile of untrusted content — inboxes, ticket queues, vendor portals — and writes its conclusions into long-term memory. Nobody reviewed that part. Nobody watches it. That is the hole. It has a name: memory poisoning. Unlike a prompt injection, which dies when the run ends, a poisoned memory persists

Vilix AI vs Zep: Which Memory Layer Fits Your AI Agents?

Vilix AI vs Zep: Which Memory Layer Fits Your AI Agents? The short answer: Vilix AI and Zep both give AI agents a memory, but they sell to different people. Zep is a temporal knowledge-graph memory you wire into agent software you build, with best-in-class "what was true when" reasoning, starting at $125/mo for production. Vilix AI is a hosted shared memory layer you attach to tools you didn't build (Claude, Codex, n8n agents, headless runners), one memory across all of them, with full conversa

CLAUDE.md Is Not a Memory System: 6 Coding-Agent Memory Layers, Compared

CLAUDE.md Is Not a Memory System: 6 Coding-Agent Memory Layers, Compared Somewhere on your machine there is a markdown file that started as a clean list of project rules and grew into a second job. Every session reads the entire thing, billed by the token. Outdated instructions sit next to new ones with no referee. And when your scheduled agent wakes up on another machine, none of it helps. CLAUDE.md is a document, not a memory system. A memory system keeps decisions, task state, and learnings