Skip to main content
This is the lifecycle. Other pages describe one piece of it. They do not define a second lifecycle.

Flow

  1. A completed turn is captured once into short-term messages. You can turn that off. On OpenClaw, captureTurns defaults to on, and MEMORY_CRYSTAL_CAPTURE_TURNS overrides it.
  2. Distillation reads eligible turns and writes durable memories.
  3. Recall returns a bounded set. It does not always run a vector lookup. An identifier shortcut or a missing embedding provider skips vector work and still returns lexical matches. The response says when retrieval was degraded or took the shortcut.
  4. Recent unextracted messages can contribute lexical evidence, inside a bounded message lane.
  5. Ranking and scope filters pick the result set.
  6. Knowledge bases, assets, and research are queried only through their own tools.
Tool-mode recall is the default, so an ordinary turn does not pay a read on its own. Context injection uses the same bounded path and stays off by default. Set MEMORY_CRYSTAL_INJECT_RECALL=1 or true, or set injectRecall: true in config. A non-empty environment variable takes precedence over config. Grok cannot inject.

What is kept

On the hosted service and by default when self-hosting, raw messages and raw sensory content stay until you delete them. Self-hosters who set CRYSTAL_RETENTION_READY=1 enable age-based expiry jobs; retention then follows the tier’s expiry policy.

Distillation

Distillation is its own job. It is not Forgetting and it is not the stale archive.

Forgetting

Forgetting archives memories only when the account is over its non-KB allowance.
  • It counts active memories that are not knowledge-base chunks.
  • Unlimited has no allowance, so Forgetting archives nothing for that entitlement.
  • It protects memories from the last 24 hours.
  • It archives the overage, lowest memory value first. It does not delete the row.
  • Enforcement is off unless CRYSTAL_FORGETTING_ENFORCEMENT=1. A dry run reports what would be archived and writes nothing.

Stale archive

The stale archive is archive-only and restorable. It does not delete memories. CRYSTAL_STALE_ARCHIVE controls it: The check is scheduled at 05:30 UTC. It only acts when the mode is dry_run or on. On the hosted service the stale archive is being enabled in October 2026 after a trial. A memory is eligible when all of these hold:
  • active, not in a knowledge base, not sensory, and auto-extracted
  • not a rule, a decision, or a memory about a person
  • strength below 0.85
  • not core, and no core tag (any case)
  • created, last accessed, and last recalled (when that timestamp exists) at least 90 days ago
These are automatically extracted memories that have been unused and not recalled for 90 days. Older conversation memories also qualify when they have a recorded extraction or links to their source messages. Confidence is not part of the rule; core memories and memories with strength of 0.85 or higher are protected. Archived rows leave recall. They are not purged by the archived-memory purge. Checkpoints keep their own copies. Restore exists for these rows. It clears the archive flag, resets the access clock, and schedules embedding with the account’s OpenRouter key. Without that key, the restored memory stays available to lexical recall until an embedding succeeds. There is no public MCP tool that restores stale-archived memories. Restore is an operator action on the account.

Choose the right read tool

Use crystal_recall for a decision or fact distilled from past conversations:
Read the returned memories and message matches. If a memory is flagged truncated, use crystal_get_memory for its full text. Use crystal_recent to catch up on the latest conversation, without a search query:
Use crystal_search_messages when you need original wording rather than a distilled memory:
Follow pagination.nextOffset while pagination.hasMore is true before concluding the window has no more matches. Keep the same channel or session scope across requests when you need a particular conversation. See Recall, Recent messages, and Search.

OpenClaw loop

  1. The user sends a message and the model replies.
  2. The plugin records the completed turn once, unless capture is disabled.
  3. The agent calls Memory Crystal tools when prior context matters.
  4. If you set MEMORY_CRYSTAL_INJECT_RECALL=true, the plugin may prepend bounded context before the model call.