Core Memories: Pinning the Facts Your OpenClaw Agent Must Never Lose


Core Memories: Pinning the Facts Your OpenClaw Agent Must Never Lose

Some things your agent should always know. Your name. Your timezone. That one time you told it to never use tabs for indentation and it keeps forgetting.

MemoClaw has a feature for exactly this: core memories. Pin a memory as “core” and it becomes exempt from decay, always surfaces during recall, and persists until you explicitly unpin it.

This guide covers what core memories are, when to use them, and how to set them up for your OpenClaw agent.

How Memory Decay Works (And Why Pinning Matters)

MemoClaw doesn’t treat all memories equally. Each memory has a memory_typecorrection, preference, decision, project, observation, or general — and each type decays at a different rate.

An observation (“user mentioned they had lunch at 1pm”) decays fast. A correction (“user’s last name is spelled García, not Garcia”) decays slowly. This is by design: recent observations matter less over time, but corrections should stick around.

But some facts should never decay at all. That’s what pinning does. A pinned (core) memory is exempt from type-based decay. It stays at full relevance forever, regardless of its type.

Core vs. Immutable vs. Regular

MemoClaw has three distinct memory behaviors. They’re often confused, so here’s the breakdown:

Regular memories — The default. They have a type, an importance score, and they decay over time based on their type. Recall ranks them by semantic similarity weighted by current importance.

Immutable memories — Locked from modification. You can’t update or delete an immutable memory. It still decays normally though. Use these for audit trails or facts that shouldn’t be tampered with.

Core (pinned) memories — Exempt from decay. They always surface during recall, regardless of how old they are or how relevant they seem to the query. They can still be updated or unpinned. Use these for facts that should always be available.

You can combine them: a memory can be both pinned and immutable (a permanent fact that can’t be changed). But that’s rare — most core memories should remain editable in case the underlying fact changes.

When to Pin a Memory

Good candidates for core memories:

  • User identity: name, pronouns, timezone, role
  • Hard preferences: “always use TypeScript”, “never auto-commit to main”
  • Critical corrections: “the API endpoint changed from /v1 to /v2”
  • Project fundamentals: “this project uses Postgres 15 on Railway”
  • Behavioral rules: “ask before sending emails”, “use British English”

Bad candidates:

  • Session summaries (they’re contextual, not permanent)
  • Temporary project states (“currently working on auth flow”)
  • Observations (“user seemed frustrated today”)
  • Anything that changes frequently

A good rule: if you’d put it in the first line of a system prompt, it’s probably a core memory.

Creating Core Memories via CLI

There are two ways to create a core memory: store and pin in one step, or pin an existing memory.

Store + Pin in One Step

memoclaw store "User's name is Ana. Pronouns: she/her. Timezone: UTC-3." \
  --importance 1.0 \
  --tags identity \
  --type preference \
  --pinned

The --pinned flag marks it as a core memory at creation time. This costs $0.005 (the normal store price). Pinning itself is free.

Pin an Existing Memory

If you already have a memory stored and want to promote it to core:

# Find the memory ID first
memoclaw search "user's name" --limit 5

Output:

ID: 550e8400-e29b-41d4-a716-446655440000
Content: User's name is Ana
Importance: 0.8
Type: preference

Now pin it:

memoclaw update 550e8400-e29b-41d4-a716-446655440000 --pinned

Or via the API directly:

curl -X POST https://api.memoclaw.com/v1/memories/core \
  -H "Content-Type: application/json" \
  -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..." \
  -d '{"memory_id": "550e8400-e29b-41d4-a716-446655440000"}'

Response:

{
  "pinned": true,
  "id": "550e8400-e29b-41d4-a716-446655440000"
}

Listing Core Memories

See everything you’ve pinned:

memoclaw list --tags core

Or via the API (this endpoint is free):

curl https://api.memoclaw.com/v1/memories/core \
  -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..."
{
  "memories": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "User's name is Ana. Pronouns: she/her. Timezone: UTC-3.",
      "importance": 1.0,
      "pinned": true,
      "memory_type": "preference",
      "tags": ["identity"],
      "created_at": "2026-02-01T12:00:00Z"
    }
  ],
  "total": 1
}

You can also filter by namespace if you’re running multiple agents:

curl "https://api.memoclaw.com/v1/memories/core?namespace=agent-frontend" \
  -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..."

Unpinning a Core Memory

When a fact changes or is no longer critical, unpin it:

memoclaw update 550e8400-e29b-41d4-a716-446655440000 --no-pinned

Or via the API:

curl -X DELETE https://api.memoclaw.com/v1/memories/core/550e8400-e29b-41d4-a716-446655440000 \
  -H "x-wallet-auth: 0xYourWallet:1699900000:0xSignature..."
{
  "unpinned": true,
  "id": "550e8400-e29b-41d4-a716-446655440000"
}

The memory isn’t deleted. It just resumes normal type-based decay. If it’s still relevant, it’ll still show up in recall results — just not with the guaranteed “always surface” treatment.

Seeding Your Agent with Core Memories

When you first set up MemoClaw for an agent, seed it with the facts that matter most. Here’s a practical pattern using batch storage:

memoclaw store-batch \
  '{"content": "User name: Ana. Pronouns: she/her.", "importance": 1.0, "memory_type": "preference", "pinned": true}' \
  '{"content": "Timezone: UTC-3 (São Paulo). Availability: weekdays 10-18.", "importance": 0.9, "memory_type": "preference", "pinned": true}' \
  '{"content": "Primary stack: TypeScript, PostgreSQL, Railway. Always use strict TypeScript.", "importance": 0.9, "memory_type": "project", "pinned": true}' \
  '{"content": "Communication style: direct, no filler words, no corporate speak.", "importance": 0.8, "memory_type": "preference", "pinned": true}' \
  '{"content": "Never auto-commit to main. Always create a PR.", "importance": 1.0, "memory_type": "correction", "pinned": true}'

This stores 5 core memories in one batch request for $0.04. Individually, that would be $0.025 (5 × $0.005) — so batch is actually more expensive at small volumes, but the convenience of a single request matters more for automation scripts.

How Core Memories Interact with memoclaw-hooks

If you’re using memoclaw-hooks (and you should be — see Setting Up memoclaw-hooks), core memories get special treatment:

  1. Session start: The hook recalls memories relevant to the user’s first message. Core memories always appear in these results, even if they’re not semantically close to the query.
  2. Gateway startup: The hook recalls recent memories for continuity. Core memories are included alongside the 3 most recent.
  3. Consolidation: Core memories are never merged or deduplicated during consolidation. They’re protected.

This means your agent always starts every session knowing the user’s name, preferences, and critical rules. No more “I apologize, could you remind me of your name?”

How Many Core Memories Is Too Many?

There’s no hard limit, but there’s a practical one: context window.

Every core memory that surfaces during recall takes up tokens in your agent’s context. If you pin 50 memories averaging 100 tokens each, that’s 5,000 tokens consumed before the conversation even starts.

Guidelines:

  • 5–15 core memories is a sweet spot for most setups
  • Keep each core memory concise (under 200 characters if possible)
  • Review your core memories monthly — unpin anything that’s no longer critical
  • Use the suggested endpoint to find stale memories that might need unpinning:
memoclaw suggested --category stale --limit 10

Pricing Recap

The good news: core memory operations are free.

OperationPrice
List core memories (GET /v1/memories/core)FREE
Pin a memory (POST /v1/memories/core)FREE
Unpin a memory (DELETE /v1/memories/core/:id)FREE
Store with --pinned$0.005 (normal store cost)

You only pay for the initial store. Managing pins costs nothing.

Practical Example: Setting Up a New Project Agent

Here’s a complete workflow for giving a project-specific OpenClaw agent its core memories:

# 1. Create a namespace for the project
export MEMOCLAW_NAMESPACE=project-acme

# 2. Seed core memories
memoclaw store "Project Acme: e-commerce platform built with Next.js 14, tRPC, Drizzle ORM, PostgreSQL 16." \
  --importance 1.0 --type project --pinned --namespace project-acme

memoclaw store "Deployment: Vercel (frontend), Railway (API), Neon (database). CI via GitHub Actions." \
  --importance 0.9 --type project --pinned --namespace project-acme

memoclaw store "Code style: Biome for formatting, strict TypeScript, no 'any' types. PR required for all changes." \
  --importance 1.0 --type correction --pinned --namespace project-acme

memoclaw store "Team: Ana (lead), Carlos (backend), Priya (frontend). Standup at 10am UTC-3." \
  --importance 0.8 --type preference --pinned --namespace project-acme

# 3. Verify
memoclaw list --namespace project-acme

Now any agent using the project-acme namespace will always know the stack, deployment setup, code standards, and team structure.

What’s Next