# Memory for Background Agents: Where It Lives When the Sandbox Is Discarded, What to Remember With No User in the Loop, and Who May Write or Forget

> A background agent wakes on a cron, a heartbeat or an event, runs in a sandbox that is thrown away afterwards, and keeps only what it wrote somewhere else. Where that memory has to live (outside compute, scoped to the user and the agent, loaded at the start of every run), what to remember when no user is there to confirm anything, how async subagent results get written back without duplicates, and who may write to and delete from a memory several bots share.

_Gaurav Dadhich · 2026-11-03_

\# Memory for Background Agents: Where It Lives When the Sandbox Is Discarded, What to Remember With No User in the Loop, and Who May Write or Forget \*Published 3 November 2026. Every product behaviour below was read from the vendor's own documentation or the named author's post on 3 November 2026.\* A background agent keeps nothing from one run to the next except what it wrote outside the compute it ran on. It wakes on a cron, a heartbeat or an event, runs an LLM loop inside a sandbox, and the sandbox is stopped or discarded when the run ends; every LLM call was stateless to begin with, so whatever continuity the agent shows on its next run was put there by a write to storage that outlived the sandbox and a read from that storage at the start of the next one. Memory for background agents therefore comes down to four decisions: where that storage lives, what the agent is allowed to write to it when no user is watching, how results from subagents that finish later get into it, and who may write to it or make it forget when several bots share it. All four got sharper at the start of November 2026. On 2 November Harrison Chase, CEO of \[LangChain\](https://www.langchain.com/), described the agent architecture builders are converging on as an LLM in a loop calling tools and "running in a sandbox", and named proactive agents that "run in the background and either listen to event feeds or are woken up with heartbeats" as one of the open problems of \[context engineering in late 2026\](https://www.langchain.com/blog/context-engineering-challenges-late-2026). The same day \[Guillermo Rauch\](https://x.com/rauchg/status/2117338179535810957), CEO of \[Vercel\](https://vercel.com/), wrote that "Stateless sandboxes are the wrong benchmark. Agents are only useful if they have their workspace with them (identity, skills, repos, memories…)", and Caroline di Vittorio, an engineer at LangChain, \[put the case for cloud agents\](https://x.com/carodivittorio/status/2117350062162669953) in one line: "A local agent only runs when you start and watch it, but what will make agents more useful next is proactive, capable work that happens in the background." ## Why a background agent loses memory that a chat agent keeps A chat agent has two things a background agent lacks: a user who is present when the memory is formed, and a process or thread that lives at least as long as the conversation. A background agent has neither. Its compute is disposable by design, its input is an event feed rather than a person, and its work is often split across subagents that finish after the run that started them. The coding agents that already run in the cloud show what the default looks like. \[GitHub Copilot Memory\](https://docs.github.com/en/copilot/concepts/agents/copilot-memory), shared across Copilot cloud agent, Copilot code review, Copilot CLI and other Copilot surfaces, is one documented example: it stores repository facts that describe a codebase and per-user preferences that follow a person between repositories. GitHub's documentation also records the background-agent difference directly: in the Copilot app and interactive CLI sessions Copilot can ask you to approve storing a memory, while "Copilot cloud agent and Copilot code review do not ask for this approval." Outside a feature like that, what a new cloud run inherits is whatever sits in the repository, such as instruction files, which is configuration, not memory of past work. Personal memory on a laptop does not follow the work into the cloud either. \[Claude Code's documentation\](https://code.claude.com/docs/en/memory) states that its auto memory "is machine-local" and that its files "are not shared across machines or cloud environments", so a preference Claude Code learned on your machine is invisible to the same agent running a scheduled job elsewhere. The same is true one level down for job-queue workers on \[Celery\](https://docs.celeryq.dev/) or \[BullMQ\](https://docs.bullmq.io/): a worker's in-process state ends with the process, so a worker that runs an agent has the same problem as a sandbox, and the same fix. The checkpoint is the default objection, and it deserves a precise answer. A \[LangGraph\](https://docs.langchain.com/oss/python/langgraph/persistence) checkpointer persists "a thread's graph state as checkpoints", which lets one run pause, resume after a crash and wait for a human, and it does that job well. Its scope, in LangGraph's own table, is "A single thread". Memory that should carry from Monday's cron run to Tuesday's is cross-thread by definition, which is what LangGraph's store is for ("Long-term, cross-thread memory"). The distinction is worked through in detail in \[agent state vs agent memory\](https://www.maximem.ai/blog/agent-state-vs-agent-memory); for a background agent it matters more than usual, because each wake-up is typically a new thread. ## Where memory has to live when the sandbox is discarded Memory for a background agent has to live outside the compute, be keyed to the user and the agent it belongs to, and be loaded at the start of every run. Anything stored inside the sandbox fails the first test, and a file mount that every run can see fails the second. | Where you put it | Survives the sandbox being discarded | Concurrent writers | Scoped to a user and an agent | Knows that a fact was replaced | |---|---|---|---|---| | Sandbox filesystem | No | One sandbox | No | No | | Sandbox snapshot (Vercel) | Until it expires, 30 days by default | Each sandbox gets an independent copy; changes are not shared | No | No | | Mounted drive (Vercel Drives) | Yes, until manually deleted | One read-write mount at a time; readers mount point-in-time snapshots | Only by naming convention | No | | Key-value or document store keyed by namespace (LangGraph store) | Yes | Many | Yes, through the namespace you choose | Only if your code handles it | | Memory layer with extraction, supersession and scopes | Yes | Many | Yes, enforced on read | Yes | Vercel figures are from the \[Drives documentation\](https://vercel.com/docs/sandbox/concepts/drives), last updated 21 September 2026 and read on 3 November 2026. \[Vercel Drives\](https://vercel.com/docs/sandbox/concepts/drives) are the clearest current example of storage built for this. Files written to a drive "persist after the sandbox stops", a later run can mount the same drive "even when starting from a different sandbox environment", and Vercel lists an agent workspace "that persists across sandbox runs, building context over time" as a common pattern. Two documented limits decide whether a drive is enough on its own: "Only one sandbox at a time can mount a given drive as read-write", and a snapshot mount "does not include any writes made to the drive thereafter". A drive is the right home for a working directory, a dependency cache or an agent's notes for one agent; it is a filesystem, so it has no idea that "the customer's renewal date is 1 March" replaced "the customer's renewal date is 1 February", and two agents cannot both write to it at the same moment. Scope belongs in the key. LangGraph's \[stores guide\](https://docs.langchain.com/oss/python/langgraph/stores) namespaces memories by a tuple, \`(, "memories")\` in its example, and notes that a namespace can be any length. For a background agent, a namespace of tenant, user and agent (and a separate shared namespace for anything several agents may read) gives you per-user isolation and per-agent separation without a second system. Loading at start is where background agents differ most from chat. A chat agent can retrieve memory against the user's message; a heartbeat has no message, so the run has to load memory against its goal and its trigger. Keep that load bounded and ranked; loading everything stops working as memory grows. Supermemory's \[write-up of Grok Bot memory\](https://supermemory.ai/blog/grok-bot-memory/), drawn from Grok Bot's docs, shows the failure a fixed window produces: each turn sees "only the newest few thousand characters" of a bot's memory, "so a long, growing rule list pushes the oldest rules out of view". An always-on agent accumulates memory faster than a chat agent does, so it reaches that ceiling sooner. ## What a background agent should remember when no user is in the loop Chase's post names this as the hard part: "The hardest part of the intelligence layer is figuring out what to remember", and "the context engineering around what to remember and when is still an open problem." With a user present, a direct statement ("I am moving to Berlin") is strong evidence and the user can correct a wrong memory on the spot. A background agent sees event feeds, tool output and other agents' messages, none of which is a statement by the person the memory is about, and nobody reviews what it writes. That changes the write rules in five specific ways. \*\*Record where every memory came from, and rank by it.\*\* A fact the user stated, a fact the agent observed in a feed and a fact the agent inferred are different things and should carry different confidence. When the background agent's inference disagrees with what the user said, the user's statement wins until the user changes it. \*\*Write outcomes with their evidence, not intentions.\*\* "Sent the renewal reminder on 3 November, message ID attached" is a memory the next run can rely on. "Will follow up next week" is a plan, and plans belong in goal state with a status, not in memory as a fact. \*\*Keep goals and attempts as their own records.\*\* Chase writes that agents are moving "from doing tasks to working towards goals" and that it is hard to get them to "try out new experiments in pursuit of a goal (and not just repeat things)". A goal record that lists what was tried, what happened and when is what stops Tuesday's run from repeating Monday's failed experiment. \*\*Never take instructions from event content.\*\* A background agent reads email, tickets, web pages and webhooks with nobody watching, which is the exact path for memory poisoning. Content from a feed may become an observed fact; it may never become a standing instruction. Only the user or the operator writes instructions. \*\*Re-check before use, and expire what goes unused.\*\* Copilot Memory is a working example of both. When a repository fact looks relevant, Copilot "checks the fact's citations against the current branch to judge whether the information is still accurate", downvotes memories it finds wrong or outdated, and stops using them past a threshold. Stored facts and preferences "expire after a period without reinforcement", 90 days by default (owners can set 7 to 180 days for repository facts), and the clock resets when Copilot upvotes a memory, not when it merely retrieves one. GitHub is candid about the limit: the citation check is "a judgment Copilot makes, rather than a guarantee enforced by the system". The per-type thresholds (facts supersede with history, preferences need a direct statement, instructions only from the user or operator, episodes append and expire) are set out in the \[memory write policy\](https://www.maximem.ai/blog/agent-memory-write-policy) guide. The background-agent version tightens one thing: with no user to confirm, anything below the bar for a direct write goes to a review queue or stays an episode, and does not become a fact by default. The other half of "what to remember" is what to stop remembering, and that work is itself a background job. Merging duplicates, superseding replaced facts and expiring time-bound ones on a schedule, against a copy that is checked before it replaces the live memory, is covered in \[agent memory consolidation\](https://www.maximem.ai/blog/agent-memory-consolidation). ## How async subagent results get written back Async subagents finish after the turn that launched them, sometimes after the run that launched them, which makes write-back a coordination problem more than a storage one. LangChain's \[Deep Agents documentation\](https://docs.langchain.com/oss/python/deepagents/async-subagents) shows the current shape: \`start\_async\_task\` returns a task ID immediately, and the supervisor uses \`check\_async\_task\`, \`update\_async\_task\`, \`cancel\_async\_task\` and \`list\_async\_tasks\` to follow it. The task ID is the subagent's thread ID; on an Agent Protocol server, subagents "automatically update the supervisor as they complete", arriving as a message marked as a notification. Task records live in a dedicated \`async\_tasks\` state channel, separate from message history, so the supervisor can still list its tasks after its conversation is summarised. That state channel is still state. It belongs to the supervisor's thread, and it tells the supervisor that a task finished; it does not decide what from the result should be remembered for next week. Four rules close the gap. 1. \*\*One writer per scope.\*\* Let the supervisor, or a dedicated memory writer, decide what from a subagent's result enters long-term memory. Subagents return results; they do not write facts into the user's memory directly. 2. \*\*Use the task ID as the idempotency key.\*\* A retried or duplicated completion should replace the earlier write for that task, not add a second copy of the same fact. 3. \*\*Write only terminal, successful results as facts.\*\* A cancelled task, or one marked \`waiting\` for a human, has produced at most an episode ("task started, cancelled at 14:05"), never a fact. 4. \*\*Carry provenance through.\*\* Record which subagent, which task and which run produced each memory, so a bad result can be traced and removed as a unit. ## Who may write, and who may make it forget, when several bots share memory When several bots share one memory, the safe default is private memory per agent, a small shared scope with a gate on writes, and forget authority that sits with the person the memory is about and the operator, never with a peer agent. The products shipping this now draw the lines in similar places. In the Grok Bot design that Supermemory describes, "Each Bot has a memory of its own", and only a few facts such as your name and time zone are shared across all your bots; Supermemory's own teammate bot "Takes forget requests only from you" and refuses when another bot asks it to forget something. \[Warp's Agent Memory\](https://docs.warp.dev/agent-platform/agent-memory/), a research preview enabled for design partners, gives each agent its own store by default, separates personal stores from team stores, lets you "Attach stores to agents with read-only or read-write access", and records every change to a memory so a team can see how it changed over time. Vercel Drives enforce a single read-write mount, which prevents two sandboxes from corrupting one directory but is a lock rather than a policy, because it says nothing about whose writes should win or who may delete. | Action on shared memory | Who should be allowed | |---|---| | Read the shared scope | Any agent the user or team has authorised | | Write to its own private scope | That agent | | Write to the shared scope | A gated writer, after validation and with provenance | | Overwrite another agent's fact | Nobody directly; write a new fact that supersedes it, keeping history | | Forget a memory about a person | That person and the operator | | Forget on a peer agent's request | Nobody | Shared memory also spreads mistakes faster than private memory does, which is why the write gate matters more than the storage choice; the measured cases and scoping rules are in \[multi-agent shared memory\](https://www.maximem.ai/blog/multi-agent-shared-memory). ## A minimal design you can build today Every run of a background agent follows the same shape, whatever storage sits underneath: \`\`\`python def run(trigger, tenant, user, agent): ns\_private = (tenant, user, agent) # this agent's memory ns\_shared = (tenant, user, "shared") # readable by authorised agents # 1. Load at start: bounded, ranked against the goal and the trigger goal = store.get(ns\_private, "goal") context = store.search(ns\_private, query=f"{goal} {trigger}", limit=20) \\ + store.search(ns\_shared, query=f"{goal} {trigger}", limit=10) # 2. Do the work in a disposable sandbox; nothing in it is kept result = agent\_loop(trigger, goal, context) # 3. Write back through a gate, with provenance and an idempotency key for candidate in extract\_candidates(result): if passes\_write\_policy(candidate, source=candidate.source): store.put(ns\_private, key=f"{result.run\_id}:{candidate.key}", value={\*\*candidate.value, "source": candidate.source, "run\_id": result.run\_id}) store.put(ns\_private, "goal", update\_goal(goal, result)) # attempts and status \`\`\` The \`store\` here is any namespace-keyed store; the method names follow LangGraph's store API, and the gate, extraction and goal update are your code. A schedule elsewhere runs consolidation on the same namespaces. ## Where Maximem Synap fits \[Maximem Synap\](https://www.maximem.ai/synap) is a memory layer for agents, and three parts of it map onto the problems above. Memory is isolated by default across your account, your tenant, the individual person and the conversation, and a read prefers the narrowest scope that applies and sees everything above it, "never below, never sideways"; several agents can share a central context layer while keeping their own agent-specific memories, with the scope chain handling isolation between them. Every memory carries provenance (where it came from, what it replaced, why it changed), and a change is recorded rather than overwritten. Writes are asynchronous: the call returns immediately with a handle you can poll and extraction takes several seconds, which suits a background run that writes at the end and reads at the next wake-up. Consolidation and conscious forgetting run on background cadences, and payment card details, passwords, API keys and private keys are never stored for any customer. Managed cloud is the default, with self-hosted and air-gapped deployment available for enterprise engagements. ## Frequently asked questions ### Does a background agent remember previous runs? Only what it wrote to storage outside its sandbox. Each run starts from a fresh environment, and a checkpointer keeps the state of one thread, not knowledge across threads. Continuity across runs needs a cross-thread store or a memory layer, read at the start of every run. ### Where should memory live for an agent that runs in a throwaway sandbox? Outside the sandbox, in a store keyed by tenant, user and agent, loaded at the start of every run. A mounted drive (such as Vercel Drives, which persist until deleted) works for one agent's files; a namespaced store or memory layer is needed when several agents write, when facts get replaced, or when users can ask to be forgotten. ### Is a sandbox snapshot enough memory? No. A snapshot preserves a filesystem (Vercel's expire after 30 days by default), and each sandbox created from it gets an independent copy whose changes are not shared. It keeps an environment, not scoped, updatable facts about a user. ### What should a proactive agent remember with no user in the loop? Outcomes with their evidence, goal progress and attempts, and observed facts tagged as observed rather than stated. It should not turn feed content into instructions, and anything below the bar for a direct write should go to review or stay an episode. ### How should async subagents write their results to memory? Through one writer per scope, usually the supervisor, using the task ID as an idempotency key, writing only successful terminal results as facts, and recording which subagent, task and run produced each memory. ### Who should be able to delete memory that several agents share? The person the memory is about and the operator. A peer agent should never be able to make shared memory forget, and no agent should overwrite another's fact directly; a new fact supersedes it and the history is kept. ## Sources Retrieved 3 November 2026. - Harrison Chase, \[New context engineering challenges in late 2026\](https://www.langchain.com/blog/context-engineering-challenges-late-2026), LangChain blog, 2 November 2026. - Guillermo Rauch, \[post on X\](https://x.com/rauchg/status/2117338179535810957), 2 November 2026. - Caroline di Vittorio, \[post on X\](https://x.com/carodivittorio/status/2117350062162669953), 2 November 2026. - Vercel, \[Drives documentation\](https://vercel.com/docs/sandbox/concepts/drives), last updated 21 September 2026. - LangChain, \[LangGraph persistence documentation\](https://docs.langchain.com/oss/python/langgraph/persistence) and \[stores guide\](https://docs.langchain.com/oss/python/langgraph/stores). - LangChain, \[Deep Agents async subagents documentation\](https://docs.langchain.com/oss/python/deepagents/async-subagents). - Anthropic, \[How Claude remembers your project\](https://code.claude.com/docs/en/memory), Claude Code documentation. - GitHub, \[About Copilot Memory\](https://docs.github.com/en/copilot/concepts/agents/copilot-memory). - Muskan Jain, \[How we built insanely good memory for grok bot (by making it a teammate instead)\](https://supermemory.ai/blog/grok-bot-memory/), Supermemory blog, 3 November 2026. - Warp, \[Agent Memory (research preview)\](https://docs.warp.dev/agent-platform/agent-memory/).

---

Source: [https://www.maximem.ai/blog/background-agent-memory](https://www.maximem.ai/blog/background-agent-memory)
