All posts
2026-03-2810 min

Setting Up OpenClaw Native Memory: Agents That Actually Remember

MemoryMEMORY.mdPersistenceSetupOpenClaw

The Problem With Stateless Agents

A tweet from this morning nails it:

> *"OpenClaw with native memory is a different experience. When memory sits inside the context flow, agents can actually carry forward work instead of starting over each time."*

470 impressions, 4 likes, 3 bookmarks in under 10 minutes. That hit a nerve.

The reason: most OpenClaw installations are still running stateless. Every session starts from zero. The agent doesn't know what was discussed yesterday, forgets preferences after a restart, and every new conversation is a blank slate. That's not the state OpenClaw was built for — it's the state most installations get stuck in because the memory system is never clearly documented anywhere.

This guide closes that gap.

---

How OpenClaw Memory Works (The Architecture)

OpenClaw's memory system is file-based. That sounds primitive — but it's a feature, not a bug. Files are:

  • versionable (Git, backup)
  • inspectable (you know exactly what your agent knows)
  • editable (no mysterious embedding update required)
  • portable (deploy to a new server, memory comes with you)
  • The structure is simple:

    ```

    ~/.openclaw/workspace/

    ├── MEMORY.md # Long-term memory — curated, dense

    ├── SOUL.md # Identity and rules

    ├── USER.md # Who's using the agent

    ├── AGENTS.md # Workspace rules (loaded at every start)

    ├── HEARTBEAT.md # Active tasks / reminders

    └── memory/

    ├── 2026-03-28.md # Daily notes (created daily)

    ├── 2026-03-27.md

    └── heartbeat-state.json

    ```

    These files are read, written, and maintained by the agent — not by you. You set up the structure, the agent fills it in.

    ---

    Step 1: Create the Foundation

    If not already in place:

    ```bash

    mkdir -p ~/.openclaw/workspace/memory

    # Create MEMORY.md

    cat > ~/.openclaw/workspace/MEMORY.md << 'EOF'

    # Long-Term Memory

    _This file is maintained by the agent. Do not overwrite unless intentional._

    Key Facts

  • (agent fills this in over time)
  • Decisions

  • (agent fills this in over time)
  • Preferences

  • (agent fills this in over time)
  • EOF

    # Create today's daily note

    touch ~/.openclaw/workspace/memory/$(date +%Y-%m-%d).md

    ```

    That's it for structure. Now the critical part: telling the agent how to use it.

    ---

    Step 2: AGENTS.md — The Rules of the Game

    This is the most common mistake in OpenClaw memory setups: MEMORY.md exists, but the agent doesn't know when to write to it.

    In `AGENTS.md` (or your main instruction to the agent) you need to explicitly define:

    ```markdown

    Memory Rules

    Daily Notes: memory/YYYY-MM-DD.md

  • Write what happened in the session here
  • Decisions, completed tasks, open items
  • Format: short bullets, not prose
  • MEMORY.md — Long-Term Memory

  • Read only in main sessions (not in Discord/group chats)
  • Curate important insights here
  • Remove outdated entries regularly
  • Target: under 1,000 words, high-density information
  • Memory Behavior

  • When someone says "remember X" → immediately write to memory/YYYY-MM-DD.md
  • No "mental notes" — files survive session restarts, thoughts don't
  • Every session: read today's and yesterday's daily note
  • ```

    Without these rules the agent doesn't know whether it should write memory or not. With them it starts automatically logging everything that matters.

    ---

    Step 3: The Session Flow — How Memory Lives in Context

    OpenClaw loads workspace files at session start. For memory to work, the agent needs to know what to load and when.

    The correct priority order:

    ```

    Session Start:

    1. Read SOUL.md → Who am I?

    2. Read USER.md → Who am I helping?

    3. memory/today.md → What happened today?

    4. memory/yesterday.md → What was relevant yesterday?

    5. MEMORY.md → Only in main sessions (not in group chats/Discord)

    During the Session:

    - Call memory_search() for specific recall

    - Update memory/today.md with important events

    End of Session / Significant Moment:

    - Update MEMORY.md with curated long-term insights

    ```

    The key: MEMORY.md is not loaded on every turn — only at session start, in main sessions. This prevents context bloat.

    ---

    Step 4: memory_search — The Underrated Superpower

    The memory system would be half as good without `memory_search`. Instead of loading all files into context, the agent searches semantically:

    ```

    # Instead of: read all daily files (100,000+ tokens)

    # Do this: fetch only relevant snippets (~500 tokens)

    memory_search("what did we decide about deployment last month?")

    → Returns top 3-5 relevant passages, with file path and line numbers

    ```

    That's the difference between an agent that knows everything and an agent that knows where to look. The latter scales — the former doesn't.

    Tip: when writing to MEMORY.md or daily notes, use clear, searchable phrasing:

    ```markdown

    # Good (easy to find):

    Decision 2026-03-15: We're using Convex instead of Supabase for all new projects.

    # Bad (not findable):

    We sorted that out today.

    ```

    ---

    Step 5: HEARTBEAT.md — Continuity Between Sessions

    HEARTBEAT.md is the bridge between sessions. It's not for long-term memory — that's MEMORY.md. It's for what's happening right now:

    ```markdown

    # HEARTBEAT.md — Active Context

    Running Projects

  • [ ] Finish blog deployment pipeline (Sam, ~80% done)
  • [ ] Check Vercel domain config (waiting on DNS propagation)
  • [ ] Review ClickUp task TC-47
  • To Do Today

  • Send email to Tim about Q2 budget
  • Have Peter review PR #412
  • Open Questions

  • Which embedding model for memory_search in production?
  • ```

    The agent reads HEARTBEAT.md on every heartbeat poll (default: every 30 minutes). This way running tasks remain visible across restarts — without you having to re-explain them.

    Keep HEARTBEAT.md small. When a task is done, remove it. If something is important enough for long-term memory, move it to MEMORY.md.

    ---

    Step 6: heartbeat-state.json — What Was Checked When

    So the agent doesn't check everything on every heartbeat (email, calendar, weather — that's API waste), it tracks in `memory/heartbeat-state.json` what was last checked when:

    ```json

    {

    "lastChecks": {

    "email": 1743124800,

    "calendar": 1743110400,

    "weather": null,

    "twitter": 1743118200

    },

    "lastActive": 1743124900

    }

    ```

    With this file the agent decides for itself: "Email was checked 47 minutes ago, that's fine. Calendar was checked 4 hours ago, I should revisit that." No redundant API calls, no guessing.

    ---

    The Full Picture: Complete Memory Lifecycle

    To make it concrete — here's what a day with the full memory setup looks like:

    8:30 AM — First Session:

  • Agent loads SOUL.md, USER.md, memory/2026-03-28.md (empty), memory/2026-03-27.md (yesterday)
  • Reads MEMORY.md → knows who you are, what projects are running, what matters
  • Reads HEARTBEAT.md → sees open tasks from yesterday
  • 10:00 AM — Task Completed:

  • Writes to memory/2026-03-28.md: "10:05 — Blog post deployed, Vercel prod live"
  • Removes task from HEARTBEAT.md
  • 2:00 PM — You Ask About a Decision from Last Week:

  • memory_search("deployment strategy decision") → returns the relevant passage
  • No confusion, no hallucination
  • 6:00 PM — End of Session:

  • Agent distills key insights into MEMORY.md
  • Updates heartbeat-state.json
  • Next Morning:

  • Agent reads yesterday's notes → knows exactly where things left off
  • No more "what were we discussing again?"
  • ---

    Common Mistakes and How to Avoid Them

    Mistake 1: Letting MEMORY.md grow unchecked

    MEMORY.md is long-term memory, not a diary. When it grows past 1,500 words, quality degrades. Let the agent clean it up regularly — or do it yourself with a monthly cron job.

    Mistake 2: Loading memory in Discord/group chats

    MEMORY.md contains personal information. It must not be loaded in group chats, Discord channels, or other shared contexts. Only in your direct main session. Make sure this rule is explicit in AGENTS.md.

    Mistake 3: "Mental notes" instead of file updates

    If you say "remember that we're upgrading Stripe webhooks next week" and the agent says "noted" — but writes nothing — that's a mental note. It won't survive a restart. Test it: tell the agent something specific, restart it, ask about it. If it doesn't know, it didn't write it down.

    Mistake 4: Not using memory_search

    Many setups blindly load MEMORY.md + all daily notes into context. That creates context bloat. Use memory_search instead — it gives you more precise answers with a fraction of the tokens.

    ---

    Summary

    OpenClaw with native memory doesn't need an external database, no vector store, no embeddings pipeline. It needs:

    1. The right files (MEMORY.md, memory/YYYY-MM-DD.md, HEARTBEAT.md)

    2. Clear rules in AGENTS.md for when to read and write what

    3. Discipline in writing (searchable phrasing, remove stale entries)

    4. memory_search instead of blind loading

    The result is an agent that actually builds a working relationship with you — one that remembers who you are, what's currently running, and what was decided last week. This isn't a feature add-on. It's the difference between a tool and a coworker.

    The complete configuration — all files, all rules, the full 6-agent setup — is documented in the OpenClaw Setup Playbook.

    Also fully available in German. 🇩🇪

    Want to learn more?

    Our playbook contains 18 detailed chapters — available in English and German.

    Get the Playbook