Enable OpenClaw Active Memory: Proactive Recall Guide
Ever feel like your AI’s memory is a bit too reactive? Usually, you have to prompt it to “remember this” or “search memory,” but by then, the natural flow of the conversation is already gone. Active memory fixes this by running a quick, blocking sub-agent before the main reply, giving the system a chance to pull relevant context exactly when it’s needed.
Paste This Into Your Agent
Section titled “Paste This Into Your Agent”If you want to get Active Memory running with a safe, self-contained setup, you can just drop this configuration into your agent:
{ plugins: { entries: { "active-memory": { enabled: true, config: { enabled: true, agents: ["main"], allowedChatTypes: ["direct"], modelFallbackPolicy: "default-remote", queryMode: "recent", promptStyle: "balanced", timeoutMs: 15000, maxSummaryChars: 220, persistTranscripts: false, logging: true, }, }, }, },}This setup enables the plugin for your main agent and limits it to direct-message sessions. It tries to use your current session model first but keeps a remote fallback ready just in case.
After you’ve updated the config, restart your gateway:
openclaw gatewayIf you want to check what’s happening during a chat, use this command:
/verbose onTurn active memory on
Section titled “Turn active memory on”The most reliable way to set this up involves three steps: enable the plugin, point it at one conversational agent, and use logging while you’re fine-tuning things.
Start by adding this to your openclaw.json:
{ plugins: { entries: { "active-memory": { enabled: true, config: { agents: ["main"], allowedChatTypes: ["direct"], modelFallbackPolicy: "default-remote", queryMode: "recent", promptStyle: "balanced", timeoutMs: 15000, maxSummaryChars: 220, persistTranscripts: false, logging: true, }, }, }, },}Then, restart the gateway to apply the changes:
openclaw gatewayHere is a breakdown of what these settings do:
plugins.entries.active-memory.enabled: trueswitches the plugin on.config.agents: ["main"]makes sure only themainagent uses active memory.config.allowedChatTypes: ["direct"]limits it to direct-message style sessions.- If you leave
config.modelempty, it uses the model from your current session. config.modelFallbackPolicy: "default-remote"ensures there is a backup model if needed.config.promptStyle: "balanced"sets a general-purpose prompt style.- Active memory only triggers on eligible interactive chat sessions.
How to see it
Section titled “How to see it”Active memory works by adding hidden system context for the model. You won’t see raw <active_memory_plugin>...</active_memory_plugin> tags in your client, as it keeps the technical markup out of the way.
Session toggle
Section titled “Session toggle”You can pause or resume active memory for a specific chat session without touching your config files. Just use these commands:
/active-memory status/active-memory off/active-memory onThese commands only affect the current session. They won’t change your global enabled status or agent settings.
If you need to change the setting for every session and write it to your config, use the global flag:
/active-memory status --global/active-memory off --global/active-memory on --globalThe global command updates plugins.entries.active-memory.config.enabled but keeps the plugin itself active so you can still use the commands later.
To see exactly what the memory system is thinking, turn on verbose mode:
/verbose onWhen verbose is on, OpenClaw can show you:
- A status line like
Active Memory: ok 842ms recent 34 chars. - A debug summary such as
Active Memory Debug: Lemon pepper wings with blue cheese..
These lines show you what’s being fed into the hidden context in a way that’s easy for you to read. Usually, the transcript from the memory sub-agent is deleted as soon as the run finishes.
Here is how a typical flow looks:
/verbose onwhat wings should i order?And this is the reply you should expect:
...normal assistant reply...
🧩 Active Memory: ok 842ms recent 34 chars🔎 Active Memory Debug: Lemon pepper wings with blue cheese.Next Steps
Section titled “Next Steps”When it runs
Section titled “When it runs”Active memory doesn’t just start on its own. You have to pass through two specific gates to get it working:
- Config opt-in
You must enable the plugin and ensure the current agent id is listed in
plugins.entries.active-memory.config.agents. - Strict runtime eligibility Even with the right config, active memory only triggers for interactive persistent chat sessions that meet the criteria.
Here is the logic the system follows:
plugin enabled+agent id targeted+allowed chat type+eligible interactive persistent chat session=active memory runsIf you miss any of those requirements, active memory does not run.
Session types
Section titled “Session types”You use config.allowedChatTypes to manage which kinds of conversations can use Active Memory.
The default setting is:
allowedChatTypes: ["direct"]This means Active Memory runs in direct-message sessions. It won’t run in group or channel sessions unless you specifically add them to the list.
Check out these examples for your configuration:
allowedChatTypes: ["direct"]allowedChatTypes: ["direct", "group"]allowedChatTypes: ["direct", "group", "channel"]Where it runs
Section titled “Where it runs”Active memory is designed as a conversational enrichment feature. It is not a platform-wide inference tool.
| Surface | Runs active memory? |
|---|---|
| Control UI / web chat persistent sessions | Yes, if the plugin is enabled and the agent is targeted |
| Other interactive channel sessions on the same persistent chat path | Yes, if the plugin is enabled and the agent is targeted |
| Headless one-shot runs | No |
| Heartbeat/background runs | No |
Generic internal agent-command paths | No |
| Sub-agent/internal helper execution | No |
Why use it
Section titled “Why use it”You should use active memory when:
- The session is persistent and user-facing.
- The agent has meaningful long-term memory to search.
- Continuity matters more than raw prompt determinism.
- Personalization is a key requirement for the experience.
It works well for:
- Stable preferences.
- Recurring habits.
- Long-term user context.
- Context that should surface naturally.
It is a poor fit for:
- Automation.
- Internal workers.
- One-shot API tasks.
- Places where hidden personalization would be surprising.
How it works
Section titled “How it works”When you send a message, the system doesn’t just jump to a reply. It runs a background process to see if there is anything relevant in your past interactions. Here is the runtime shape of that flow:
flowchart LR U["User Message"] --> Q["Build Memory Query"] Q --> R["Active Memory Blocking Memory Sub-Agent"] R -->|NONE or empty| M["Main Reply"] R -->|relevant summary| I["Append Hidden active_memory_plugin System Context"] I --> M["Main Reply"]This blocking memory sub-agent is focused. It only has access to two specific tools:
memory_searchmemory_get
If your connection is weak, the system is designed to stay out of your way and will return NONE to keep things moving.
Query modes
Section titled “Query modes”You can use config.queryMode to manage the “field of vision” for the blocking memory sub-agent. This setting determines how much of your current conversation history the sub-agent can see when it tries to figure out what to search for.
Prompt styles
Section titled “Prompt styles”The config.promptStyle setting is your way of telling the sub-agent how to behave. You can make it very picky or very eager to find matches.
Here are the styles you can choose from:
balanced: This is the general-purpose default when you userecentmode.strict: The most conservative option. Use this if you want to avoid context bleed.contextual: This prioritizes continuity and works best when the conversation history is important.recall-heavy: This makes the agent more likely to surface memories even if the match is a bit soft.precision-heavy: This is the opposite; it prefersNONEunless the match is very clear.preference-only: This is specifically tuned for your habits, routines, tastes, and recurring facts.
If you don’t set config.promptStyle, the system uses these default mappings:
message -> strictrecent -> balancedfull -> contextualIf you want to force a specific behavior, you can override it in your config like this:
promptStyle: "preference-only"Model fallback policy
Section titled “Model fallback policy”If you leave config.model empty, Active Memory follows a specific hierarchy to find a model to use:
explicit plugin model-> current session model-> agent primary model-> optional built-in remote fallbackYou can control that final step using config.modelFallbackPolicy. By default, it uses:
modelFallbackPolicy: "default-remote"If you prefer the plugin to simply stop and skip the recall process instead of using the built-in remote default, you can switch to this option:
modelFallbackPolicy: "resolved-only"This is useful if you want to ensure the plugin only runs when your specific preferred models are available.
Advanced escape hatches
Section titled “Advanced escape hatches”Sometimes you need to go beyond the standard setup. These options are tucked away because they aren’t part of the recommended path, but they give you granular control when you need it.
You can use config.thinking to override how much the blocking memory sub-agent “thinks”:
thinking: "medium"By default, it is set to:
thinking: "off"You shouldn’t enable this by default. Since Active Memory runs right in the reply path, any extra thinking time adds latency that your users will notice.
If you need to add specific instructions, config.promptAppend puts your text after the default Active Memory prompt but before the conversation context:
promptAppend: "Prefer stable long-term preferences over one-off events."If you want total control, config.promptOverride replaces the default prompt entirely. OpenClaw still attaches the conversation context at the end:
promptOverride: "You are a memory search agent. Return NONE or one compact user fact."I wouldn’t recommend customizing the prompt unless you are testing a specific recall contract. The default is already tuned to give the main model exactly what it needs—either NONE or a compact user-fact context.
message
Section titled “message”In this mode, only the latest user message gets sent to the agent.
Latest user message onlyYou should use this when you need the fastest possible response and want to prioritize stable preference recall. It is also the right choice if your follow-up turns don’t really need the previous conversational context.
Recommended timeout:
- Start around
3000to5000ms.
recent
Section titled “recent”This sends the latest user message along with a short tail of the conversation.
Recent conversation tail:user: ...assistant: ...user: ...
Latest user message:...This is a good choice when you want a balance between speed and conversational grounding, especially if follow-up questions often depend on the last few messages.
Recommended timeout:
- Start around
15000ms.
This sends the entire conversation to the blocking memory sub-agent.
Full conversation context:user: ...assistant: ...user: ......Use this when recall quality is more important to you than latency, or if the conversation has critical setup info buried deep in the thread.
Recommended timeout:
- You’ll need to increase this significantly compared to
messageorrecent. - Start at
15000ms or higher, depending on how long your threads get.
As a general rule, your timeout should scale with the context size:
message < recent < fullTranscript persistence
Section titled “Transcript persistence”When the Active Memory blocking memory sub-agent runs, it creates a session.jsonl transcript. Usually, this transcript is just a temporary file that lives in a temp directory and is only used for that specific run. It gets deleted the moment the run ends.
If you need to keep these transcripts for debugging or to see what’s happening under the hood, you can turn on persistence explicitly:
{ plugins: { entries: { "active-memory": { enabled: true, config: { agents: ["main"], persistTranscripts: true, transcriptDir: "active-memory", }, }, }, },}When you enable this, Active Memory saves transcripts in a separate folder within the target agent’s sessions directory. They won’t clutter your main user conversation transcripts.
The layout looks like this:
agents/<agent>/sessions/active-memory/<blocking-memory-sub-agent-session-id>.jsonlYou can use config.transcriptDir to change that subdirectory name.
Just be careful with this setting. Transcripts can pile up fast on busy sessions, especially since full query mode duplicates a lot of context. Also, remember that these files contain hidden prompt context and recalled memories.
Configuration
Section titled “Configuration”You can find all your active memory settings under this specific path:
plugins.entries.active-memoryThese are the primary fields you’ll be working with:
| Key | Type | Meaning |
|---|---|---|
enabled | boolean | Enables the plugin itself |
config.agents | string[] | Agent ids that may use active memory |
config.model | string | Optional blocking memory sub-agent model ref; when unset, active memory uses the current session model |
config.queryMode | "message" | "recent" | "full" | Controls how much conversation the blocking memory sub-agent sees |
config.promptStyle | "balanced" | "strict" | "contextual" | "recall-heavy" | "precision-heavy" | "preference-only" | Controls how eager or strict the blocking memory sub-agent is when deciding whether to return memory |
config.thinking | "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | Advanced thinking override for the blocking memory sub-agent; default off for speed |
config.promptOverride | string | Advanced full prompt replacement; not recommended for normal use |
config.promptAppend | string | Advanced extra instructions appended to the default or overridden prompt |
config.timeoutMs | number | Hard timeout for the blocking memory sub-agent |
config.maxSummaryChars | number | Maximum total characters allowed in the active-memory summary |
config.logging | boolean | Emits active memory logs while tuning |
config.persistTranscripts | boolean | Keeps blocking memory sub-agent transcripts on disk instead of deleting temp files |
config.transcriptDir | string | Relative blocking memory sub-agent transcript directory under the agent sessions folder |
If you need to fine-tune the performance, these fields are quite helpful:
| Key | Type | Meaning |
|---|---|---|
config.maxSummaryChars | number | Maximum total characters allowed in the active-memory summary |
config.recentUserTurns | number | Prior user turns to include when queryMode is recent |
config.recentAssistantTurns | number | Prior assistant turns to include when queryMode is recent |
config.recentUserChars | number | Max chars per recent user turn |
config.recentAssistantChars | number | Max chars per recent assistant turn |
config.cacheTtlMs | number | Cache reuse for repeated identical queries |
Recommended setup
Section titled “Recommended setup”I recommend starting with the recent mode. It provides a solid balance for most tasks.
{ plugins: { entries: { "active-memory": { enabled: true, config: { agents: ["main"], queryMode: "recent", promptStyle: "balanced", timeoutMs: 15000, maxSummaryChars: 220, logging: true, }, }, }, },}If you want to check how it’s behaving in real-time while you tune it, just use /verbose on in the session. You don’t need to look for a separate debug command.
Once you’re comfortable, you can adjust the mode based on your needs:
- Switch to
messageif you want lower latency. - Switch to
fullif you decide the extra context is worth a slower blocking memory sub-agent.
Debugging
Section titled “Debugging”If active memory isn’t showing up where you expect, you can try these steps to get things back on track:
- Confirm the plugin is enabled under
plugins.entries.active-memory.enabled. - Confirm the current agent id is listed in
config.agents. - Confirm you are testing through an interactive persistent chat session.
- Turn on
config.logging: trueand watch the gateway logs. - Verify memory search itself works with
openclaw memory status --deep.
If you find that memory hits are getting a bit noisy, you should tighten maxSummaryChars.
If active memory feels too slow, you have a few options to speed it up:
- lower
queryMode - lower
timeoutMs - reduce recent turn counts
- reduce per-turn char caps
Related pages
Section titled “Related pages”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.