DEV Community

Cover image for Your Agent's Memory Needs a Scope: What to Keep, Where, and When to Forget
PromptMaster
PromptMaster

Posted on AI-assisted

Your Agent's Memory Needs a Scope: What to Keep, Where, and When to Forget

Most agent memory problems I see aren't about storage. They're about scope.

A preference that belongs to you ends up in a file the whole team shares. A temporary rule ("don't deploy this week") gets saved as if it were permanent. A note about the task you're working on right now is still being loaded three weeks later. The agent isn't forgetting. It's remembering the right thing in the wrong place, for the wrong amount of time.

In an earlier article I covered the four kinds of agent memory: working, episodic, semantic and procedural. This one is about a different question you have to answer for every single memory: who is it for, and how long should it live?

Three scopes cover most cases

You can slice scope many ways, but three levels handle almost everything a coding agent or assistant needs:

  • Session: true only for the current task. "We're fixing the login redirect." "The test database is already seeded." Useful for an hour, noise tomorrow.
  • Project: true for this repository or this product, for everyone who works on it. "We use pnpm." "Deploys go through the staging branch." "Never edit generated files in src/gen/."
  • User: true for you, across every project. "Keep answers short." "I prefer TypeScript examples." "Explain shell commands before running them."

Each scope answers a different question. Session memory answers what are we doing? Project memory answers how does this place work? User memory answers how does this person like to work? When a memory is filed under the wrong question, you get the familiar symptoms: your personal style leaks into teammates' sessions, a project fact doesn't follow you into a new worktree, or yesterday's task keeps steering today's work.

How Claude Code maps these scopes to real files

You don't have to invent this structure. Claude Code's documentation on how Claude remembers your project is a good concrete example, because each scope has its own location:

  • User instructions live in ~/.claude/CLAUDE.md and apply to all your projects. Only you see them.
  • Project instructions live in ./CLAUDE.md or ./.claude/CLAUDE.md and are meant to be shared with the team through version control.
  • Local instructions live in ./CLAUDE.local.md: personal, project-specific preferences that the docs say to add to .gitignore, like your sandbox URLs or preferred test data.
  • Managed policy is an organization-wide file deployed by IT or DevOps, which loads before user and project files.

Two details from the docs are worth knowing. First, these files don't override each other; all discovered files are concatenated into context, ordered from broadest to most specific. So "most specific wins" only works if you write the specific file to say so clearly. Second, a gitignored CLAUDE.local.md only exists in the worktree where you created it. If you want personal project notes in every worktree, the docs suggest importing a file from your home directory instead.

Then there's auto memory, the notes Claude writes for itself. The docs describe it as per repository: each project gets a directory at ~/.claude/projects/<project>/memory/, and all worktrees and subdirectories of the same git repo share it. It's machine-local, so it doesn't follow you to another machine or a cloud environment. Claude records each note with a type of user, feedback, project or reference, and skips anything it can derive from the code or that your CLAUDE.md already says.

Subagents get the same idea in miniature. A subagent's memory field takes a scope: user (~/.claude/agent-memory/<name>/), project (.claude/agent-memory/<name>/, shareable via version control) or local (.claude/agent-memory-local/<name>/, not checked in). The docs recommend project as the default.

Even if you don't use Claude Code, this is a useful template: one place per scope, and a clear rule for which ones get committed.

A decision test for every memory

Before a fact gets saved, by you or by the agent, run it through four questions. This is my own rule of thumb, not something from a spec:

  1. Would it still be true next week? If not, it's session memory. Keep it in the task, a scratch file, or a plan, and let it go when the task ends.
  2. Would it be true for a teammate in this repo? If yes, it's project memory and belongs in the shared, committed file.
  3. Is it about you rather than the code? It's user memory: your home-level file, never the repo.
  4. Does it have an end date? Then write the date into the memory and give it a review point. "No deploys until 16 Nov" is fine. "No deploys" with no date is a bug waiting to happen.

The fourth question is the one people skip. A rule that was true for two weeks and stays loaded forever is worse than no memory, because the agent will follow it with total confidence.

A minimal scoped memory, run for real

Here's a small Python sketch of the idea. Each memory has a scope, a subject, a value, the date it was written, and an optional review date. Session memories are dropped when the session ends. When two scopes hold the same subject, the more specific one wins. Anything past its review date gets flagged instead of silently trusted.

from datetime import date, timedelta

# Most specific scope wins when two scopes hold the same subject.
SCOPES = ["user", "project", "session"]

memory = []  # each entry: scope, subject, value, written, review_after

def remember(scope, subject, value, written, review_days=None):
    # Update, don't append: one current value per (scope, subject).
    memory[:] = [m for m in memory if (m["scope"], m["subject"]) != (scope, subject)]
    review = written + timedelta(days=review_days) if review_days else None
    memory.append({"scope": scope, "subject": subject, "value": value,
                   "written": written, "review_after": review})

def end_session():
    memory[:] = [m for m in memory if m["scope"] != "session"]

def recall(today):
    current, stale = {}, []
    for scope in SCOPES:  # broad to specific, so specific overwrites
        for m in memory:
            if m["scope"] != scope:
                continue
            current[m["subject"]] = f'{m["value"]}  [{scope}]'
            if m["review_after"] and today > m["review_after"]:
                stale.append(f'{m["subject"]} ({scope}, written {m["written"]})')
    return current, stale

d0 = date(2026, 11, 2)
remember("user", "answer_style", "short answers, no emoji", d0)
remember("user", "package_manager", "npm", d0)
remember("project", "package_manager", "pnpm", d0)
remember("project", "release_freeze", "no deploys until 16 Nov", d0, review_days=14)
remember("session", "current_task", "fix the login redirect", d0)

facts, stale = recall(d0)
print("Session 1, day 0:")
for k, v in facts.items():
    print(f"  {k}: {v}")

end_session()
facts, stale = recall(d0 + timedelta(days=15))
print("Session 2, day 15:")
for k, v in facts.items():
    print(f"  {k}: {v}")
print("Needs review:", stale or "nothing")
Enter fullscreen mode Exit fullscreen mode

This is the actual output from running it with Python 3.13:

Session 1, day 0:
  answer_style: short answers, no emoji  [user]
  package_manager: pnpm  [project]
  release_freeze: no deploys until 16 Nov  [project]
  current_task: fix the login redirect  [session]
Session 2, day 15:
  answer_style: short answers, no emoji  [user]
  package_manager: pnpm  [project]
  release_freeze: no deploys until 16 Nov  [project]
Needs review: ['release_freeze (project, written 2026-11-02)']
Enter fullscreen mode Exit fullscreen mode

Three things happened. The project's pnpm beat the user-level npm, because the repo knows better than your habits. The session task disappeared once the session ended. And the release freeze is still loaded on day 15, but it's flagged for review rather than quietly obeyed. In a real agent, that flag is the moment to ask the user or drop the entry.

Keep the always-loaded part small

Scope also decides what gets loaded every time. Claude Code's auto memory is a good example of why that matters: only the first 200 lines or 25KB of MEMORY.md load at the start of a conversation, whichever comes first, and anything past that limit isn't loaded at session start. Detailed notes go into separate topic files that Claude reads on demand. The docs also note that when Claude writes a memory file with frontmatter, Claude Code records a modified timestamp, so both you and Claude can see how current a fact is.

The general lesson: keep a short index of what's always relevant, push detail into files that load only when needed, and keep a date on every fact. Memory files in Claude Code are excluded from transcript cleanup and stay until you or Claude edits or deletes them, so reviewing them is your job.

Sharing one memory across tools

If your team uses more than one coding agent, project memory is the scope worth sharing. The Claude Code docs describe two ways to keep one AGENTS.md as the file every tool reads: Claude Code can read AGENTS.md directly when there's no CLAUDE.md, or you can put an @AGENTS.md import at the top of a CLAUDE.md and add Claude-specific notes below it. User memory, on the other hand, should stay personal and out of the repo, whichever tool you use.

Quick checklist

  • [ ] Every memory has a scope: session, project or user
  • [ ] Session notes are cleared or archived when the task ends
  • [ ] Project facts live in a committed file the whole team can review
  • [ ] Personal preferences live outside the repo (home-level or gitignored)
  • [ ] Time-limited rules carry an end date and a review point
  • [ ] The always-loaded index stays short; detail loads on demand
  • [ ] One shared project file across tools, if you use more than one agent
  • [ ] Someone reads the memory files on a schedule and deletes what's stale

Where to go next

If you're new to agent memory, start with the free AI Agent Memory Quick-Start, six pages on the four kinds of memory and the basic memory loop.

When you're ready to build it properly, AI Agent Memory: The Complete Guide covers writing and reading memories, consolidation and forgetting, tiered, vector and graph architectures, the production failure modes (bloat, poisoning, contradictions), and personalization and privacy, with a worked example of a support agent that remembers users across sessions.

This article was written with the assistance of AI and reviewed by the author. The code output above comes from a real run of the script shown.

Top comments (0)