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: true turns the plugin on
  • config.mode: "escalate" runs deep recall only for recall intent without a strong deterministic hit
  • config.agents: ["main"] opts only the main agent in
  • config.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 model
  • config.modelFallback is used only when no explicit or inherited model resolves
  • config.fastMode optionally overrides fast mode for recall without changing the main agent
  • config.promptStyle: "balanced" is the default for recent mode
  • 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:

SurfaceRuns active memory?
Control UI / web chat persistent sessionsYes, when either activation path targets the agent
Other interactive channel sessions on the same persistent chat pathYes, when either activation path allows the conversation
Headless one-shot runsNo
Heartbeat/background runsNo
Generic internal agent-command pathsNo
Sub-agent/internal helper executionNo

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:

  1. Remember across conversations automatically targets agents whose effective memory.search.rememberAcrossConversations setting is enabled, but only for private direct or persistent explicit UI conversations.
  2. Advanced Active Memory targets agent IDs listed in plugins.entries.active-memory.config.agents and 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:

ModeBehavior
escalateDefault. Run only for recall intent when lane 1 has no strong hit.
alwaysPreserve the previous behavior and run on every eligible targeted turn.
offDisable 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:

  • allowedChatIds is 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 to allowedChatIds too, or keep allowedChatTypes scoped to the group/channel rollout you are testing.
  • deniedChatIds is a denylist that always wins over allowedChatTypes and allowedChatIds.

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 on adds a status line: 🧩 Active Memory: status=ok elapsed=842ms query=recent summary=34 chars
  • /trace on adds 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:

StyleBehavior
balancedGeneral-purpose default for recent mode
strictLeast eager; minimal bleed from nearby context
contextualMost continuity-friendly; conversation history matters more
recall-heavySurfaces memory on softer but still plausible matches
precision-heavyAggressively prefers NONE unless the match is obvious
preference-onlyOptimized 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 model
  • google/gemini-3-flash, a low-latency fallback that leaves your primary chat model untouched
  • your regular session model, achieved by leaving config.model unset

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 providerDefault 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.

KeyTypeMeaning
enabledbooleanTurns 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.agentsstring[]Identifies which agents are permitted to leverage active memory
config.modelstringOptional 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.allowedChatIdsstring[]Optional per-conversation allowlist checked after allowedChatTypes; empty lists cause failure by default
config.deniedChatIdsstring[]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.toolsAllowstring[]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.fastModeboolean | "auto"Optional fast-mode override for the blocking sub-agent; if unset, standard agent, session, and model defaults apply
config.promptOverridestringAdvanced full prompt substitution; not advised for typical usage
config.promptAppendstringAdvanced extra instructions added to the default or overridden prompt
config.timeoutMsnumberMaximum wait time for the blocking sub-agent (250-120000 ms; 15000 ms by default)
config.setupGraceTimeoutMsnumberAdvanced 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.maxSummaryCharsnumberCharacter limit for the active-memory summary (40-1000; 220 by default)
config.loggingbooleanLogs active memory activity during tuning
config.persistTranscriptsbooleanSaves blocking sub-agent transcripts as JSONL artifacts before their temporary SQLite session rows are deleted
config.transcriptDirstringRelative directory for transcript artifacts under the agent sessions folder (default "active-memory")
config.modelFallbackstringOptional model reserved for the final step in the model fallback chain

Useful tuning fields:

KeyTypeMeaning
config.recentUserTurnsnumberHow many earlier user turns get pulled in when queryMode is set to recent (0 to 4 allowed; 2 is the default)
config.recentAssistantTurnsnumberHow many earlier assistant turns get pulled in when queryMode is set to recent (0 to 3 allowed; 1 is the default)
config.recentUserCharsnumberCharacter ceiling for each recent user turn (40 to 1000 allowed; 220 is the default)
config.recentAssistantCharsnumberCharacter ceiling for each recent assistant turn (40 to 1000 allowed; 180 is the default)
config.cacheTtlMsnumberReusing cached results for repeated identical queries (1000 to 120000 ms allowed; 15000 is the default)
config.circuitBreakerMaxTimeoutsnumberStop 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.circuitBreakerCooldownMsnumberHow long recall stays disabled once the circuit breaker trips, in ms (5000 to 600000 allowed; 60000 is the default).

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:

  1. Verify the plugin is active under plugins.entries.active-memory.enabled.
  2. For Remember across conversations, check that the agent's effective memory.search.rememberAcrossConversations setting is on, run openclaw doctor to confirm the current memory provider handles protected transcript recall, and ensure config.toolsAllow includes memory_search when explicitly configured. For advanced Active Memory, verify the agent ID appears in config.agents.
  3. Make sure you are testing through an eligible interactive persistent conversation.
  4. Keep in mind that groups and channels never use cross-conversation transcript recall.
  5. Enable config.logging: true and check the gateway logs.
  6. 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 on to display the plugin-owned Active Memory debug summary in the session.
  • Enable /verbose on to 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 --deep to 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.

4,268 words · updated Aug 10, 2026