Active Memory: Deep Recall for Conversational Sessions
Learn how Active Memory escalates to deep recall when deterministic memory fails, enabling cross-session and temporal queries. Ideal for developers configuring trusted agents.
Read this when
- You want to understand what active memory is for
- You want to turn active memory on for a conversational agent
- You want to tune active memory behavior without enabling it everywhere
Active Memory serves as the deep-recall pathway for conversational sessions that qualify for it. In the default escalate mode, the blocking recall sub-agent is invoked only when a query concerns past events and the deterministic memory lane fails to produce a strong trusted trigger match. This design keeps routine responses quick while still offering a more thorough search route for earlier decisions, discussions, and questions involving time spans or multiple hops.
Flat retrieval excels at direct fact matches but struggles with temporal and cross-session queries. LongMemEval (arXiv:2410.10813) quantifies this shortfall, whereas the PrefEval benchmark underscores how much preference-related reminders matter. By default, escalation spends the blocking model call exactly where those harder recall patterns exist.
Remember across conversations
For a personal or fully trusted agent, you can enable bounded recall across its other private conversations through a single per-agent setting:
{
agents: {
entries: {
personal: {
memory: {
search: {
rememberAcrossConversations: true,
},
},
},
},
},
}
This setting is on by default for personal installs: global session.dmScope must be either unset or "main", and no binding may override session.dmScope. Any configured DM isolation switches it off by default. An explicit true or false takes precedence in all cases. When turned on, OpenClaw indexes that agent's session transcripts and performs an Active Memory retrieval pass before eligible private replies. That pass can pull relevant transcript excerpts from the same agent's other private conversations, while excluding the conversation currently being answered.
The privacy boundary stays fixed:
- private direct and persistent explicit UI conversations can recall one another
- groups and channels are neither recall sources nor recall destinations
- another agent's transcripts are never eligible
- unknown or archived transcripts without enough conversation metadata are rejected
This does not merge transcripts, change session keys or delivery routes, widen tools.sessions.visibility, or grant broader sessions_* tool access. Shared workspace memory (MEMORY.md and memory/*.md) keeps its existing behavior.
Active Memory must remain enabled. Retrieval adds a bounded blocking step to eligible replies; timeout, unavailable search, and empty results all continue the reply without recalled transcript context. OpenClaw's built-in memory provider supports this protected transcript-recall path. Other memory providers keep their own recall behavior but do not automatically receive private transcript authorization. openclaw doctor reports an unsupported provider or missing memory_search tool.
Advanced Active Memory quick start
Paste into openclaw.json for an advanced safe default: plugin on, scoped to main, direct-message sessions only, model inherited from the session.
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
enabled: true,
mode: "escalate",
agents: ["main"],
allowedChatTypes: ["direct"],
modelFallback: "google/gemini-3-flash",
queryMode: "recent",
promptStyle: "balanced",
timeoutMs: 15000,
maxSummaryChars: 220,
persistTranscripts: false,
logging: true,
},
},
},
},
}
plugins.entries.* (including active-memory.config) is in the no-restart config category: the Gateway reloads the plugin runtime automatically and no manual restart is needed. If you want to force a full restart anyway, run:
openclaw gateway restart
To inspect it live in a conversation:
/verbose on
/trace on
What the key fields do:
plugins.entries.active-memory.enabled: trueturns the plugin onconfig.mode: "escalate"runs deep recall only for recall intent without a strong deterministic hitconfig.agents: ["main"]opts only themainagent inconfig.allowedChatTypes: ["direct"]scopes it to direct-message sessions (opt in groups/channels explicitly)config.model(optional) pins a dedicated recall model; unset inherits the current session modelconfig.modelFallbackis used only when no explicit or inherited model resolvesconfig.fastModeoptionally overrides fast mode for recall without changing the main agentconfig.promptStyle: "balanced"is the default forrecentmode- active memory still runs only for eligible interactive persistent chat sessions (see When it runs)
How it works
flowchart LR
U["User Message"] --> D["Deterministic Trigger Recall"]
D -->|strong trusted match| I["Inject Bounded Hidden Context"]
D -->|weak or empty| H["Check Recall Intent"]
H -->|no| M["Main Reply"]
H -->|yes| R["Active Memory Deep Recall Sub-Agent"]
R -->|NONE| M
R -->|relevant summary| I
I --> M
The deep-recall sub-agent can call only the configured memory recall tools (see Memory tools). If the connection between the query and available memory is weak, it returns NONE and the main reply proceeds without extra context.
Active memory is a conversational enrichment feature, not a platform-wide inference feature:
| Surface | Runs active memory? |
|---|---|
| Control UI / web chat persistent sessions | Yes, when either activation path targets the agent |
| Other interactive channel sessions on the same persistent chat path | Yes, when either activation path allows the conversation |
| Headless one-shot runs | No |
| Heartbeat/background runs | No |
Generic internal agent-command paths | No |
| Sub-agent/internal helper execution | No |
Use it when the session is persistent and user-facing, the agent has meaningful long-term memory to search, and continuity/personalization matter more than raw prompt determinism: stable preferences, recurring habits, long-term context that should surface naturally. It is a poor fit for automation, internal workers, one-shot API tasks, or anywhere hidden personalization would be surprising.
When it runs
Active Memory has two targeting paths for the deep-recall lane:
- Remember across conversations automatically targets agents whose effective
memory.search.rememberAcrossConversationssetting is enabled, but only for private direct or persistent explicit UI conversations. - Advanced Active Memory targets agent IDs listed in
plugins.entries.active-memory.config.agentsand applies the plugin's chat type and chat ID controls.
Both paths require the plugin to be enabled and an eligible interactive persistent conversation. A session-scoped /active-memory off pauses both paths for that conversation. If any condition fails, active memory does not run for that turn, and the main reply is unaffected.
config.mode controls when a targeted turn starts the blocking sub-agent:
| Mode | Behavior |
|---|---|
escalate | Default. Run only for recall intent when lane 1 has no strong hit. |
always | Preserve the previous behavior and run on every eligible targeted turn. |
off | Disable deep recall without unloading the plugin. |
The deterministic trusted-trigger lane remains available in off mode. rememberAcrossConversations is unchanged: it still controls whether deep recall may search other private conversations.
Session types
config.allowedChatTypes controls which kinds of conversations may run the advanced Active Memory path. It cannot widen Remember across conversations: that product setting remains private-only even when advanced Active Memory is allowed in groups or channels. Default:
allowedChatTypes: ["direct"];
Valid values: direct, group, channel, explicit (portal-style sessions with an opaque session id, for example agent:main:explicit:portal-123). Direct-message sessions run by default; group, channel, and explicit sessions need to be opted in:
allowedChatTypes: ["direct", "group"];
allowedChatTypes: ["direct", "group", "channel"];
For narrower rollout inside an allowed chat type, add
config.allowedChatIds and config.deniedChatIds:
allowedChatIdsis an allowlist of resolved conversation ids. When non-empty, active memory only runs for sessions whose conversation id is in the list, this narrows every allowed chat type at once, including direct messages. To keep all direct messages while narrowing only groups, add the direct peer ids toallowedChatIdstoo, or keepallowedChatTypesscoped to the group/channel rollout you are testing.deniedChatIdsis a denylist that always wins overallowedChatTypesandallowedChatIds.
Ids come from the persistent channel session key (for example Feishu
chat_id/open_id, Telegram chat id, Slack channel id). Matching is
case-insensitive. If allowedChatIds is non-empty and OpenClaw cannot
resolve a conversation id for the session, active memory skips the turn
instead of guessing.
allowedChatTypes: ["direct", "group"],
allowedChatIds: ["ou_operator_open_id", "oc_small_ops_group"],
deniedChatIds: ["oc_large_public_group"]
Session toggle
Pause or resume active memory for the current chat session without editing config:
/active-memory status
/active-memory off
/active-memory on
This only affects the current session; it does not change
plugins.entries.active-memory.config.enabled, an agent's
memory.search.rememberAcrossConversations setting, or other global
configuration.
To pause/resume for all sessions instead, use the global form (requires
owner or operator.admin):
/active-memory status --global
/active-memory off --global
/active-memory on --global
The global form writes plugins.entries.active-memory.config.enabled but
leaves plugins.entries.active-memory.enabled on, so the command stays
available to turn active memory back on later.
How to see it
By default, active memory injects a hidden untrusted prompt prefix that is not shown in the normal reply. Turn on the session toggles that match the output you want:
/verbose on
/trace on
With those on, OpenClaw appends diagnostic lines after the normal reply (as a follow-up, so channel clients do not flash a separate pre-reply bubble):
/verbose onadds a status line:🧩 Active Memory: status=ok elapsed=842ms query=recent summary=34 chars/trace onadds a debug summary:🔎 Active Memory Debug: Lemon pepper wings with blue cheese.
Example flow:
/verbose on
/trace on
what wings should i order?
...normal assistant reply...
🧩 Active Memory: status=ok elapsed=842ms query=recent summary=34 chars
🔎 Active Memory Debug: Lemon pepper wings with blue cheese.
With /trace raw, the traced Model Input (User Role) block shows the raw
hidden prefix:
Context:
<active_memory_plugin>
...
</active_memory_plugin>
By default the blocking sub-agent's transcript is temporary and deleted after the run completes; see Transcript persistence to keep it.
Query modes
config.queryMode controls how much conversation the blocking sub-agent
sees. Pick the smallest mode that still answers follow-ups well; grow
timeoutMs as context size grows, from message to recent to full.
message
Only the latest user message is sent.
Latest user message only
Use when you want the fastest behavior, the strongest bias toward stable
preference recall, and follow-up turns do not need conversational
context. Start around 3000-5000 ms for config.timeoutMs.
recent
The latest user message plus a small recent conversational tail.
Recent conversation tail:
user: ...
assistant: ...
user: ...
Latest user message:
...
Use for a balance of speed and conversational grounding, when follow-up
questions often depend on the last few turns. Start around 15000 ms.
full
The full conversation is sent to the blocking sub-agent.
Full conversation context:
user: ...
assistant: ...
user: ...
...
Use when recall quality matters more than latency, or important setup is
far back in the thread. Start around 15000 ms or higher depending on
thread size.
Prompt styles
config.promptStyle controls how eager or strict the sub-agent is about
returning memory:
| Style | Behavior |
|---|---|
balanced | General-purpose default for recent mode |
strict | Least eager; minimal bleed from nearby context |
contextual | Most continuity-friendly; conversation history matters more |
recall-heavy | Surfaces memory on softer but still plausible matches |
precision-heavy | Aggressively prefers NONE unless the match is obvious |
preference-only | Optimized for favorites, habits, routines, taste, recurring personal facts |
Default mapping when config.promptStyle is unset:
message -> strict
recent -> balanced
full -> contextual
An explicit config.promptStyle always overrides the mapping.
Model fallback policy
If config.model is not set, active memory picks a model through this sequence:
explicit plugin model (config.model)
-> current session model
-> agent primary model
-> optional configured fallback model (config.modelFallback)
modelFallback: "google/gemini-3-flash";
When every entry in that chain comes up empty, recall is skipped for the current turn.
config.modelFallbackPolicy exists only as a deprecated compatibility field for older
configurations; it no longer affects runtime behavior. modelFallback serves
strictly as the final option in the sequence above, not as a runtime fallback
that substitutes another model when the chosen one fails.
Speed recommendations
The safest choice is to leave config.model unset, which inherits the session model:
this respects your current provider, authentication, and model preferences. To cut
latency, opt for a dedicated fast model instead. Recall quality still matters, but
latency carries more weight here than on the main answer path, and the tool
surface stays narrow, limited to memory recall tools.
Solid fast-model candidates:
cerebras/gpt-oss-120b, a dedicated low-latency recall modelgoogle/gemini-3-flash, a low-latency fallback that leaves your primary chat model untouched- your regular session model, achieved by leaving
config.modelunset
Cerebras setup
{
models: {
providers: {
cerebras: {
baseUrl: "https://api.cerebras.ai/v1",
apiKey: "${CEREBRAS_API_KEY}",
api: "openai-completions",
models: [{ id: "gpt-oss-120b", name: "GPT OSS 120B (Cerebras)" }],
},
},
},
plugins: {
entries: {
"active-memory": {
enabled: true,
config: { model: "cerebras/gpt-oss-120b" },
},
},
},
}
Make sure the Cerebras API key has chat/completions access for the model in
use. /v1/models visibility by itself does not ensure this.
Memory tools
config.toolsAllow defines the exact tool names the blocking sub-agent may
invoke for advanced Active Memory. The defaults shift with the memory provider:
| Memory provider | Default toolsAllow |
|---|---|
| Built-in memory | ["memory_search", "memory_get"] |
| LanceDB | ["memory_recall"] |
If none of the configured tools are present, or the sub-agent run fails, active memory skips recall for that turn and the main reply proceeds without memory context. For custom recall tools, non-empty model-visible tool output counts as recall evidence, unless structured result fields explicitly indicate an empty result or failure.
toolsAllow accepts only concrete memory tool names. Wildcards, group:*
entries, and core agent tools (read, exec, message, web_search, and
similar) get silently filtered out before the hidden sub-agent starts.
Built-in memory
No explicit toolsAllow is required:
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
agents: ["main"],
// Default: ["memory_search", "memory_get"]
},
},
},
},
}
LanceDB memory
Once LanceDB is installed and configured, Active
Memory automatically switches to memory_recall; no explicit toolsAllow is needed:
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
agents: ["main"],
promptAppend: "Use memory_recall for long-term user preferences, past decisions, and previously discussed topics. If recall finds nothing useful, return NONE.",
},
},
},
},
}
This represents the advanced Active Memory path for memories stored by LanceDB itself.
memory.search.rememberAcrossConversations does not expose private session
transcripts through memory_recall. When LanceDB is the active memory provider, rely on
LanceDB's auto-recall or the advanced configuration described above.
Lossless Claw
Lossless Claw is an
external context-engine plugin (openclaw plugins install @martian-engineering/lossless-claw) that ships its own recall tools. Configure it as a
context engine first; consult Context engine. Then
direct active memory toward its tools:
{
plugins: {
slots: {
contextEngine: "lossless-claw",
},
entries: {
"lossless-claw": {
enabled: true,
},
"active-memory": {
enabled: true,
config: {
agents: ["main"],
toolsAllow: ["memory_search", "lcm_grep", "lcm_describe", "lcm_expand_query"],
promptAppend: "Use lcm_grep first for compacted conversation recall. Use lcm_describe to inspect a specific summary. Use lcm_expand_query only when the latest user message needs exact details that may have been compacted away. Return NONE if the retrieved context is not clearly useful.",
},
},
},
},
}
Avoid adding lcm_expand to toolsAllow in this context. Lossless Claw treats it as a
lower-level tool for delegated expansion, not intended for the top-level
active-memory sub-agent. Lossless Claw alters context assembly without
replacing the current memory provider. Keep memory_search in toolsAllow
when rememberAcrossConversations is also in use. An LCM-only tool list stays
valid for advanced Active Memory but turns off the product transcript-recall
path.
Advanced escape hatches
Not part of the recommended setup.
config.thinking controls the sub-agent's thinking level (default "off",
since active memory operates in the reply path and extra thinking time directly
adds latency the user sees):
thinking: "medium"; // default: "off"
config.fastMode overrides fast mode only for the blocking memory sub-agent.
Choose true, false, or "auto"; leave it unset to inherit the normal
agent, session, and model defaults. "auto" applies the recall model's configured
fastAutoOnSeconds cutoff:
fastMode: true;
config.promptAppend appends operator instructions after the default prompt
and before the conversation context. Pair it with a custom toolsAllow when
a non-core memory plugin needs specific tool order or query shaping:
promptAppend: "Prefer stable long-term preferences over one-off events.";
config.promptOverride swaps out the entire default prompt (conversation context still gets appended after it). Only use this when intentionally testing a different recall contract, since the standard prompt is designed to produce either NONE or a concise user-fact context for the main model:
promptOverride: "You are a memory search agent. Return NONE or one compact user fact.";
Transcript persistence
Blocking sub-agent executions keep their runtime transcript in the agent's SQLite store. By default, OpenClaw deletes the temporary sub-agent session rows once the run completes and skips generating a JSONL file.
To save those transcripts as JSONL artifacts for debugging purposes:
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
agents: ["main"],
persistTranscripts: true,
transcriptDir: "active-memory",
},
},
},
},
}
Exported transcript artifacts are placed under the target agent's sessions folder, in a distinct directory from the active runtime state:
agents/<agent>/sessions/active-memory/<blocking-memory-sub-agent-session-id>.jsonl
Adjust the relative artifact subdirectory using config.transcriptDir. Be cautious here: exports can pile up quickly on active sessions, full query mode repeats a lot of conversation context, and these artifacts include hidden prompt context along with recalled memories.
Configuration
Every active memory configuration is located under plugins.entries.active-memory.
| Key | Type | Meaning |
|---|---|---|
enabled | boolean | Turns the plugin on or off |
config.mode | "escalate" | "always" | "off" | Determines when the blocking deep-recall sub-agent is triggered; "escalate" is the default |
config.agents | string[] | Identifies which agents are permitted to leverage active memory |
config.model | string | Optional model reference for the blocking sub-agent; if omitted, the current session model is used |
config.allowedChatTypes | ("direct" | "group" | "channel" | "explicit")[] | Session categories eligible for active memory; falls back to ["direct"] |
config.allowedChatIds | string[] | Optional per-conversation allowlist checked after allowedChatTypes; empty lists cause failure by default |
config.deniedChatIds | string[] | Optional per-conversation denylist that supersedes allowed session types and allowed ids |
config.queryMode | "message" | "recent" | "full" | Sets how much conversation context the blocking sub-agent receives |
config.promptStyle | "balanced" | "strict" | "contextual" | "recall-heavy" | "precision-heavy" | "preference-only" | Adjusts how permissive or strict the blocking sub-agent is when choosing to return memory |
config.toolsAllow | string[] | Specific memory tool names callable by the blocking sub-agent; defaults to ["memory_search", "memory_get"], or ["memory_recall"] when plugins.slots.memory equals memory-lancedb; wildcards, group:* entries, and core agent tools are disregarded |
config.thinking | "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max" | Advanced thinking override for the blocking sub-agent; off is the default for performance reasons |
config.fastMode | boolean | "auto" | Optional fast-mode override for the blocking sub-agent; if unset, standard agent, session, and model defaults apply |
config.promptOverride | string | Advanced full prompt substitution; not advised for typical usage |
config.promptAppend | string | Advanced extra instructions added to the default or overridden prompt |
config.timeoutMs | number | Maximum wait time for the blocking sub-agent (250-120000 ms; 15000 ms by default) |
config.setupGraceTimeoutMs | number | Advanced extra setup budget before the recall timeout expires; 0-30000 ms, with 0 as the default. Consult Cold-start grace for v2026.4.x upgrade notes |
config.maxSummaryChars | number | Character limit for the active-memory summary (40-1000; 220 by default) |
config.logging | boolean | Logs active memory activity during tuning |
config.persistTranscripts | boolean | Saves blocking sub-agent transcripts as JSONL artifacts before their temporary SQLite session rows are deleted |
config.transcriptDir | string | Relative directory for transcript artifacts under the agent sessions folder (default "active-memory") |
config.modelFallback | string | Optional model reserved for the final step in the model fallback chain |
Useful tuning fields:
| Key | Type | Meaning |
|---|---|---|
config.recentUserTurns | number | How many earlier user turns get pulled in when queryMode is set to recent (0 to 4 allowed; 2 is the default) |
config.recentAssistantTurns | number | How many earlier assistant turns get pulled in when queryMode is set to recent (0 to 3 allowed; 1 is the default) |
config.recentUserChars | number | Character ceiling for each recent user turn (40 to 1000 allowed; 220 is the default) |
config.recentAssistantChars | number | Character ceiling for each recent assistant turn (40 to 1000 allowed; 180 is the default) |
config.cacheTtlMs | number | Reusing cached results for repeated identical queries (1000 to 120000 ms allowed; 15000 is the default) |
config.circuitBreakerMaxTimeouts | number | Stop recalling after that many consecutive timeouts for the same agent/model. A successful recall or the cooldown elapsing resets it (1 to 20 allowed; 3 is the default). |
config.circuitBreakerCooldownMs | number | How long recall stays disabled once the circuit breaker trips, in ms (5000 to 600000 allowed; 60000 is the default). |
Recommended setup
Kick off with recent:
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
agents: ["main"],
mode: "escalate",
queryMode: "recent",
promptStyle: "balanced",
timeoutMs: 15000,
maxSummaryChars: 220,
logging: true,
},
},
},
},
}
While tuning, rely on /verbose on for the status line and /trace on for the debug summary; both arrive as a follow-up after the main reply, never before. Reserve always for cases where every eligible turn justifies the added latency. Stick with escalate for the suggested middle ground, then pick message, recent, or full for the deep-recall query itself.
Cold-start grace
Prior to v2026.5.2, the plugin quietly padded timeoutMs with an extra 30000 ms during cold start, letting model warm-up, embedding-index load, and the first recall share a single larger allowance. That grace period moved behind an explicit setupGraceTimeoutMs config in v2026.5.2: timeoutMs now serves as the default recall-work budget unless you opt in. The blocking hook splits that budget into two fixed stages: up to 1500 ms for session/config preflight before recall starts, then another fixed 1500 ms for abort settlement and transcript recovery once recall work ends. Neither allowance extends model or tool execution.
For anyone upgrading from v2026.4.x who tuned timeoutMs around the old implicit-grace behavior (the recommended starter timeoutMs: 15000 is one such case), set setupGraceTimeoutMs: 30000 to bring back the pre-v5.2 effective budget:
{
plugins: {
entries: {
"active-memory": {
config: {
timeoutMs: 15000,
setupGraceTimeoutMs: 30000,
},
},
},
},
}
The worst-case blocking time lands at timeoutMs + setupGraceTimeoutMs + 3000 ms: the configured recall-work budget, plus up to 1500 ms preflight, plus a fixed 1500 ms post-recall completion allowance. The embedded recall runner operates under the same effective timeout budget, so setupGraceTimeoutMs spans both the outer prompt-build watchdog and the inner blocking recall run.
On resource-constrained gateways where cold-start latency is an acceptable cost, lower values (5000-15000 ms) function fine too, though the first recall after a gateway restart is more likely to come back empty while warm-up finishes.
Debugging
If active memory is missing where you expect it:
- Verify the plugin is active under
plugins.entries.active-memory.enabled. - For Remember across conversations, check that the agent's effective
memory.search.rememberAcrossConversationssetting is on, runopenclaw doctorto confirm the current memory provider handles protected transcript recall, and ensureconfig.toolsAllowincludesmemory_searchwhen explicitly configured. For advanced Active Memory, verify the agent ID appears inconfig.agents. - Make sure you are testing through an eligible interactive persistent conversation.
- Keep in mind that groups and channels never use cross-conversation transcript recall.
- Enable
config.logging: trueand check the gateway logs. - Confirm memory search itself functions with
openclaw status --deep.
When memory hits feel noisy, tighten maxSummaryChars. If active memory lags, reduce queryMode, reduce timeoutMs, or trim recent turn counts and per-turn char caps.
Common issues
Advanced Active Memory depends on the configured memory plugin's recall pipeline, so most recall surprises trace back to embedding-provider issues rather than active-memory bugs. The default memory-core path relies on memory_search and memory_get; the memory-lancedb slot uses memory_recall. With a different memory plugin, verify config.toolsAllow names the tools that plugin actually registers. Remember across conversations is more limited: the current memory provider must support OpenClaw's protected same-agent/private-session recall path.
Embedding provider switched or stopped working
When memory.search.provider is not configured, OpenAI embeddings serve as the default. To use Bedrock, DeepInfra, Gemini, GitHub Copilot, LM Studio, local, Mistral, Ollama, Voyage, or OpenAI-compatible embeddings, you must set memory.search.provider explicitly. If the chosen provider is unavailable, memory_search can fall back to lexical-only retrieval; however, failures that occur at runtime after a provider has been selected do not trigger automatic fallback.
Only set an optional memory.search.fallback when you specifically want a single, deliberate fallback. The complete provider list and usage examples are available in Memory Search.
Recall feels slow, empty, or inconsistent
- Enable
/trace onto display the plugin-owned Active Memory debug summary in the session. - Enable
/verbose onto additionally show the🧩 Active Memory: ...status line following every reply. - Check gateway logs for
active-memory: ... start|done,memory sync failed (search-bootstrap), or provider embedding errors. - Execute
openclaw status --deepto check the memory-search backend and index health. - When using
ollama, verify that the embedding model is installed (ollama list).
First recall after gateway restart returns status=timeout
Starting with v2026.5.2, if cold-start setup (model warm-up plus embedding index load) is incomplete when the first recall occurs, the run may consume the configured timeoutMs budget and return status=timeout with no output. Gateway logs will show active-memory timeout after Nms around the first eligible reply after a restart.
The recommended setupGraceTimeoutMs value is described in Cold-start grace under Recommended setup.