User-Scoped Memory in Deep Agents: What It Is and Why You Need It Deep Agents introduced user-scoped memory to isolate long-term memory per user in shared AI agents, preventing preference leakage between users. The implementation uses a namespace based on the user ID, ensuring each user's memory files remain separate, as demonstrated with Alice and Bob receiving distinct responses. Imagine you build one AI agent and 1,000 people use it. Alice tells the agent: "I prefer Python examples and concise answers." Later, Bob asks: "How do I read a CSV file?" Bob should not suddenly receive a short Python-focused answer just because Alice used the agent before. This is exactly the problem user-scoped memory solves. User-scoped memory means giving each user their own separate long-term memory . The same agent can be shared by many users, but the memory belonging to one user is isolated from everyone else. For example: One AI Agent | +--------------+--------------+ | | | Alice Bob Charlie | | | Alice's memory Bob's memory Charlie's memory Alice might have: - Likes concise answers - Prefers Python Bob might have: - Likes detailed explanations - Prefers TypeScript When Alice talks to the agent, the agent reads Alice's memory. When Bob talks to it, the agent reads Bob's memory. Deep Agents implements this using a namespace . The namespace can be based on the user's ID, such as: namespace=lambda current runtime: current runtime.context.user id, This makes the user's ID the boundary between their memories. LangChain's documentation describes the same concept as user-scoped memory: each user gets an isolated copy of the memory files. Without user-scoped memory, you can accidentally create shared memory . Suppose your application has: php User A - Agent - preferences.md User B - Agent - preferences.md If both users access the same memory namespace, the agent could potentially read information written by the other user. That can cause several problems. Alice says: "Always give me Python examples." Bob could later receive Python examples even though he prefers TypeScript. A memory file might contain information about a user's previous interactions, preferences, or other personal context. If that memory is shared, one user's information could become available to another user. Imagine 100 users are constantly teaching the same agent different preferences: User A: Be concise. User B: Give detailed explanations. User C: Use Python. User D: Use TypeScript. If all of this goes into one shared memory, the agent has no reliable way to know whose preference it should follow . There is an important distinction. Short-term memory is generally associated with a conversation/thread. It helps the agent remember what is happening in the current conversation. Long-term memory survives across conversations. User-scoped long-term memory adds another layer: Conversation 1 ─┐ Conversation 2 ─┼── Alice's long-term memory Conversation 3 ─┘ So Alice can start a completely new conversation and the agent can still know her saved preferences. Deep Agents uses memory files for long-term memory and a backend/store to control where those files are stored. There are three important pieces in the example. MEMORY PATH = "/memories/preferences.md" This tells the agent which memory file it should use. Our application provides: @dataclass frozen=True class UserContext: user id: str For example: user-alice user-bob The important part is: namespace=lambda current runtime: current runtime.context.user id, This means: php user-alice - namespace "user-alice", user-bob - namespace "user-bob", The same /preferences.md path can therefore exist independently for both users. Conceptually: Store │ ├── "user-alice", │ └── /preferences.md │ └── "user-bob", └── /preferences.md The file has the same name, but it belongs to a different namespace. LangChain recommends user scope when memory should belong to individual users, and specifically notes that user A's preferences should not leak into user B's conversations. A good default is: If memory does not need to be shared, make it user-scoped. Shared memory should be used deliberately. LangChain's documentation also warns that allowing one user to write memory that another user can read can create security problems, including malicious instructions being inserted into shared state. For shared organizational policies, read-only memory is often more appropriate. The following example creates two users: Both use the same agent , but their memories are isolated. Install the required packages and set your NVIDIA API KEY , then save the code as user scoped memory.py and run: uv run user scoped memory.py The example uses NVIDIA's model through ChatNVIDIA , while the memory isolation itself is handled by Deep Agents and InMemoryStore . """Runnable user-scoped long-term memory example. Run with uv run user scoped memory.py after setting NVIDIA API KEY in the environment or in a .env file. Each invocation supplies a user ID through the graph context. The backend uses that ID as the store namespace, so users can share one agent without sharing their preference files. """ import os from dataclasses import dataclass from dotenv import load dotenv from langchain nvidia ai endpoints import ChatNVIDIA from langgraph.store.memory import InMemoryStore from requests.exceptions import Timeout from deepagents import create deep agent from deepagents.backends import CompositeBackend, StateBackend, StoreBackend from deepagents.backends.utils import create file data MEMORY PATH = "/memories/preferences.md" STORE MEMORY PATH = "/preferences.md" @dataclass frozen=True class UserContext: user id: str def build model : """Create the chat model used by the demo.""" if not os.getenv "NVIDIA API KEY" : raise RuntimeError "Set NVIDIA API KEY in the environment or a .env file before " "running this example." model name = os.getenv "NVIDIA MODEL", "nvidia:nvidia/nemotron-3-ultra-550b-a55b", .removeprefix "nvidia:" timeout seconds = int os.getenv "NVIDIA TIMEOUT SECONDS", "180" max completion tokens = int os.getenv "NVIDIA MAX COMPLETION TOKENS", "1024" return ChatNVIDIA model=model name, timeout=timeout seconds, max completion tokens=max completion tokens, model kwargs={"parallel tool calls": False}, def seed memory store: InMemoryStore - None: """Create an isolated preference file for each demo user.""" preferences = { "user-alice": """ Preferences - Likes concise bullet points. - Prefers Python examples. """, "user-bob": """ Preferences - Likes detailed explanations. - Prefers TypeScript examples. """, } for user id, content in preferences.items : store.put user id, , STORE MEMORY PATH, create file data content , def build backend store: InMemoryStore - CompositeBackend: """Route memory to the namespace belonging to the current user.""" return CompositeBackend default=StateBackend , routes={ "/memories/": StoreBackend store=store, namespace=lambda current runtime: current runtime.context.user id, , , }, def build agent store: InMemoryStore : return create deep agent model=build model , memory= MEMORY PATH , backend=build backend store , context schema=UserContext, store=store, name="user-scoped-memory-demo", def invoke for user agent, user id: str, thread id: str, prompt: str, - str: result = agent.invoke {"messages": {"role": "user", "content": prompt} }, config={"configurable": {"thread id": thread id}}, context=UserContext user id=user id , return result "messages" -1 .content def main - None: load dotenv store = InMemoryStore seed memory store agent = build agent store prompt = "How do I read a CSV file? Use only the preferences stored in " f"{MEMORY PATH}. State which language and response style you used." print "Alice's isolated memory" try: print invoke for user agent, user id="user-alice", thread id="alice-memory-thread", prompt=prompt, except Timeout: print "The NVIDIA model timed out. The memory store is configured " "correctly; try NVIDIA MODEL=meta/llama-3.2-3b-instruct or " "increase NVIDIA TIMEOUT SECONDS." print "\nBob's isolated memory" try: print invoke for user agent, user id="user-bob", thread id="bob-memory-thread", prompt=prompt, except Timeout: print "The NVIDIA model timed out. The memory store is configured " "correctly; try NVIDIA MODEL=meta/llama-3.2-3b-instruct or " "increase NVIDIA TIMEOUT SECONDS." if name == " main ": main You do not need a separate agent for every user. You can have: php One Agent | +-- User ID A - Memory A | +-- User ID B - Memory B | +-- User ID C - Memory C The user ID becomes the memory boundary . That is the core idea behind user-scoped memory in Deep Agents. For production applications, InMemoryStore is only suitable for a simple demonstration. Deep Agents' documentation notes that a persistent/platform store should be used when deploying rather than relying on an in-memory store. For the complete and current implementation details, see LangChain Deep Agents Memory documentation https://docs.langchain.com/oss/python/deepagents/memory?utm source=chatgpt.com .