Giving Your AI Agents Memory That Travels With Them
The Problem
I run about 10 specialist agents in Claude Code: a CTO agent for architecture decisions, a CFO for financial modeling, a Forge agent that builds my dev tooling, a grants pipeline agent, and so on. Each agent has a clear identity defined in ~/.claude/agents/{name}.md with frontmatter, system prompts, and scoped tools.
The problem: they’re all amnesiacs.
Every session starts cold. The CTO agent doesn’t remember the architecture decision it made yesterday. Forge doesn’t know what it shipped last session. When I launch the CTO agent inside the grants project, it picks up grants’ status.md and BACKLOG.md (great for project context) but it has zero memory of its own work across projects.
Claude Code’s built-in project memory (~/.claude/projects/) is keyed by directory path, not by agent. So the CTO agent’s work in project A is invisible when it’s launched in project B.
What I Wanted
When I launch any specialist agent from any project directory, it should know:
- What it was last doing (last session summary, which project, what was accomplished)
- What’s on its plate (agent-scoped backlog, not project tasks, but agent responsibilities)
- What it’s learned (operational patterns specific to how that agent works)
- What this project needs (project status, backlog, lessons, already solved)
Items 1-3 are agent state. Item 4 is project state. The gap was entirely in agent state.
The Design
Two layers, deliberately simple:
Layer 1: State Files
~/.claude/state/
forge.md
cto.md
cfo.md
cpo.md
grants.md
...
Each file is structured markdown, under 40 lines, read every session:
---
updated: 2026-04-10
agent: cto
---
# CTO Agent State
## Last Session
- **Date:** 2026-04-10
- **Project:** pike-acm (Agentic Content Manager)
- **Summary:** Orientation pass. ACM has significant uncommitted
work from prior sessions. ADF layout migration still pending.
## Agent Backlog
- Review ACM distribute stage architecture if asked
- B6 (ADF layout migration) may need CTO input
## Recent Learnings
- pike-acm has dual status files (docs/status.md for ADF,
.status/status.md for pipeline runtime) — intentional, not debt
## Key Decisions
(None this session)
Zero infrastructure dependency. It’s just a file. Any agent can read it on startup, write it on close.
Layer 2: Memory MCP Namespaces
I already run a Memory MCP server with namespace-based scoping. Each namespace has access control via client profiles. I added an agent-{name} namespace for each agent:
# memory_config.yaml
namespaces:
canonical:
agent-forge:
aliases: [forge]
agent-cto:
aliases: [cto]
# ... one per agent
client_profiles:
forge:
allowed_namespaces: [global, agent-forge, pike-agents,
capabilities-registry, adf]
can_cross_scope: false
cto:
allowed_namespaces: [global, agent-cto, even-ground,
pike, risk, agf, nerve-center]
can_cross_scope: false
This gives each agent a private memory space for cross-session semantic search. The state file is the quick-reference snapshot; the Memory MCP namespace is the searchable depth.
Wiring It Into the Lifecycle
The key insight: don’t create one-off mechanisms. I already had /orient (read state on startup) and /session-wrap (capture state on close) skills that every agent runs. Adding agent state was two surgical edits:
/orient: Added Step 0
### Step 0: Read Agent State
If you are a named agent, read your agent state file at
`~/.claude/state/{your-agent-name}.md`.
Note what you were last working on, your agent backlog,
and recent learnings. If the file doesn't exist, note
"No prior agent state" and continue.
Before any project files are read, the agent loads its own context first.
/session-wrap: Added Steps 5 and 5b
### Step 5: Agent State Update
Write your state file with: last session summary,
agent backlog (carry forward + update), recent learnings,
key decisions. Keep under 40 lines.
### Step 5b: Agent Memory Capture
write_memory(
content: "{session summary}",
namespace: "{your-agent-name}",
writer_id: "{your-agent-name}",
writer_type: "agent",
source_project: "{project name}"
)
Agent Definitions
Each agent’s system prompt got a small section:
## Agent State
Your persistent state file is `~/.claude/state/cto.md`.
Your Memory MCP namespace is `agent-cto` (caller_id: `cto`).
- On orient: Read your state file + project files. Report both.
- On /session-wrap: Write your state file + write to Memory MCP.
And each agent’s initialPrompt was updated to read the state file first:
initialPrompt: "Read your agent state at ~/.claude/state/cto.md,
then read project status.md, BACKLOG.md, and lessons.md.
Summarize both agent state and project state in 3-5 lines,
then ask what we're working on."
Testing It
I didn’t modify the real agents first. I created a test-forge agent, a copy of Forge with the state mechanism bolted on. Cheap to throw away if it broke.
Test 1: Launched test-forge from ~/code/tools/ai-dev/. It correctly identified no prior state, read the project files, did some work, and on wrap wrote ~/.claude/state/forge.md.
Test 2: Launched test-forge from ~/code/sandbox/grant-pipeline/, a completely different project. It read back the agent state from Test 1 (“Previous session: ai-dev, validated agent state mechanism…”) AND picked up the grants project context.
Agent memory traveled across projects. The mechanism worked.
Test 3: Promoted to the real CTO agent, launched from ~/code/clients/pike/pike-acm. Clean orient: “CTO Agent State: Fresh, no prior sessions tracked.” Read ACM’s status and backlog. On wrap, wrote CTO-specific state (architecture observations, not project tasks). No permission prompts after adding Write(~/.claude/state/*) and Edit(~/.claude/state/*) to settings.json.
Permission Gotcha
The first write to ~/.claude/state/ triggered a permission prompt even with --dangerously-skip-permissions. Claude Code treats ~/.claude/ as a protected path. The fix was explicit allow rules in settings.json:
{
"permissions": {
"allow": [
"Write(~/.claude/state/*)",
"Edit(~/.claude/state/*)"
]
}
}
Both Write and Edit are needed. The agent uses Write on first creation and Edit on subsequent updates.
The Separation That Matters
The critical design decision: identity and state are separate concerns.
~/.claude/
agents/ <-- WHO the agent is (static, curated)
forge.md
cto.md
state/ <-- WHAT the agent remembers (dynamic, agent-written)
forge.md
cto.md
Mixing them in one directory would get messy fast. Ten agents means 20 files, half static identity documents and half constantly-updating state. Separate directories, same naming convention, clean separation.
What’s Not Covered
Agent-scoped state, not agent-scoped reasoning. The agent doesn’t get smarter over time. It just doesn’t forget. The Memory MCP namespace opens the door to more sophisticated patterns (semantic search over past decisions, pattern detection across sessions), but that’s future work.
The state files also aren’t conflict-managed. If two sessions with the same agent somehow overlap, the last writer wins. In practice this doesn’t happen. I run one instance of each agent at a time.
The Full Change List
For anyone building something similar, here’s what I touched:
| Component | Change |
|---|---|
~/.claude/state/ | New directory, one .md per agent |
/orient skill | Step 0: read agent state |
/session-wrap skill | Step 5: write state file, Step 5b: write to Memory MCP namespace |
/session-handoff skill | Inherits new session-wrap steps |
| 10 agent definitions | initialPrompt + Agent State system prompt section |
memory_config.yaml | 9 agent namespaces + 8 client profiles |
settings.json | Write + Edit permissions for ~/.claude/state/* |
The whole thing took about 2 hours, including the test-forge validation cycle.
What Stuck
Test with a throwaway copy. test-forge caught a model string error and a permission issue before they hit production agents. If I’d modified the real Forge agent first, I’d have been debugging in production.
Use existing lifecycle hooks. I already had orient and session-wrap skills running every session. Adding agent state was two edits, not a new system. The mechanism disappears into the existing workflow.
State files are the floor, not the ceiling. The 40-line markdown file is the minimum viable memory. Memory MCP namespaces add depth. You can build incrementally.
Separate identity from state. Agents are defined once and rarely change. State changes every session. Different directories, different update patterns, different ownership rules. Mixing them creates a mess.
Every agent writes state through the same /session-wrap skill. No inline wrap logic, no per-agent special cases. One pattern, ten agents.
Built with Claude Code, 10 specialist agents, and a stubborn refusal to keep re-explaining context to amnesiacs.