Module 2: Agent Memory and Scopes

2. Memory Scopes in Depth

2. Memory Scopes in Depth

Description

In the previous capsule you saw the problem — amnesiac subagents that repeat analysis, forget conventions, and start from scratch each session. You also saw the solution at the conceptual level: three memory scopes (user, project, local) and a MEMORY.md file that persists context. Now it's time to implement it.

Configuring memory in a subagent is adding a field to the YAML frontmatter. But choosing the right scope, writing instructions that guide the subagent on what to remember, and verifying that persistence actually works — that takes deliberate practice. A subagent with poorly configured memory is worse than one without memory: it accumulates noise, reaches the 200-line limit with irrelevant information, and its decisions get contaminated with stale context.

In this capsule you're going to configure memory in the three scopes, write system prompts that instruct the subagent to curate its own memory, verify persistence across sessions, and apply everything to the reviewer and implementer of capsule 05's project.


The memory Field in the Frontmatter

Configuration syntax

Enabling memory is adding a line to the subagent file's YAML frontmatter:

---
name: code-reviewer
description: Reviews code for quality
memory: project
---

The memory field accepts exactly three values:

ValueMEMORY.md locationShareable
user~/.claude/agent-memory/{name}/MEMORY.mdNo — personal, all projects
project.claude/agent-memory/{name}/MEMORY.mdYes — via git, the whole team
local.claude/agent-memory-local/{name}/MEMORY.mdNo — private, gitignored

If you don't include the memory field, the subagent has no persistence. Each session starts with no previous context.

What happens when you enable memory

When you add memory: project to a subagent named code-reviewer, Claude Code:

  1. Creates the directory .claude/agent-memory/code-reviewer/ if it doesn't exist
  2. Creates an empty MEMORY.md in that directory if it doesn't exist
  3. Injects the first 200 lines of MEMORY.md into the subagent's system prompt at the start of each session
  4. Automatically enables the Read, Write, and Edit tools so the subagent can manage its memory file
  5. Adds instructions to the system prompt telling the subagent how to read and write in its memory directory

Those tools are enabled in addition to the ones you define in tools. If your reviewer has tools: Read, Glob, Grep, with memory: project it will have access to Read, Glob, Grep plus Write and Edit — but only for files inside its memory directory.

Without memory:
  available tools = [Read, Glob, Grep]

With memory: project:
  available tools = [Read, Glob, Grep]
  + Write/Edit enabled ONLY for .claude/agent-memory/code-reviewer/*

user Scope: Universal Personal Knowledge

When to use it

The user scope stores memory in your home directory (~/.claude/agent-memory/{name}/). It isn't associated with any project — it's yours, available in any repository where you use that subagent.

---
name: style-enforcer
description: Enforces personal coding style preferences across all projects
memory: user
---

What to store in user scope

  • 📝 Personal style preferences (indentation, naming, comments)
  • 📝 Patterns you use frequently in any project
  • 📝 Personal documentation conventions

Example: personal style enforcer

Create ~/.claude/agents/style-enforcer.md:

---
name: style-enforcer
description: Enforces personal coding style preferences across all projects
tools: Read, Glob, Grep
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
memory: user
---

## Role
You enforce coding style preferences. You read code and report
deviations from the style preferences stored in your memory.
You NEVER modify code files.

## Memory Management
On first run (empty MEMORY.md):
- Ask what style preferences the user wants to enforce
- Save preferences to MEMORY.md in structured format

On subsequent runs:
- Read MEMORY.md for established preferences
- Apply preferences to code review
- Add new preferences if the user mentions them

## Output Format
### Style Report
**Preferences applied:** [count from memory]
#### Deviations Found
- **[file:line]** — Expected: [preference] | Found: [deviation]
#### Summary: [n] deviations in [n] files

The first time you run this subagent, MEMORY.md is empty and it will ask for your preferences. The second time it already knows them and applies them directly.


project Scope: Team Knowledge

When to use it

The project scope stores memory in .claude/agent-memory/{name}/ — inside the project, versionable with git. It's the most powerful scope because it lets the whole team share the subagent's accumulated knowledge.

What to store in project scope

  • 🏗️ Project architectural decisions
  • 🏗️ Team code conventions
  • 🏗️ Common codebase patterns
  • 🏗️ Recurring bugs and their solutions

Example: reviewer with project memory

Update your .claude/agents/reviewer.md from Module 1:

---
name: reviewer
description: Reviews recent code changes for quality, security, and best practices
tools: Read, Glob, Grep, Bash
disallowedTools: Write, Edit
model: haiku
maxTurns: 15
permissionMode: plan
memory: project
---

## Role
You are a code reviewer. You analyze recent git changes and produce
a structured report. You NEVER modify any file except your MEMORY.md.

## Memory Management
Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.

When updating MEMORY.md:
- Add patterns you observe repeatedly
- Record architectural decisions mentioned in comments or PR descriptions
- Note recurring issues so you can flag them proactively next time
- Keep entries concise: one line per pattern/decision
- If MEMORY.md exceeds 150 lines, consolidate redundant entries

## Review Process
1. Read MEMORY.md for context on known patterns and previous findings
2. Run `git diff HEAD~3 --name-only` to identify changed files
3. Read each changed file completely
4. Apply review criteria WITH context from memory
5. Update MEMORY.md with new patterns discovered
6. Produce the report

## Output Format
### Code Review Report
**Date:** [current date]
**Files reviewed:** [list]
**Memory context:** [relevant patterns from MEMORY.md applied]
#### CRITICAL (must fix)
- **[file:line]** — Description
#### WARNING (should fix)
- **[file:line]** — Description
#### Summary
- Critical: [n] | Warnings: [n] | Suggestions: [n]
- Verdict: PASS | PASS_WITH_WARNINGS | NEEDS_REVISION
#### Memory Updates
- [list what was added to MEMORY.md this session]

How the reviewer's memory evolves

Session 1 — empty MEMORY.md:

# Reviewer Memory

## Architecture
- FastAPI project with SQLAlchemy ORM
- Routes in src/routes/, models in src/models/

## Conventions
- Snake_case for all Python identifiers
- Type hints required on all public functions

Session 3 — accumulation:

# Reviewer Memory

## Architecture
- FastAPI + SQLAlchemy + Alembic + PostgreSQL
- Background tasks in src/tasks/ using Celery
- Redis caching layer in src/cache/

## Conventions
- Snake_case for all Python identifiers
- All endpoints return standardized {data, error, meta} response
- Exceptions use custom AppError hierarchy (src/exceptions.py)

## Resolved Issues
- routes/products.py:45 SQL injection — FIXED in commit abc123

The reviewer now knows the architecture, the conventions, and the previous issues. When it reviews new code, it applies this context without you repeating anything.

Sharing with the team

git add .claude/agent-memory/reviewer/MEMORY.md
git commit -m "chore: update reviewer memory with project patterns"
git push

When a colleague pulls, their reviewer subagent inherits all that knowledge.


local Scope: Private Project Knowledge

When to use it

The local scope stores memory in .claude/agent-memory-local/{name}/ — inside the project, but gitignored automatically. For information that shouldn't be shared.

What to store in local scope

  • 🔒 Development-environment tokens and credentials
  • 🔒 Test results from your specific machine
  • 🔒 Personal notes about the project

Example: tester with local memory

---
name: tester
description: Runs test suites and reports results
tools: Bash, Read, Glob
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
memory: local
---

## Role
You are a test runner and reporter. You NEVER modify source code.

## Memory Management
Track test results across sessions:
- Record pass/fail counts per module after each run
- Note flaky tests (tests that sometimes pass, sometimes fail)
- Track coverage percentages over time
Keep MEMORY.md under 100 lines — summarize old results, keep recent ones.

## Output Format
### Test Report
**Comparison with last run:** [improved/degraded/stable]
#### Results
- ✅ Passed: [n] (previous: [n from memory])
- ❌ Failed: [n] (previous: [n from memory])
#### Coverage
| Module | Current | Previous | Trend |
|--------|---------|----------|-------|
| [module] | [%] | [% from memory] | ↑/↓/= |
#### Verdict: ALL_PASS | FAILURES | ERROR

The tester uses local because the results depend on your machine — versions, local database, environment variables. It makes no sense to commit that.


Comparison: Which Scope for What?

Decision table

InformationScopeJustification
My personal style preferencesuserApplies to all my projects
Team code conventionsprojectThe team needs to see them
Project architectureprojectShared decision
My development tokenslocalSecrets, don't share
Test results from my machinelocalEnvironment-dependent
Common patterns I use in PythonuserThey're mine, not the project's
Recurring project bugsprojectThe team should know them
Notes about a pending refactorlocalPersonal ideas
Decision: "we use PostgreSQL"projectTeam decision

The three-question rule

When you don't know which scope to use:

1. Is this information for ALL my projects?  → user
2. Does the team need this information?       → project
3. Is it specific to MY environment?          → local

On-disk structure

my-project/
├── .claude/
│   ├── agents/
│   │   ├── reviewer.md          # memory: project
│   │   ├── implementer.md       # memory: project
│   │   └── tester.md            # memory: local
│   └── agent-memory/
│       ├── reviewer/
│       │   └── MEMORY.md        # ← shared via git
│       └── implementer/
│           └── MEMORY.md        # ← shared via git
├── .claude/agent-memory-local/
│   └── tester/
│       └── MEMORY.md            # ← gitignored
└── .gitignore

~/.claude/
└── agent-memory/
    └── style-enforcer/
        └── MEMORY.md            # ← personal, all projects

Memory Instructions in the System Prompt

Why what you write matters

Enabling memory: project creates the infrastructure. But the quality of the memory depends on what the subagent decides to store. Without clear instructions, a subagent may store everything (memory saturated on the first session), store nothing (memory enabled but empty), or store irrelevance (noise that confuses).

Pattern: structured instructions

## Memory Management

Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.

### What to Remember
- Architecture patterns (directory structure, design patterns in use)
- Team conventions (naming, formatting, error handling approach)
- Key decisions (why X library over Y, why this architecture)
- Recurring issues (bugs that keep appearing, common mistakes)

### What NOT to Remember
- Specific code content (it changes — reference files instead)
- One-time issues already fixed
- Personal opinions or subjective assessments

### Format Rules
- One line per entry when possible
- Group by category (Architecture, Conventions, Issues, Patterns)
- If MEMORY.md exceeds 150 lines, consolidate: merge similar entries,
  remove outdated ones, summarize old sections

Pattern: active curation

## Memory Curation

Before writing to MEMORY.md, read it first. Then:
1. Check if the new information already exists — don't duplicate
2. Check if any existing entry is now outdated — update or remove it
3. If adding pushes past 150 lines, consolidate the oldest section
4. Always keep the most recent and most actionable items

Think of MEMORY.md as a living document, not a log.

Verifying Persistence

The smoke test

Step 1: Run the subagent and give it context it should remember.

Use the reviewer to analyze src/routes/products.py

Step 2: Verify that it wrote to MEMORY.md.

cat .claude/agent-memory/reviewer/MEMORY.md

Step 3: Close Claude Code completely.

Step 4: Reopen Claude Code and run the reviewer again.

Use the reviewer to analyze src/routes/users.py

Step 5: Verify that the report references context from the previous session. The reviewer should mention learned patterns or apply conventions it discovered in session 1.

Step 6: Inspect MEMORY.md again.

cat .claude/agent-memory/reviewer/MEMORY.md

It should have entries from both sessions, organized without duplicates.

Verification for project scope

git status
# You should see: new file: .claude/agent-memory/reviewer/MEMORY.md

Verification for local scope

git status
# It should NOT show files in .claude/agent-memory-local/

ls .claude/agent-memory-local/tester/MEMORY.md
# The file exists but git ignores it

Example: Implementer with Project Memory

The implementer needs to remember code conventions to apply them consistently:

---
name: implementer
description: Implements code changes in src/ following project conventions
tools: Read, Glob, Grep, Write, Edit, Bash
model: sonnet
maxTurns: 30
memory: project
---

## Role
You are a senior developer implementing code changes in src/.
Follow existing project conventions — never introduce new patterns.

## Memory Management
Update your agent memory with:
- Code conventions you observe (naming, structure, error handling)
- Architectural decisions referenced in code comments or CLAUDE.md
- Library-specific patterns (e.g., "sessions use context manager")
- File/module purposes you discover

Keep MEMORY.md organized by category. Consolidate if over 150 lines.
When implementing, ALWAYS check MEMORY.md first for conventions.

## Constraints
- ONLY modify files inside src/
- NEVER modify test files, config files, or CLAUDE.md
- Follow conventions from MEMORY.md — they represent team agreements

## Output Format
### Implementation Report
**Files modified:** [list]
**Conventions applied from memory:** [list]
**Changes made:**
1. **[file]** — Description of change
   - Convention: [which memory entry guided this decision]
**Memory updates:** [what was added to MEMORY.md]

Connection to the Project

Toward capsule 05: Memory Hierarchy for 3 Subagents

In capsule 05 you'll implement a complete memory hierarchy:

reviewer    → memory: project ← shares codebase patterns with the team
implementer → memory: project ← shares code conventions with the team
tester      → memory: local   ← test results are private

The configuration you did here is the building block. What capsule 05 adds is the coordination: what happens when the reviewer and the implementer have independent memories? How do you avoid inconsistencies? Capsule 03 (next) addresses exactly that.


Troubleshooting

"MEMORY.md is empty after running the subagent"

Cause: The system prompt doesn't include explicit enough memory instructions. The subagent has the ability to write but doesn't know what to store.

Fix: Add a ## Memory Management section with imperative instructions: "Update your agent memory as you discover..." not "You might want to remember..."

"MEMORY.md grew too fast — it already has 200+ lines"

Cause: The subagent stores everything without curating.

Fix: Add curation instructions:

If MEMORY.md exceeds 150 lines, before adding new entries:
1. Merge similar entries into summaries
2. Remove entries about files that no longer exist
3. Archive resolved issues

"The subagent doesn't read its MEMORY.md at startup"

Cause: The first 200 lines are injected automatically. If MEMORY.md has trivial information at the beginning, the injected context doesn't help.

Fix: Structure MEMORY.md with the most important sections first. Architecture, conventions, and frequent patterns go in the first 200 lines.

"The project scope doesn't appear in git status"

Cause: The .claude/agent-memory/ directory was added to .gitignore by mistake.

Fix:

cat .gitignore | grep agent-memory
# Only .claude/agent-memory-local/ should be in gitignore
# .claude/agent-memory/ (without -local) should NOT be in gitignore

"Two subagents with the same name share memory"

Cause: The memory directory uses the name from the frontmatter. Equal names = same directory.

Fix: Use unique names: reviewer-security and reviewer-performance, not two reviewer.


Exercises

Exercise 1: Enable basic memory (Easy)

Take the todo-finder subagent from Module 1 and add user scope to it. It should remember how many TODOs it found in each session to report trends.

See solution
---
name: todo-finder
description: Finds all TODO and FIXME comments across the codebase
memory: user
---

Search for comments containing TODO, FIXME, HACK, or XXX.

## Memory Management
After each scan, record in MEMORY.md:
- Date of scan and total count by type (TODO, FIXME, HACK, XXX)
- Compare with previous scan and note trend (increasing/decreasing)
Keep only the last 10 scan results in memory.

### TODO/FIXME Report
**Trend:** [count] total ([+/-n] vs last scan from memory)
#### FIXME (urgent)
- **[file:line]** — Comment text
#### TODO (planned)
- **[file:line]** — Comment text
**Total:** [count] items found

Verification: cat ~/.claude/agent-memory/todo-finder/MEMORY.md after running.

Exercise 2: Choose the right scope (Easy)

For each scenario, indicate the correct scope (user, project, or local):

  1. A subagent that remembers the staging API keys
  2. A subagent that remembers the architecture of a project with 5 devs
  3. A subagent that remembers your error-handling patterns across all your projects
  4. A subagent that remembers which tests were flaky on your laptop
  5. A subagent that remembers the project dependencies and why they were chosen
See solution
  1. local — API keys are secrets that aren't committed
  2. project — The architecture is shared team knowledge
  3. user — Personal preferences that apply to all projects
  4. local — Flaky tests depend on your machine/environment
  5. project — Dependencies and their justifications are team decisions

Exercise 3: Write memory instructions (Medium)

Write the ## Memory Management section for a dependency-auditor subagent that reviews the dependencies of a Python project. It should remember: current versions, vulnerabilities, and decisions about why each dependency was chosen.

See solution
## Memory Management

Update your agent memory after each audit:

### What to Remember
- Current dependency versions and when they were last audited
- Known vulnerabilities: severity, status (open/fixed/accepted-risk)
- Decisions: why each key dependency was chosen over alternatives
- Version constraints: why certain packages are pinned
- Incompatibilities discovered between packages

### What NOT to Remember
- Transitive dependencies (too many, too volatile)
- Exact vulnerability CVE details (link to advisory instead)

### Format
| Package | Version | Why Chosen | Last Audited |
|---------|---------|------------|--------------|
| fastapi | 0.104.0 | Team standard | 2026-03-10 |

### Curation Rules
- Update versions after each audit, don't append duplicates
- Remove vulnerability entries once fixed and verified
- If over 100 lines, archive old audit dates — keep only latest

Exercise 4: Verify persistence end-to-end (Medium)

Configure the reviewer with memory: project. Run these steps and document what you see:

  1. Run the reviewer on a project file
  2. Read MEMORY.md and verify it has content
  3. Close Claude Code
  4. Reopen and run the reviewer on a different file
  5. Verify that the report references context from the previous session
  6. Confirm that MEMORY.md has entries from both sessions without duplicates
See solution
# Step 1: Run reviewer
# > "Use the reviewer to analyze src/routes/products.py"

# Step 2: Verify
cat .claude/agent-memory/reviewer/MEMORY.md
# Expected: entries about products.py patterns

# Step 3: Close
# exit

# Step 4-5: Reopen and run on another file
# > "Use the reviewer to analyze src/routes/users.py"
# Expected: the report mentions context from session 1

# Step 6: Verify MEMORY.md
cat .claude/agent-memory/reviewer/MEMORY.md
# Expected: entries from BOTH sessions, organized without duplicates

If MEMORY.md duplicated entries, improve the curation instructions with "Check if the new information already exists — don't duplicate."

Exercise 5: Design the memory hierarchy (Hard)

You have a project with 4 subagents: reviewer, implementer, tester, doc-generator. Design which scope each one uses, which categories of information it stores, and justify the choice. Present it as a table.

See solution
SubagentScopeCategoriesJustification
reviewerprojectArchitecture, conventions, recurring bugsThe team needs consistency in reviews
implementerprojectCode conventions, library patternsThe whole team should follow the same conventions
testerlocalResults, flaky tests, coverage trendsThe results depend on the local environment
doc-generatorprojectDocumentation style, glossaryDocumentation should be consistent across the team

Reviewer and implementer share the project scope but have separate memories (different name = different directories). The tester is in local because your laptop's coverage isn't relevant for CI.

Exercise 6: Debug corrupted memory (Hard)

Your MEMORY.md has 250 lines: an 80-line session log, random notes, and the critical sections (Architecture, Conventions) are after line 200 (not injected). Restructure it so it fits in 150 lines with the priorities at the top.

See solution

Before (250 lines, poorly structured):

## Session Log
- 2026-01-15: Reviewed products.py...
... (80 entries)
## Random Notes
- The team uses PostgreSQL
- There might be a performance issue
## Architecture (line ~180)
- FastAPI + SQLAlchemy + Alembic
## Conventions (line ~220)
- Snake_case everywhere

After (25 lines, well structured):

# Reviewer Memory

## Architecture
- Stack: FastAPI + SQLAlchemy + Alembic + PostgreSQL
- Routes in src/routes/, models in src/models/
- Repository pattern for DB access

## Conventions
- Snake_case for all Python identifiers
- Type hints required on all public functions

## Active Issues
- routes/products.py: N+1 query (found 2026-01-19)

## Resolved Issues
- routes/products.py:45 SQL injection — fixed (2026-01-17)

## Review Summary
- 5 reviews completed (Jan 15-19, 2026)

Changes: Architecture and Conventions at the top (they get injected), session log replaced by a summary, random notes integrated into categories, from ~250 to ~25 lines.


Summary

  • The memory field in the frontmatter accepts three values: user, project, local
  • user (~/.claude/agent-memory/{name}/) is personal and applies to all projects
  • project (.claude/agent-memory/{name}/) is shared via git — team knowledge
  • local (.claude/agent-memory-local/{name}/) is private and gitignored — secrets and local data
  • When you enable memory, MEMORY.md is injected (first 200 lines) into the system prompt automatically
  • The subagent gets Read, Write, Edit enabled for its memory directory
  • The quality of the memory depends on the instructions in the system prompt — be explicit about what to remember and when to curate
  • Verifying persistence requires run → close → reopen → confirm retention
  • The three-question rule: all my projects? → user. Does the team need it? → project. Only my environment? → local
  • The first 200 lines are critical — put the most important thing at the top of MEMORY.md
  • The 3 subagents with memory are the building block of capsule 05's project

Additional Resources

  1. Subagents — Persistent Memory (Anthropic Docs) — Official documentation of the memory field and its scopes
  2. Create Custom Subagents — Complete frontmatter reference including memory
  3. Claude Code Best Practices — Context-organization best practices applicable to MEMORY.md
  4. CLAUDE.md Documentation — How CLAUDE.md complements agent memory
  5. Claude Code Overview — General context of persistence in Claude Code
  6. Prompt Engineering: System Prompts — Principles transferable to memory instructions
  7. Claude Code Tips and Tricks — Tips on context organization
  8. Git Best Practices — Versioning shared configuration files

Next capsule: In capsule 03 you'll tackle the shared-memory problem. You have a reviewer and an implementer, both with memory: project, but with independent memories. How do you keep them from making contradictory decisions? You'll see strategies to share context between subagents without overwriting each other.