Free forever, no credit card.Get Started for 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.

Get Started for Free

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

Get Started for Free

Free forever, no credit card.

Keep reading
Your Relevance AI Agent Has a Memory Feature. Your Scheduled Runs Still Start Blind.

You set a Relevance AI agent on a recurring schedule. Every morning at 7 it wakes up, pulls the new leads, scores them, and fires off the follow-ups. It works beautifully for a week. Then one morning it re-scores a lead it already contacted on Tuesday, sends a second follow-up to a prospect who said no, and completely misses the one who said "call me next week" because nobody told the agent that last week ended. The agent did not malfunction. It did not hallucinate. It just started blank, the s

Our AI Agent Forgets Everything Between Sessions. What Should We Put Underneath It?

Our AI Agent Forgets Everything Between Sessions. What Should We Put Underneath It? The short answer: an agent is stateless by default, so it forgets unless something outside it stores and returns context. What goes underneath is a memory layer: a store that saves what matters from each session and hands the right pieces back at the start of the next one. You have five real options: a plain database, a vector store, an embedded memory library like Mem0, Zep, Letta, or Cognee, a hosted memory se

One Memory Across Every AI Tool: Tabula, Eling, openIME, and Vilix AI, Honestly Compared

One Memory Across Every AI Tool: Tabula, Eling, openIME, and Vilix AI, Honestly Compared Quick answer: If you keep re-explaining yourself every time you switch AI tools, you need a memory layer outside any one of them. Four real options do this today: Tabula, Eling, openIME, and Vilix AI. Same goal, one memory for every AI, but they differ in what gets stored, who hosts it, and how much you manage yourself. Tabula is strongest for dashboard-level control. Eling is strongest for the simplest hos