Agent Memory Scoping: Why Concurrent Claude Code Agents Need Isolated Memory
By W. Kyle Million (~K¹) | IntuiTek¹ | Published on dev.to/@thebrierfox
Two Claude Code agents. One task each. Running in parallel.
Agent 1 writes context.md. Agent 2 reads context.md. Agent 2 is now running in Agent 1's context instead of its own.
This isn't a bug you'll catch in testing. It surfaces under load — when two agents happen to run at the same moment, overwrite each other's work, or read stale state left by a previous run. By the time you notice, the output is wrong and you have no way to know which agent produced it.
Memory scoping is the architecture pattern that prevents this.
The Problem: Shared Memory in Autonomous Agents
Claude Code agents read and write files. That's their memory. In a single-agent setup, this works fine — there's only one writer.
Add a second agent and you have the classic concurrent write problem. Files don't know about agents. context.md doesn't have a lock. The last write wins.
Three concrete failure modes:
1. Context contamination
Agent A processes customer order 1 and writes findings to working/analysis.md. Before A finishes, Agent B starts processing customer order 2 and reads working/analysis.md as its starting context — now B is reasoning about the wrong order. Neither agent knows anything went wrong.
2. Partial-write corruption
Agent A is mid-write to output.md when Agent B reads it. B gets a partial file: valid JSON up to line 47, then garbage. B's subsequent reasoning is based on malformed data.
3. Stale state loops
Agent A fails halfway through. It leaves working/checkpoint.md in an intermediate state. Next time the cron fires Agent A again, it reads its own stale checkpoint and resumes from the wrong position — often repeating completed work or skipping required steps.
The Pattern: Agent-Scoped Memory Paths
The fix is simple in principle: each agent gets its own memory namespace. No shared state unless explicitly designed.
# Before: every agent writes to the same path
WORKSPACE="$INTUITEK/working/"
# After: each agent writes to its own scoped path
AGENT_ID="${AGENT_NAME:-agent}_${TASK_ID:-$(date +%s)}"
WORKSPACE="$INTUITEK/working/${AGENT_ID}/"
mkdir -p "$WORKSPACE"
Every file write goes to working/{agent_id}/ instead of working/. Agent 1 writes to working/agent_order_1_1713654000/context.md. Agent 2 writes to working/agent_order_2_1713654001/context.md. They never touch each other's files.
The AGENT_ID should be composed of:
- A task-type prefix (human-readable label)
- A unique ID or timestamp (guarantees no collision)
# Examples
AGENT_ID="orders_processor_1713654000"
AGENT_ID="reddit_poster_822629015"
AGENT_ID="content_draft_20260421_153022"
Memory Categories and Isolation Rules
Not all memory should be isolated. Different categories have different access patterns:
Exclusive Memory (always isolated)
Working files, intermediate results, agent-specific context, logs for this run.
working/{agent_id}/
├── context.md # agent's current reasoning state
├── progress.md # task-specific progress tracker
├── scratch/ # temp files this agent creates and reads
└── output/ # completed work product (before review)
Shared-Read Memory (never write; read freely)
Reference data, configuration, prompts, source files.
soul/ # identity files — read-only by all agents
CLAUDE.md # operating instructions — read-only
.env # credentials — read-only (source it; don't write it)
capabilities/ # reusable tools — read-only
Coordination Memory (write with lock; read freely)
Shared state that multiple agents need to see and occasionally update.
coordination/
├── SHARED_MIND.md # operational state — lock before write
├── CURRENT_STATE.md # per-run status — lock before write
└── locks/ # lock files for coordination resources
Output Memory (write once; never overwrite)
Final deliverables. Each run writes new files; nothing is modified in place.
outputs/
├── task_{id}_20260421.md # immutable once written
├── report_{id}_20260421.md # never overwrite existing outputs
└── error_{id}_20260421.md # same for failures
The naming convention {type}_{id}_{date}.md makes outputs inspectable and prevents collision.
Lock Protocol for Coordination Memory
Shared coordination files (SHARED_MIND, CURRENT_STATE) need a lock before write. The protocol:
LOCK_DIR="$INTUITEK/coordination/locks"
RESOURCE_SLUG="shared-mind" # one slug per resource
LOCK_FILE="$LOCK_DIR/${RESOURCE_SLUG}.lock"
MAX_WAIT=30 # seconds
WAIT=0
acquire_lock() {
while [[ -f "$LOCK_FILE" ]]; do
AGE=$(( $(date +%s) - $(stat -c %Y "$LOCK_FILE") ))
if [[ $AGE -gt 300 ]]; then
# Stale lock (5+ min old) — overwrite
break
fi
sleep 2
WAIT=$(( WAIT + 2 ))
if [[ $WAIT -ge $MAX_WAIT ]]; then
echo "Lock timeout after ${MAX_WAIT}s" >&2
exit 1
fi
done
echo "peer: ${AGENT_ID}" > "$LOCK_FILE"
echo "acquired: $(date -Iseconds)" >> "$LOCK_FILE"
}
release_lock() {
rm -f "$LOCK_FILE"
}
For files that only one agent writes but others read, a lock isn't required — the writer is sole. The lock is only for files where multiple agents might write.
Cleanup After Termination
Scoped workspaces accumulate. Production agents running every 10 minutes will fill disk over time if working directories aren't pruned.
Two cleanup strategies:
Strategy A: Keep-on-failure, delete-on-success
cleanup_workspace() {
if [[ $EXIT_CODE -eq 0 ]]; then
rm -rf "$WORKSPACE"
else
# Keep failed workspace for debugging
mv "$WORKSPACE" "$INTUITEK/failed_workspaces/${AGENT_ID}/"
echo "Failed workspace preserved at: failed_workspaces/${AGENT_ID}/"
fi
}
trap 'cleanup_workspace' EXIT
Strategy B: Archive-after-N-days
# Run as cron cleanup job
find "$INTUITEK/working/" -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
Strategy A is better for debugging; Strategy B is better for disk management. In production: use both. Delete on success, archive failed workspaces, prune archives older than 7 days.
The Multi-Agent Test
Before deploying any multi-agent architecture, run this test:
- Start two agent instances with the same task simultaneously
- Check whether output files from Run 1 and Run 2 are in separate directories (PASS) or the same directory (FAIL)
- Check whether Agent 2 read any files written by Agent 1 (FAIL if yes, unless it was explicitly designed to)
- Check whether either agent failed due to a lock conflict that wasn't handled (FAIL)
If you pass all four: your memory scoping is production-grade.
If you fail any of them: you have a concurrency bug that will surface under load.
Why This Matters More as You Scale
Single-agent deployments hide memory scoping problems. They don't surface until you add a second agent, add cron scheduling, or add a retry mechanism that runs the same agent twice.
The pattern that costs nothing to implement when building is expensive to retrofit after the first production incident. Two agents corrupting each other's work is not a theoretical risk — it's the first thing that happens when you horizontally scale a Claude Code setup that was designed for single-agent operation.
The Production Implementation
The patterns above are the foundation. The production implementation includes:
- Agent ID generation utilities with collision-free timestamp-based naming
- Scoped workspace factory with automatic directory creation
- Lock protocol implementation with stale lock detection and exponential backoff
- Memory category classifier for new projects (helps you decide what goes where)
- Cleanup handler for both success/failure paths
- Test harness for validating isolation in concurrent runs
- CLAUDE.md template blocks for embedding memory scoping rules in agent instructions
Agent Memory Scoping — Production Isolation Architecture:
https://www.shopclawmart.com/listings/agent-memory-scoping-production-isolation-architecture-8d66ead8
$19. Instant download. One-time purchase.
Built by Aegis, IntuiTek¹ | ~K¹ (W. Kyle Million)
Tags: claudecode, devtools, aiagents, programming, productivity
Top comments (0)