Module 2: Agent Memory and Scopes

5. Project — Memory Hierarchy for 3 Subagents

5. Project — Memory Hierarchy for 3 Subagents

Project Description

In Module 1 you built 3 specialized subagents — reviewer, implementer, tester — and chained them into a pipeline. They work. But every time you run them, they start from scratch. The reviewer doesn't remember that your project uses cursor-based pagination. The implementer doesn't know the team decided to use separate Pydantic v2 models for request and response. The tester doesn't retain that the payments module's integration test takes 8 seconds and should run last. They're competent but amnesiac.

In this project you're going to solve that by configuring a complete memory hierarchy for the 3 subagents. It's not just adding memory: project to the frontmatter — it's designing what each agent remembers, how it curates its memory, and how one's memory complements (without duplicating) the other's. The reviewer remembers codebase patterns and recurring issues. The implementer remembers code conventions and architectural decisions. The tester remembers test trends and failure patterns. Each agent has a deliberate scope: the reviewer and implementer share via git (project scope), the tester keeps local data that makes no sense to share (local scope).

The result is a 3-agent system that accumulates institutional knowledge. The first run is identical to what you had before. The second is already different — the reviewer mentions "this issue is new, it wasn't in previous sessions." The fifth run is notably better — the implementer applies conventions without you having to remind it, and the tester knows which tests are normally slow. When a new team member clones the repo, the subagents with project scope bring the accumulated knowledge with no explanations.

This is the culminating project of Module 2. If the 3 subagents retain memory across sessions, curate it proactively, and the project-scope memory is shared via git — you've mastered agent memory management.


Project Objective

Configure a persistent memory hierarchy for 3 subagents (reviewer, implementer, tester) with differentiated scopes, self-curation instructions, and verify persistence across sessions.

By the end of this project:

  • ✅ The 3 subagents will have persistent memory configured in their frontmatter
  • ✅ The reviewer and implementer will use project scope (shareable via git)
  • ✅ The tester will use local scope (private, machine data)
  • ✅ Each subagent will have self-curation instructions in its system prompt
  • ✅ MEMORY.md will be created automatically on each subagent's first run
  • ✅ The memory will persist across sessions: closing and reopening Claude Code doesn't erase it
  • ✅ The second run of each subagent will show use of accumulated memory
  • ✅ The project memories will be committed in git to share with the team

Estimated duration: 1-1.5 hours (configuration: 20 min + initial run: 20 min + persistence verification: 15 min + second run: 15 min + git commit and validation: 10 min).


Technical Specifications

Technology Stack

  • Tool: Claude Code v2.1.63+
  • Subagent files: Markdown with YAML frontmatter
  • Subagent location: .claude/agents/ (project scope)
  • Project memory location: .claude/agent-memory/{name}/MEMORY.md
  • Local memory location: .claude/agent-memory-local/{name}/MEMORY.md
  • Base project: The same project used in Module 1 (with code in src/, tests, and commits in git)

Prerequisites

RequirementDetail
Module 1 completedThe 3 subagent files exist in .claude/agents/
Project with codesrc/ with files, tests with a runnable suite
Git initializedExisting commits, clean git status
Claude Code v2.1.63+Support for the memory field in the frontmatter

Final Project Structure

By the end, your project will have this additional structure:

your-project/
├── .claude/
│   ├── agents/
│   │   ├── code-reviewer.md          ← memory: project
│   │   ├── code-implementer.md       ← memory: project
│   │   └── code-tester.md            ← memory: local
│   ├── agent-memory/                  ← project scope (git tracked)
│   │   ├── code-reviewer/
│   │   │   └── MEMORY.md             ← patterns, recurring issues
│   │   └── code-implementer/
│   │       └── MEMORY.md             ← conventions, decisions
│   └── agent-memory-local/            ← local scope (gitignored)
│       └── code-tester/
│           └── MEMORY.md             ← test performance, failure patterns
├── src/
├── tests/
├── CLAUDE.md
└── .gitignore                         ← includes .claude/agent-memory-local/

Step-by-Step Guide

Step 1: Verify the Current State

Before adding memory, verify that the 3 subagents from Module 1 exist and work.

ls -la .claude/agents/

You should see:

code-reviewer.md
code-implementer.md
code-tester.md

Open Claude Code and verify:

/agents

The 3 should appear listed. If any is missing, create it first (reference: Module 1, capsule 05).

Verify that no previous memory directories exist:

ls .claude/agent-memory/ 2>/dev/null || echo "Doesn't exist (expected)"
ls .claude/agent-memory-local/ 2>/dev/null || echo "Doesn't exist (expected)"

Step 2: Configure the Code Reviewer with Memory

Edit .claude/agents/code-reviewer.md. Add memory: project to the frontmatter and a Memory Management section to the system prompt.

Complete file:

---
name: code-reviewer
description: Analyzes recent code changes against quality criteria with persistent memory of project patterns. Read-only — never modifies files.
tools: Read, Grep, Glob, Bash
disallowedTools: Write, Edit
model: haiku
maxTurns: 15
memory: project
---

## Role

You are a senior code reviewer with persistent memory. You analyze recent git changes and produce a structured report organized by severity. You NEVER modify any file. Your job is to find problems — fixing them is someone else's responsibility.

You have memory of previous sessions. Use your MEMORY.md to:
- Avoid re-reporting known issues that haven't changed
- Apply project conventions consistently
- Track patterns across sessions
- Note when a previously recurring issue has been fixed

## Process

1. Read your MEMORY.md to recall project context
2. Run `git diff HEAD~3 --name-only` to identify recently changed files
3. Filter: only review files in `src/` (skip tests, configs, docs)
4. For each changed file:
   a. Read the complete file
   b. Read related files (imports, parent classes, interfaces) for context
   c. Apply review criteria, informed by your memory of project patterns
5. Compare findings against your memory:
   - If an issue was already reported and not fixed → note as "recurring"
   - If a previously recurring issue was fixed → note as "resolved"
   - If a new pattern is discovered → note for memory update
6. Produce the report in the exact output format below
7. Update your MEMORY.md with new insights

If `git diff HEAD~3` returns no files, try `git diff HEAD~1` or report that no recent changes were found.

## Review Criteria

### 1. Readability
- Functions longer than 30 lines
- Deeply nested logic (3+ levels)
- Unclear control flow

### 2. Naming Conventions
- Variables/functions not following project conventions (check memory for conventions)
- Inconsistent naming style within a file

### 3. Error Handling
- Bare `except:` or `except Exception:`
- Silenced errors (empty except blocks)
- Missing error handling on I/O, network, or database operations

### 4. Security
- Hardcoded credentials, API keys, or secrets
- User input used without validation or sanitization
- SQL queries built with string concatenation or f-strings

### 5. Performance
- Database queries inside loops (N+1 pattern)
- Loading large collections without pagination or limits
- Blocking operations in async context

### 6. Edge Cases
- Missing null/None checks before attribute access
- No handling of empty collections
- Missing boundary value validation

### 7. DRY (Don't Repeat Yourself)
- Duplicated logic blocks (3+ lines repeated)
- Copy-pasted code with minor variations

### 8. Type Safety
- Missing type hints on function signatures
- Using `Any` where a specific type is known

## Output Format

Follow this EXACT structure:

Code Review Report

Date: [YYYY-MM-DD] Commit range: HEAD~3..HEAD Files reviewed: [list of files] Memory status: [n] entries loaded from previous sessions

CRITICAL (must fix before merge)

  • [file:line] — [Short description]
    • Criteria: [which of the 8 criteria]
    • Evidence: [relevant code snippet]
    • Recommendation: [specific fix]
    • Status: [NEW | RECURRING (seen in [n] previous sessions)]

WARNING (should fix)

  • [file:line] — [Short description]
    • Criteria: [which of the 8 criteria]
    • Recommendation: [specific fix]
    • Status: [NEW | RECURRING]

SUGGESTION (nice to have)

  • [file:line] — [Short description]
    • Recommendation: [specific improvement]

Previously Recurring Issues — Now Resolved

  • [issue description] — Fixed in [file]

Summary

PriorityCountNewRecurring
Critical[n][n][n]
Warning[n][n][n]
Suggestion[n][n][n]

Verdict: [PASS | PASS_WITH_WARNINGS | NEEDS_REVISION]


If no issues are found in a category, write "None found."

## Memory Management

At the END of each session, update your MEMORY.md following these rules:

### Categories (use exactly these)
- **Architecture Decisions:** High-level design decisions observed in the codebase
- **Coding Conventions:** Naming, formatting, import ordering, style patterns
- **Known Patterns:** Authentication, validation, error handling patterns used in the project
- **Recurring Issues:** Issues found in 2+ sessions — track frequency

### Organization rules
- Most important items at the TOP of each category
- Each entry is a single line starting with "- "
- For Recurring Issues, include frequency: "- [3x] N+1 queries in product listings"
- No timestamps, no session narratives

### Size constraint
- Keep MEMORY.md under 150 lines
- If approaching 150 lines, remove least frequent Recurring Issues first
- Architecture Decisions are PERMANENT unless explicitly reverted
- NEVER exceed 180 lines total

### What NOT to store
- Information already in CLAUDE.md
- Temporary debugging observations
- Information obvious from reading pyproject.toml or package.json
- Individual file contents or code snippets

Step 3: Configure the Code Implementer with Memory

Edit .claude/agents/code-implementer.md. Add memory: project and a Memory Management section.

Complete file:

---
name: code-implementer
description: Fixes code issues from review reports with persistent memory of project conventions. Only modifies files in src/. Follows CLAUDE.md and accumulated conventions.
tools: Read, Edit, Write, Grep, Glob
disallowedTools: Bash
model: sonnet
maxTurns: 25
memory: project
---

## Role

You are a senior developer with persistent memory who fixes code issues identified in review reports. You work exclusively in `src/`. You follow existing project conventions — and you remember them from previous sessions.

You have memory of previous sessions. Use your MEMORY.md to:
- Apply coding conventions consistently without rediscovering them
- Remember architectural decisions and follow them
- Recall CLAUDE.md conventions that you've learned
- Avoid repeating implementation mistakes from previous sessions

## Constraints

- ONLY modify files inside `src/`
- NEVER modify files in `tests/`, `test/`, or any test file
- NEVER modify configuration files (*.yml, *.toml, *.cfg, *.json at root)
- NEVER modify CLAUDE.md, README.md, or documentation files
- NEVER install new dependencies
- NEVER delete files
- Follow the coding style already present in the project AND in your memory

## When Receiving a Review Report

Read the entire report first. Then:

1. **CRITICAL items:** Fix ALL of them. These are blockers.
2. **WARNING items:** Fix if the change is straightforward (< 10 lines changed). Skip if it requires architectural changes.
3. **SUGGESTION items:** SKIP unless explicitly asked to address them.
4. **RECURRING items:** Prioritize these — they indicate systematic issues.

For each fix:
- Check your memory for relevant conventions before editing
- Read the file and surrounding context before editing
- Make the minimal change that resolves the issue
- Preserve existing code style (indentation, quotes, naming)
- If a fix could affect other files, read those files first

## Process

1. Read your MEMORY.md to recall project conventions and decisions
2. Read CLAUDE.md for project-level conventions
3. Parse the review report to extract all items by priority
4. For each CRITICAL item:
   a. Check memory for relevant conventions
   b. Read the file mentioned
   c. Understand the context around the problematic code
   d. Apply the fix following known conventions
   e. Record what you changed
5. For each WARNING item (if straightforward):
   a. Same process as CRITICAL
6. Produce the implementation report
7. Update your MEMORY.md with new conventions or decisions discovered

## Output Format

Follow this EXACT structure:

Implementation Report

Files modified: [list of files changed] Review items addressed: [n] of [total] Memory entries used: [list conventions/decisions from memory that guided implementation]

Changes Made

  1. [file:line] — [What was changed]
    • Review item: [CRITICAL|WARNING] — [original description]
    • Fix applied: [description of the fix]
    • Convention applied: [from memory or CLAUDE.md]
    • Lines changed: [n]

Items Not Addressed

  • [file:line] — [original description]
    • Reason: [why it was skipped]

New Conventions Discovered

  • [any new convention or pattern discovered during implementation]

Summary

CategoryFoundFixedSkipped
Critical[n][n][n]
Warning[n][n][n]
Suggestion[n][n][n]

## Memory Management

At the END of each session, update your MEMORY.md following these rules:

### Categories (use exactly these)
- **Architecture Decisions:** Design patterns, service boundaries, data flow decisions
- **Coding Conventions:** Naming, formatting, import ordering, docstring style, error handling patterns
- **File Organization:** Where different types of code live, module structure
- **Dependency Decisions:** Libraries chosen, versions, why alternatives were rejected

### Organization rules
- Most important items at the TOP of each category
- Each entry is a single line starting with "- "
- Be specific: "snake_case for functions" not "use good naming"
- Include the WHY when non-obvious: "- cursor pagination (not offset) — performance on tables > 1M rows"

### Complementary to reviewer's memory
- You own Coding Conventions and Architecture Decisions (most detailed here)
- The reviewer owns Known Patterns and Recurring Issues
- Don't duplicate what the reviewer tracks — focus on implementation knowledge

### Size constraint
- Keep MEMORY.md under 150 lines
- If approaching 150 lines, remove Dependency Decisions with obvious choices first
- Architecture Decisions and Coding Conventions are priority — never remove these to make space
- NEVER exceed 180 lines total

### What NOT to store
- Information already in CLAUDE.md (don't duplicate)
- Review findings (that's the reviewer's job)
- Test results or coverage data (that's the tester's job)
- Temporary implementation notes

Step 4: Configure the Code Tester with Memory

Edit .claude/agents/code-tester.md. Add memory: local and a Memory Management section.

The tester uses local scope because:

  • Test execution times depend on the hardware
  • Virtualenv paths and environment configuration are machine-specific
  • Coverage trends can differ between developers (test subsets, configurations)
  • Failure patterns by environment (OS-specific, memory, concurrent processes) are local

Complete file:

---
name: code-tester
description: Runs test suites and reports results with persistent memory of test performance trends and failure patterns. Never modifies code.
tools: Bash, Read, Grep, Glob
disallowedTools: Write, Edit
model: haiku
maxTurns: 12
memory: local
---

## Role

You are a test runner and reporter with persistent memory. You execute the project's test suite and produce a detailed report. You NEVER modify source code, test files, or any other file. If tests fail, your job is to report WHY they fail — not to fix them.

You have memory of previous test runs. Use your MEMORY.md to:
- Compare current results with historical trends
- Identify new failures vs pre-existing failures
- Track test suite execution time trends
- Note which tests are consistently slow or flaky

## Process

1. Read your MEMORY.md to recall test history
2. **Detect the test framework:**
   - Check for `pyproject.toml`, `setup.cfg` → pytest
   - Check for `package.json` → jest, vitest, or mocha
   - Check for `Cargo.toml` → cargo test
   - If unclear, look for test files and infer
3. **Run the full test suite:**
   - Python (pytest): `python -m pytest -v --tb=short 2>&1`
   - Python (with coverage): `python -m pytest --cov=src --cov-report=term-missing -v 2>&1`
   - Node (jest): `npx jest --verbose 2>&1`
   - Node (vitest): `npx vitest run --reporter=verbose 2>&1`
   - Always redirect stderr to stdout with `2>&1`
4. **Analyze results against memory:**
   - New failures (not in memory) → mark as NEW
   - Known failures (in memory) → mark as KNOWN
   - Previously failing tests now passing → mark as FIXED
   - Execution time compared to memory → note if significantly slower/faster
5. **If tests fail:**
   - Read the failing test file to understand what it expects
   - Read the source file the test is testing
   - Determine likely root cause
   - Do NOT attempt to fix anything
6. Produce the report
7. Update your MEMORY.md with current run data

## Output Format

Follow this EXACT structure:

Test Report

Framework: [detected framework and version] Command: [exact command executed] Execution time: [seconds] ([FASTER|SLOWER|STABLE] vs last run: [previous time])

Results

StatusCountvs Last Run
✅ Passed[n][+/-n]
❌ Failed[n][+/-n]
⏭️ Skipped[n][+/-n]
Total[n]

Failed Tests

(If no failures, write "All tests passed.")

  1. [test_file::TestClass::test_name]
    • Status: [NEW failure | KNOWN failure (seen [n] times) | REGRESSION (was passing)]
    • Expected: [what the test expected]
    • Got: [what actually happened]
    • Error: [error message]
    • Root cause: [your analysis]

Previously Failing — Now Fixed

  • [test name] — was failing since [first seen], now passes

Slow Tests (> 2s)

TestTimeTrend
[test name][seconds][STABLE

Coverage

(If coverage data is available)

ModuleCoveragevs Last Run
[module][%][+/-pp]
Total[%][+/-pp]

Verdict

[ALL_PASS | FAILURES | ERROR]


## Memory Management

At the END of each session, update your MEMORY.md following these rules:

### Categories (use exactly these)
- **Test Performance:** Suite execution times (keep last 5 runs), slow tests (> 2s)
- **Failure Patterns:** Tests that have failed in 2+ sessions with root cause
- **Coverage Trends:** Module coverage percentages (keep last 3 snapshots)
- **Environment Notes:** Test framework detected, command used, virtualenv path, OS-specific notes
- **Flaky Tests:** Tests that pass/fail inconsistently — track pass rate

### Organization rules
- Most recent data at the TOP within each category
- For Performance, keep a running log: "- [2026-03-13] 45s (82 tests)"
- For Failures, track frequency: "- [5x] test_payment_timeout — root cause: mock not cleaning up"
- For Coverage, keep snapshots: "- [2026-03-13] total: 78%, src/api: 85%, src/models: 72%"

### Size constraint
- Keep MEMORY.md under 120 lines (test data changes more frequently)
- Keep only last 5 performance entries (remove oldest)
- Keep only last 3 coverage snapshots
- Remove failure patterns for tests that have been deleted
- NEVER exceed 150 lines total

### What NOT to store
- Full test output or stack traces (only root cause summaries)
- Individual test results that passed (only failures and slow tests)
- Dependency versions (obvious from config files)
- One-time failures that didn't recur

Step 5: Configure .gitignore for Local Memory

Add the local memory folder to .gitignore so it's not committed by accident.

echo "" >> .gitignore
echo "# Claude Code local memory (machine-specific, not shared)" >> .gitignore
echo ".claude/agent-memory-local/" >> .gitignore

Verify:

grep "agent-memory-local" .gitignore

The project memory (in .claude/agent-memory/) is NOT added to .gitignore — that's the one shared via git.

Step 6: First Run — Create Initial Memories

Now run each subagent once so they create their initial MEMORY.md files.

6a. Run the reviewer:

Use the code-reviewer to analyze the project's recent changes

After the run, verify that the memory was created:

ls -la .claude/agent-memory/code-reviewer/
cat .claude/agent-memory/code-reviewer/MEMORY.md

You should see a MEMORY.md file with the categories defined in the system prompt, populated with insights from this first run.

What to verify:

  • ✅ The file exists in .claude/agent-memory/code-reviewer/
  • ✅ It uses the correct categories: Architecture Decisions, Coding Conventions, Known Patterns, Recurring Issues
  • ✅ The content reflects real project patterns (not generic ones)
  • ✅ It's under 150 lines
  • ✅ It doesn't duplicate information from CLAUDE.md

6b. Run the implementer:

Use the code-implementer to add type hints to the functions in src/ that don't have them

Verify:

ls -la .claude/agent-memory/code-implementer/
cat .claude/agent-memory/code-implementer/MEMORY.md

What to verify:

  • ✅ The file exists in .claude/agent-memory/code-implementer/
  • ✅ Categories: Architecture Decisions, Coding Conventions, File Organization, Dependency Decisions
  • ✅ Complementary to the reviewer (doesn't duplicate Known Patterns or Recurring Issues)
  • ✅ Specific content: concrete convention names, not generic ones

6c. Run the tester:

Use the code-tester to run the project's test suite

Verify:

ls -la .claude/agent-memory-local/code-tester/
cat .claude/agent-memory-local/code-tester/MEMORY.md

What to verify:

  • ✅ The file exists in .claude/agent-memory-local/code-tester/ (local, not project)
  • ✅ Categories: Test Performance, Failure Patterns, Coverage Trends, Environment Notes, Flaky Tests
  • ✅ It contains real data: execution time, test count, coverage
  • ✅ Environment Notes has the detected framework and the command used

Step 7: Verify Persistence — Close and Reopen

This is the most important step. Memory is only worth it if it persists across sessions.

7a. Close Claude Code:

Exit the current Claude Code session completely.

/exit

7b. Verify that the files are still there:

cat .claude/agent-memory/code-reviewer/MEMORY.md
cat .claude/agent-memory/code-implementer/MEMORY.md
cat .claude/agent-memory-local/code-tester/MEMORY.md

The 3 files should exist with the content from the previous session.

7c. Reopen Claude Code:

claude

7d. Run the reviewer again:

Use the code-reviewer to analyze the project's recent changes

What to observe in the second run:

  • ✅ The report mentions "Memory status: [n] entries loaded from previous sessions"
  • ✅ If there are issues identical to the previous session, they appear as "RECURRING" instead of "NEW"
  • ✅ If any issue was resolved, it appears under "Previously Recurring Issues — Now Resolved"
  • ✅ MEMORY.md is updated without duplicating existing entries

7e. Verify that the memory was updated (not duplicated):

wc -l .claude/agent-memory/code-reviewer/MEMORY.md
cat .claude/agent-memory/code-reviewer/MEMORY.md

The line count should be similar to the previous session's (±10 lines). If everything got duplicated, the curation instructions need adjustment.

Step 8: Second Run of the Complete Pipeline

Run the complete pipeline to verify that memory works in the chained flow:

Run reviewer → implementer → tester in sequence.
The reviewer should distinguish new issues from recurring ones.
The implementer should apply conventions from its memory.
The tester should compare results with previous runs.
Give me a consolidated summary at the end.

What to observe: The reviewer classifies issues as NEW or RECURRING. The implementer mentions "Convention applied: [from memory]." The tester compares: "45s (vs 42s last run)", "test_X: KNOWN failure."

Step 9: Git Commit to Share Project-Scope Memories

The memories with project scope must be committed so the team shares them.

git add .claude/agent-memory/
git status

Verify that git status shows:

new file: .claude/agent-memory/code-reviewer/MEMORY.md
new file: .claude/agent-memory/code-implementer/MEMORY.md

Verify that it does NOT show files from .claude/agent-memory-local/ (they should be in .gitignore).

git commit -m "Add agent memory for reviewer and implementer (project scope)

- Reviewer: codebase patterns, naming conventions, recurring issues
- Implementer: coding conventions, architecture decisions, file organization
- Tester memory is local scope (machine-specific, not committed)"

Step 10: Verify the Tester's Local Scope

Confirm that the tester's memory is NOT in the commit:

git show HEAD --stat

You should only see files from code-reviewer and code-implementer. The tester's memory is in .claude/agent-memory-local/ which is gitignored — it exists locally but isn't shared.


The 3 Complete Subagent Files — Reference

Quick reference of differences

Aspectcode-reviewercode-implementercode-tester
Memory scopeprojectprojectlocal
Shareable via git✅✅❌
Memory categoriesPatterns, IssuesConventions, ArchitecturePerformance, Failures
Line limit150150120
ComplementarityPatterns + IssuesConventions + DecisionsTest-specific data
Auto-curation✅ (in system prompt)✅ (in system prompt)✅ (in system prompt)

Where each memory lives

Reviewer (project):
  .claude/agent-memory/code-reviewer/MEMORY.md
  → git tracked, shared with team

Implementer (project):
  .claude/agent-memory/code-implementer/MEMORY.md
  → git tracked, shared with team

Tester (local):
  .claude/agent-memory-local/code-tester/MEMORY.md
  → gitignored, machine-specific

Why each scope

AgentScopeReason
ReviewerprojectPatterns and issues are the team's — a new dev should know them when cloning
ImplementerprojectConventions and decisions are the team's — everyone should follow them
TesterlocalTest times depend on the hardware, failure patterns vary by OS/environment

Validation Checklist

Updated subagent files

  • code-reviewer.md has memory: project in the frontmatter
  • code-reviewer.md has a Memory Management section in the system prompt
  • code-implementer.md has memory: project in the frontmatter
  • code-implementer.md has a Memory Management section in the system prompt
  • code-tester.md has memory: local in the frontmatter
  • code-tester.md has a Memory Management section in the system prompt

Memory files created

  • .claude/agent-memory/code-reviewer/MEMORY.md exists and has content
  • .claude/agent-memory/code-implementer/MEMORY.md exists and has content
  • .claude/agent-memory-local/code-tester/MEMORY.md exists and has content

Correct memory content

  • Reviewer memory has: Architecture Decisions, Coding Conventions, Known Patterns, Recurring Issues
  • Implementer memory has: Architecture Decisions, Coding Conventions, File Organization, Dependency Decisions
  • Tester memory has: Test Performance, Failure Patterns, Coverage Trends, Environment Notes, Flaky Tests
  • There's no significant duplication between reviewer and implementer
  • All memories are under their line limit (150/150/120)

Persistence verified

  • You closed Claude Code and reopened it
  • The MEMORY.md files still exist with their content
  • The reviewer's second run uses the memory (shows "entries loaded" or marks issues as RECURRING)
  • The tester's second run compares with historical data

Correct scopes

  • .gitignore includes .claude/agent-memory-local/
  • git status does NOT show files from agent-memory-local
  • Project memories are committed in git
  • Local memory is NOT in the commit

Complementarity

  • The reviewer doesn't record code conventions (the implementer does that)
  • The implementer doesn't record recurring issues (the reviewer does that)
  • The tester doesn't record codebase patterns (reviewer/implementer do that)

Pipeline with memory

  • The complete pipeline (reviewer → implementer → tester) works with the 3 memories active
  • The consolidated summary includes memory references (recurring issues, conventions applied, test comparison)

Common Errors and Solutions

Error 1: "MEMORY.md isn't created after running the subagent"

Symptom: You run the subagent but .claude/agent-memory/{name}/ doesn't exist or is empty.

Possible causes:

  • The memory field isn't in the frontmatter or is misspelled
  • The field value isn't valid (memory: project, not memory: "project" with quotes in some parsers)
  • Claude Code doesn't have permissions to create directories

Solution:

Verify the frontmatter:

head -10 .claude/agents/code-reviewer.md

Confirm that memory: project appears between the ---. If you use quotes, try without them. The value must be exactly project, local, or user.

If the directory isn't created automatically, create it manually and let the agent write the file:

mkdir -p .claude/agent-memory/code-reviewer

Error 2: "MEMORY.md duplicates on every session"

Symptom: Each run adds all the entries again, duplicating the content.

Cause: The Memory Management instructions don't specify "update existing entries" — the agent interprets that it should always add.

Solution: Add this instruction at the start of the Memory Management section:

### Update rules
- READ your current MEMORY.md before making ANY changes
- UPDATE existing entries if the information changed
- ADD new entries only if they don't already exist
- REMOVE entries that are no longer accurate
- NEVER duplicate an existing entry — update it in place

Error 3: "The tester's memory appears in git status"

Symptom: git status shows files in .claude/agent-memory-local/.

Cause: .gitignore doesn't have the right rule, or it was committed before adding the rule.

Solution:

grep "agent-memory-local" .gitignore

If it doesn't appear, add:

echo ".claude/agent-memory-local/" >> .gitignore

If it's already in .gitignore but the files keep appearing, it's because they were tracked before:

git rm -r --cached .claude/agent-memory-local/
git commit -m "Remove local memory from tracking"

Error 4: "The reviewer and implementer have contradictory information"

Symptom: The reviewer says "offset pagination" and the implementer says "cursor-based pagination."

Solution: Establish a source of truth in both system prompts: the implementer is the source of truth for Architecture Decisions and Coding Conventions, the reviewer for Known Patterns and Recurring Issues. If there's a contradiction, the agent that isn't the source of truth updates its memory to match.

Error 5: "The memory grows out of control despite the instructions"

Symptom: MEMORY.md exceeds the line limit.

Solution: Reinforce with "CRITICAL CONSTRAINT: Before adding ANY new entry, check the line count. If it exceeds [limit], remove at least one entry first. This is a HARD LIMIT." You can also verify and curate manually with wc -l and your editor.

Error 6: "The subagent doesn't use the memory"

Symptom: Output identical to that of an agent without memory. It doesn't mark issues as RECURRING.

Solution: Verify that MEMORY.md has fewer than 200 lines (wc -l). If it has content but the agent doesn't use it, add at the start of the system prompt: "IMPORTANT: You have persistent memory. Read your MEMORY.md at the START of every session and reference specific entries in your output."

Error 7: "I don't know if the memory really persists or is recreated from scratch"

Symptom: Doubts about whether the agent uses the previous memory or recreates it.

Solution: Add a manual "canary" entry:

echo "- [CANARY] This entry was manually added to verify persistence" >> \
  .claude/agent-memory/code-reviewer/MEMORY.md

Run the subagent. If [CANARY] is still present after the run, the memory persists. If it disappeared, there's a problem with persistence.

Error 8: "The implementer doesn't follow the conventions in its own memory"

Symptom: MEMORY.md says "snake_case for functions" but the implementer creates functions with camelCase.

Solution: In the Process section, make the connection explicit: "For EVERY file you edit, check your Coding Conventions section and apply them. If a convention in your memory contradicts the current code, follow the code (it may have changed) and update your memory."


Project Resources

  1. Subagents — Persistent Memory (Anthropic Docs) — Official documentation of the memory field, scopes, and the MEMORY.md mechanism
  2. Create Custom Subagents — Complete YAML frontmatter reference including memory, hooks, and all optional fields
  3. Claude Code Best Practices — Context-management and CLAUDE.md best practices that complement agent memory
  4. Prompt Engineering: Be Clear and Direct — Clarity techniques applicable to self-curation and memory management instructions
  5. Claude Code CLI Reference — CLI reference for verifying subagents with /agents and debugging
  6. Claude Models Documentation — Model and context-window reference for understanding memory's impact on performance

Connection to the Next Module

You've built a 3-agent system with persistent memory. Each one remembers what it needs, curates its own memory, and shares (or doesn't) via git depending on the scope. It's a fundamental improvement over the amnesiac agents from Module 1. But they still have a limitation: they work in sequence.

The reviewer finishes before the implementer starts. The implementer finishes before the tester runs. In a 3-agent pipeline, this is acceptable — the flow is linear and each agent needs the previous one's output. But imagine a project where you need:

  • One agent reviewing the backend while another reviews the frontend
  • One agent generating tests while another updates the documentation
  • Three agents implementing different features in parallel

Sequential execution would triple the time. What you need is parallel delegation — multiple subagents working simultaneously.

But this is where the memory you configured becomes critical. If two agents work in parallel without shared context, they can make contradictory decisions. The backend agent decides to use snake_case while the frontend one uses camelCase. The test agent generates tests for an interface that the implementation agent changed. Without the memory shared via project scope, parallel delegation produces coordinated chaos.

Module 3: Parallel Sub-Agent Delegation teaches you to run subagents in parallel with the guarantee that shared memory maintains consistency. The subagents with memory you created here are the ones you'll parallelize — and memory is what prevents parallelization from sacrificing coherence.


Summary

  • You configured memory: project for the reviewer and implementer — their memories are shared via git with the team
  • You configured memory: local for the tester — its performance and environment data are machine-specific
  • Each subagent has self-curation instructions in its system prompt with categories, line limits, and prioritization rules
  • The memories are complementary: the reviewer records patterns and issues, the implementer records conventions and decisions, the tester records performance and failures
  • You verified persistence by closing and reopening Claude Code — the MEMORY.md files survive across sessions
  • The second run produces different results from the first: issues marked as RECURRING, conventions applied from memory, test results compared with history
  • The project memories are committed in git — a new team member gets the institutional knowledge when cloning
  • The local memory is gitignored — machine data doesn't contaminate the shared repository
  • The memory configured here is a prerequisite for Module 3 — without shared context, parallel delegation produces contradictory decisions

Next module: Module 3 (Parallel Sub-Agent Delegation) teaches you to run multiple subagents simultaneously. You'll use the agents with memory you configured here and learn to coordinate their work in parallel — reviewing backend and frontend at the same time, implementing multiple concurrent features, running test suites in parallel. The shared memory you configured is the foundation that guarantees consistency in parallel execution.