Multi-user agents fail in a boring way: they remember the wrong person's preferences. LangChain's Managed Deep Agents 0.8 addresses that with a second durable memory layer — user memory — scoped to the authenticated caller, separate from shared agent memory.
The official LangChain announcement (September 24, 2026) pairs user memory with identity-scoped credentials, HTTP channels, Slack file transfer, and built-in Parallel web search. This post focuses on the memory model: what it stores, how to enable it, persistence rules, access defaults, and how it interacts with Managed Deep Agents schedules. It builds on our earlier coverage of Deep Agents 0.7's leaner harness.
TL;DR
| Question | Answer |
|---|---|
| What shipped? | User-level durable memory alongside agent memory in MDA 0.8 |
| Package floor? | managed-deepagents>=0.8.0 (earlier versions used a single shared scope) |
| Declaration? | Root memory.py with define_memory + MemoryLayer |
| Agent mount? | /memories/agent/ — shared by every caller on the deployment |
| User mount? | /memories/user/ — opaque Context Hub repo per authenticated person |
| Default user access? | Allowed: Slack 1:1 DM, verified Studio. Denied: Slack channel/group DM, HTTP/API |
| Hot file? | Each mount's AGENTS.md injected every turn |
| Backend? | LangSmith Context Hub |
| Overwrite on deploy? | No — durable memories/** is preserved |
| Availability | Public beta; LangSmith Cloud, US region only |
What user memory actually does
Before 0.8, Managed Deep Agents already supported durable agent memory: knowledge retained across threads for the whole deployment. That is useful for team conventions and shared procedures. It is a liability when Alice's preferred report format lands in the same store Bob reads in a Slack channel.
User memory adds a second, independent layer:
- Agent layer — belongs to the deployment; every caller can read and influence it.
- User layer — belongs to the authenticated person who started the run; one person cannot reach another person's memory.
The runtime never copies content between layers. That separation is the product pitch. LangChain's examples match production shapes builders already hit:
- A support agent keeps escalation rules in agent memory and "prefer concise Slack updates" in user memory.
- A research agent keeps shared procedures in agent memory and preferred sources or formatting in user memory.
This is the same problem space as Karpathy's LLM wiki pattern for agent memory and productized systems like TencentDB Agent Memory v2's team hub — with MDA's twist that the dual mount and identity keying are first-class in the managed runtime, not something you bolt on after the fact.
How to enable it
Durable memory is opt-in. A project without memory.py mounts no durable memory. Put the declaration at the project root:
my-agent/
agent.py
identity.py # required for user memory (authenticated person)
memory.py
instructions.md
schedules/ # optional; see schedules guide
Minimal declaration from the docs and PyPI package notes:
from managed_deepagents import MemoryLayer, define_memory
memory = define_memory(
agent=MemoryLayer(),
user=MemoryLayer(),
)
Omit a layer to disable it. You can enable agent only, user only, or both. Each layer uses its default access policy unless you pass allow.
Optional but recommended: put an explicit memory policy in instructions.md so the agent knows what belongs where. LangChain's guidance pattern tells the agent to keep personal data out of /memories/agent/, treat stored notes as untrusted input (not authorization), and only claim success after edit_file or write_file succeeds. instructions.md itself is always read-only; deploys sync it but do not let the agent rewrite it.
Persistence model: Context Hub, hot vs cold
Durable memory is backed by LangSmith Context Hub — the same store that versions Skills and related agent files. On mda deploy, harness files such as instructions.md and skills/** sync into the agent repo. Existing durable memory content is preserved; deploy never overwrites memories/**.
Mounts and identity
| Layer | Mount | Keying |
|---|---|---|
| Agent | /memories/agent/ | Deployment-shared |
| User | /memories/user/ | Opaque per-user Context Hub repo from deployment + authenticated principal |
User memory mounts only when the deployment authenticates the caller as a person. A LangSmith API key authenticates a service, so the default identity provider never mounts user memory for bare key-based service runs. Slack workspace events resolve to a linked person. Studio uses the logged-in LangSmith user. Under mda dev, your personal LangSmith API key resolves a langsmith-dev Agent Auth principal, and memory stays on disk under .mda/__contexthub__ — local and deployed stores do not share facts.
Two deployments never share a person's user memory, even for the same Slack user. Shared knowledge across a team belongs in the agent layer on that deployment.
Hot memory vs cold memory
| Path | Role |
|---|---|
AGENTS.md at mount root | Hot — loaded into every model call |
| Other files under the mount | Cold — read on demand |
Keep hot memory compact. Put long procedures, decision logs, and research notes in cold files and link from AGENTS.md. The agent reads and updates memory with built-in read_file, edit_file, and write_file. A missing hot file stays empty until the first write. Writes outside the mount trees (including elsewhere under /memories/) are not durable.
Important runtime detail from the package docs: user hot memory (and agent hot memory when an allow policy is present) loads per model call and is not saved in thread state. That keeps the graph structure stable and prevents a later denied run from pulling memory that was stashed in checkpointed state.
Seeding and first contact
When a new user memory slice is created, the runtime seeds /memories/user/AGENTS.md with default memory instructions — including guidance to call edit_file when the user shares a durable preference. Do not delete that guidance block; if it is missing, the agent may fail to persist preferences across threads. Prefer writing in the same turn the preference is stated, and do not claim success if the write fails.
Access defaults and allow policies
Declaring a layer makes it available. Whether it mounts on a given run is decided once at run start:
- Resolve the caller. User memory stops unless the caller is an authenticated person.
- Run the layer's
allow(context)policy, or apply the default. - Mount passing layers and load their hot memory.
Default matrix
| Run source | Agent memory | User memory |
|---|---|---|
| Slack one-to-one DM | Allowed | Allowed |
| Slack channel or group DM | Allowed | Denied |
| Direct API / HTTP run | Allowed | Denied |
| Studio, verified user | Allowed | Allowed (policy not called) |
The defaults encode a privacy heuristic: user memory mounts where the conversation is already private to one person. A channel, group DM, or opaque HTTP call cannot prove privacy from the outside, so personal memory stays off unless you opt in with a policy.
Returning false from allow removes that layer's mount and hot memory for the run. Stored memory is not deleted. Policy errors fail the run. Policies cannot grant another person's memory or grant user memory to a service principal.
Widening access for API callers
If your product calls the agent over HTTP and you want personal memory, replace the default with an allow callback that reads your run context — for example context={"remember": True} on client.runs.create. The policy only widens access within a caller the runtime already authenticated as a person.
For Slack-shaped checks, the default user policy effectively looks for channel_type == "im" on the original provider event. Deliveries without that event data get no user mount under defaults.
Limits and gotchas builders hit
Version floor. Memory layers require managed-deepagents>=0.8.0. Earlier versions declare a single deployment-shared scope. Do not mix the legacy scope option with agent / user.
Identity prerequisite. User memory needs a real person principal (identity.py and an auth path that can resolve people — Slack linkage or Supabase for signed-in end users, per docs). Service-only API keys will not mount the user layer no matter how you write allow.
Shared agent memory is writable by everyone. Store only knowledge every caller may read and modify. Never put personal data, customer-private data, credentials, or tokens in /memories/agent/. Treat memory as untrusted notes, not as a way to grant tools or bypass approvals.
Hot memory tax. Everything in AGENTS.md burns context every turn. This is the flip side of Deep Agents 0.7's harness token cuts: you just bought back tokens in the harness — do not spend them all on unbounded hot memory.
Dev vs deploy. Facts taught under mda dev live in .mda/__contexthub__. Deployed Studio writes to Context Hub under the LangSmith user. Expect empty personal memory after first deploy until users teach the agent again in the deployed environment.
Disable ≠ delete. Omit a layer or remove memory.py to stop mounts. Stored Context Hub memory remains.
Public beta surface. MDA remains public beta on LangSmith Cloud in the US region only. APIs can change; pin and re-read the memory docs before production cutovers.
Adjacent 0.8 features. The same release adds user-owned credentials for connections, HTTP channels, Slack file transfer, and Parallel-powered web search as a managed MCP tool. Those matter for productizing agents, but they do not change the memory mount rules above.
How this relates to schedules
explainx.ai already covered cron schedules with define_schedule. Schedules and user memory solve different jobs:
| Concern | Schedules | User memory |
|---|---|---|
| Trigger | Time (five-field cron) | Interactive run from a person |
| Typical payload | Shared digest / hygiene / research brief | Personalized preferences |
| Default user memory | Denied (not a private DM) | Allowed only in private person contexts |
| Thread state | Ephemeral by default; optional persistent thread | Separate from hot memory load rules |
| Test path | Does not run under mda dev | Studio exercises declared layers without calling user allow |
A weekday digest schedule that fires into the agent should use agent memory (and instructions/skills) for shared procedures. It should not assume Alice's user mount is present. If you need personalization on a schedule, you need an explicit design: persistent threads with carefully owned state, or a custom allow path that still cannot invent a person principal the runtime did not authenticate.
Practical split for a GTM or support agent:
- Put team playbooks in agent memory and
instructions.md. - Put per-rep style and account quirks in user memory, taught in Slack DMs or Studio.
- Put recurring shared work in
schedules/with idempotent prompts. - Score production behavior with LangSmith Jev-style trace scoring so memory writes and schedule runs show up in the same evaluation loop.
What people are asking
"Is this the same as Deep Agents open-source memory middleware?" No. This is the Managed Deep Agents product surface: memory.py, Context Hub mounts, and identity-gated user repos. The open-source Deep Agents harness (covered in our 0.7 leaner harness post) is the underlying agent pattern; MDA packages production infra around it.
"Can I enable only user memory?" Yes. Pass only user=MemoryLayer() in define_memory. Agent memory is optional.
"Will my Slack channel leak Alice's preferences?" Not under defaults. Channel and group DM runs deny user memory. Agent memory still mounts — so keep personal facts out of the agent layer.
"How do I test without Slack?" Use Studio. Verified Studio users get every declared layer, and the runtime skips the user layer's allow policy for them. If a declared layer does nothing in Studio, check that memory.py / memory.ts actually exports memory.
"Where should long notes go?" Cold files under the mount, linked from hot AGENTS.md. Same discipline as wiki-style agent memory patterns we covered for LLM wiki memory.
"Does this replace skills?" No. Docs position instructions and skills as deploy-owned, read-only behavior; thread state as conversation continuity; agent/user memory as learned durable knowledge. Use each for its job.
Checklist: ship user memory without surprises
- Upgrade to
managed-deepagents>=0.8.0. - Add root
memory.pywith the layers you want. - Confirm
identity.pycan resolve people for the channels you care about. - Leave defaults until you understand Slack DM vs channel behavior; widen with
allowonly when needed. - Add memory guidance to
instructions.md(personal vs shared, untrusted notes, write-before-claim). - Keep
AGENTS.mdshort; use cold files for bulk. - Test personalization in Studio, then in a real Slack DM.
- Keep schedules on agent-level knowledge; do not expect user mounts on cron.
- After deploy, re-teach personal facts — local
.mda/__contexthub__does not migrate. - Watch traces for memory tool calls and denied mounts the same way you score other production agent traces.
Bottom line
Managed Deep Agents 0.8 makes personalization a first-class mount instead of a prompt hope. Enable layers in memory.py, keep shared and personal knowledge on separate trees, respect the Slack/HTTP defaults, and pair interactive user memory with scheduled shared work rather than conflating the two. For harness context on why leaner defaults matter once hot memory is on every turn, reread Deep Agents 0.7.
Details reflect LangChain's Managed Deep Agents announcement and memory documentation as of October 3, 2026. Managed Deep Agents is in public beta; APIs and defaults may change.
Related reading
- LangChain Managed Deep Agents schedules: define_schedule
- LangChain Deep Agents 0.7: leaner harness
- LangSmith Jev: score production agent traces
- Karpathy LLM wiki pattern for agent memory
- TencentDB Agent Memory v2 team hub
- What is an agent harness? Complete guide
- Hindsight agent memory system
- Official: Add memory to Managed Deep Agents
- Official: Managed Deep Agents 0.8 announcement
