Why your agent forgets everything between sessions (and how to fix it)


I spent three weeks telling my OpenClaw agent the same thing: “I use pnpm, not npm.” Every single session, it defaulted back to npm. Install commands, lockfile references, script suggestions. All npm. Every time.

The agent wasn’t broken. It was working exactly as designed. And that’s the problem.

The way most OpenClaw agents handle memory

If you’re running an OpenClaw agent with the default setup, your memory situation probably looks like this:

workspace/
  MEMORY.md          # grows forever
  memory/
    2026-02-15.md    # daily log
    2026-02-16.md    # daily log
    2026-02-17.md    # daily log
    ...

Your agent reads MEMORY.md at session start, maybe scans recent daily files, and uses whatever fits in context. Works fine for the first month.

Then MEMORY.md hits 30KB. Then 50KB. Then you notice your agent is slower, more expensive, and somehow still forgetting things.

The math nobody does

Let’s run the numbers on a real MEMORY.md file. Mine hit 52KB after about six weeks of active use.

52KB of text is roughly 13,000 tokens. At current API pricing, loading that into context costs about $0.002 per session. Doesn’t sound like much until you multiply it out.

10 sessions per day. 30 days. That’s 300 sessions. 3.9 million tokens just on memory loading. Around $0.60 per month for a single agent. Scale to five agents running across different projects and you’re burning $3 per month on context that’s mostly irrelevant to whatever you’re doing right now.

But cost isn’t even the real problem. The real problem is context window pollution.

When your agent loads 13,000 tokens of MEMORY.md, that’s 13,000 tokens less for actual work. On a model with a 128K context window, that might seem trivial. In practice, it’s not. Those 13,000 tokens include your coffee preference alongside your deployment conventions alongside a note about a bug you fixed in January. The model has to process all of it, weigh it against the current prompt, and figure out what matters.

The result: your agent gets confused. It surfaces irrelevant context. It mixes up project-specific preferences because everything lives in one flat file.

The daily log problem is worse

Daily log files seem like a good idea. Date-stamped notes, easy to organize. But they create their own mess.

Your agent reads today’s log and maybe yesterday’s. What about the correction you made last Tuesday? The preference you stated two weeks ago? Those are buried in files the agent never looks at.

$ ls memory/ | wc -l
43

43 daily files. My agent reads 2 of them. The other 41 contain context that might be relevant but is effectively lost. It’s like taking notes in a notebook and only ever reading the last two pages.

Some agents try to be clever and scan all recent files. Now you’re back to the MEMORY.md problem but spread across multiple files. More tokens loaded, same irrelevance problem, with the added cost of file I/O.

Why “just summarize it” doesn’t work

The obvious fix is periodic summarization. Compress old memories into shorter summaries. Several OpenClaw setups do this automatically.

The problem: summarization is lossy. When you compress “user corrected agent: always use strict TypeScript config with noUncheckedIndexedAccess enabled” into “user prefers strict TypeScript,” you’ve lost the specific flag. Next time the agent sets up tsconfig.json, it enables strict mode but misses noUncheckedIndexedAccess. Close, but wrong.

Compression works for general context. It destroys specifics. And specifics are usually what you need. The timezone. The exact CLI flag. The naming convention for database migrations. These details get smoothed away by summarization.

What actually fixes this

The fix is selective recall. Instead of loading everything and hoping the model sorts it out, you query for what’s relevant to the current task and load only that.

I switched my agent to MemoClaw two months ago. Here’s what the setup looks like:

npm install -g memoclaw

First, I migrated my existing MEMORY.md:

memoclaw migrate --file MEMORY.md

This parsed my 52KB file into individual memories, generated embeddings for each one, and stored them. 214 separate memories from one monolithic file.

Now, instead of loading everything at session start, my agent does this:

memoclaw recall "current task context" --limit 5

If I’m working on TypeScript configuration, it returns my TypeScript preferences. If I’m doing deployment work, it returns deployment conventions. Not everything. Just what matches.

The before and after

Before, session start:

Loading MEMORY.md... 13,247 tokens
Loading memory/2026-02-28.md... 1,832 tokens  
Loading memory/2026-02-27.md... 2,104 tokens
Total memory context: 17,183 tokens

After:

Recalling context for "set up new API endpoint"... 
Retrieved 4 memories, 387 tokens

From 17,000 tokens to 400. And the 400 tokens are actually relevant to what I’m doing.

Storing memories that matter

The other half is being intentional about what gets stored. My old MEMORY.md was a dumping ground. Session notes, random observations, preferences, corrections, project status updates. All mixed together with no structure.

Now I store memories with metadata that helps recall work better:

memoclaw store "Always use pnpm, never npm. User corrected this explicitly." \
  --importance 0.9 \
  --tags "preferences,tooling"

The importance score means this surfaces ahead of casual observations. The tags let me filter recalls to specific categories when I need to.

For corrections, I always store at high importance. If someone takes the time to correct their agent, that correction matters. It should surface reliably, every time the topic comes up.

memoclaw store "Deploy to Railway, not Vercel. Project uses Railway auto-deploys from main branch." \
  --importance 0.85 \
  --tags "deployment,infrastructure"

Namespaces keep projects separate

One thing that made a huge difference: scoping memory per project.

memoclaw store "Uses PostgreSQL with Drizzle ORM" --namespace api-project
memoclaw store "Uses SQLite with Prisma" --namespace cli-tool

My old MEMORY.md had notes from every project in one file. The agent would suggest Prisma patterns in a Drizzle project because both facts existed in the same flat document. Namespaces eliminated that entirely.

When I start a session for the API project:

memoclaw recall "database setup" --namespace api-project --limit 3

Only memories from that namespace come back. No cross-contamination.

The maintenance side

Memories accumulate. After two months, I have over 400 stored memories. Some are outdated. We switched from Express to Hono three weeks ago, but the Express memories still exist.

I run periodic cleanup. MemoClaw has a delete endpoint for removing stale memories and a consolidate endpoint for merging related ones:

memoclaw delete --id <old-express-memory-id>

For related memories that overlap, consolidation merges them into a single cleaner memory. Five scattered notes about TypeScript configuration become one comprehensive memory.

I do this roughly every two weeks. Takes about ten minutes. Compare that to editing a 52KB MEMORY.md file where you have to read through everything to find what’s outdated.

What I’d tell someone starting today

If you’re setting up a new OpenClaw agent, don’t wait for MEMORY.md to become a problem before fixing it. Start with semantic memory from day one.

The migration path from MEMORY.md works fine. The memoclaw migrate command handles existing files. But starting fresh is even simpler because you skip the “parse a giant markdown file” step entirely.

Store corrections at high importance. Use namespaces per project. Keep memories specific and actionable. Let semantic search do the work of finding what’s relevant instead of loading everything and hoping for the best.

Your agent doesn’t forget because it’s bad at remembering. It forgets because nobody gave it a real memory system. The file-based approach was a reasonable starting point. It’s not where you should stay.