diff --git a/.openclaw-sync/source.json b/.openclaw-sync/source.json
index dc0ea4922..6759126fc 100644
--- a/.openclaw-sync/source.json
+++ b/.openclaw-sync/source.json
@@ -1,5 +1,5 @@
{
"repository": "openclaw/openclaw",
- "sha": "164287f0569a271d073dbffc9e8e0657cf00ca0b",
- "syncedAt": "2026-04-09T16:01:55.036Z"
+ "sha": "b83726d13e336643d0b68d8aae79f222b8d26e90",
+ "syncedAt": "2026-04-09T16:28:17.601Z"
}
diff --git a/docs/concepts/active-memory.md b/docs/concepts/active-memory.md
new file mode 100644
index 000000000..0f03ed214
--- /dev/null
+++ b/docs/concepts/active-memory.md
@@ -0,0 +1,608 @@
+---
+title: "Active Memory"
+summary: "A plugin-owned blocking memory sub-agent that injects relevant memory into interactive chat sessions"
+read_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
+
+Active memory is an optional plugin-owned blocking memory sub-agent that runs
+before the main reply for eligible conversational sessions.
+
+It exists because most memory systems are capable but reactive. They rely on
+the main agent to decide when to search memory, or on the user to say things
+like "remember this" or "search memory." By then, the moment where memory would
+have made the reply feel natural has already passed.
+
+Active memory gives the system one bounded chance to surface relevant memory
+before the main reply is generated.
+
+## Paste This Into Your Agent
+
+Paste this into your agent if you want it to enable Active Memory with a
+self-contained, safe-default setup:
+
+```json5
+{
+ 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 turns the plugin on for the `main` agent, keeps it limited to direct-message
+style sessions by default, lets it inherit the current session model first, and
+still allows the built-in remote fallback if no explicit or inherited model is
+available.
+
+After that, restart the gateway:
+
+```bash
+node scripts/run-node.mjs gateway --profile dev
+```
+
+To inspect it live in a conversation:
+
+```text
+/verbose on
+```
+
+## Turn active memory on
+
+The safest setup is:
+
+1. enable the plugin
+2. target one conversational agent
+3. keep logging on only while tuning
+
+Start with this in `openclaw.json`:
+
+```json5
+{
+ 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:
+
+```bash
+node scripts/run-node.mjs gateway --profile dev
+```
+
+What this means:
+
+- `plugins.entries.active-memory.enabled: true` turns the plugin on
+- `config.agents: ["main"]` opts only the `main` agent into active memory
+- `config.allowedChatTypes: ["direct"]` keeps active memory on for direct-message style sessions only by default
+- if `config.model` is unset, active memory inherits the current session model first
+- `config.modelFallbackPolicy: "default-remote"` keeps the built-in remote fallback as the default when no explicit or inherited model is available
+- `config.promptStyle: "balanced"` uses the default general-purpose prompt style for `recent` mode
+- active memory still runs only on eligible interactive persistent chat sessions
+
+## How to see it
+
+Active memory injects hidden system context for the model. It does not expose
+raw `...` tags to the client.
+
+## Session toggle
+
+Use the plugin command when you want to pause or resume active memory for the
+current chat session without editing config:
+
+```text
+/active-memory status
+/active-memory off
+/active-memory on
+```
+
+This is session-scoped. It does not change
+`plugins.entries.active-memory.enabled`, agent targeting, or other global
+configuration.
+
+If you want the command to write config and pause or resume active memory for
+all sessions, use the explicit global form:
+
+```text
+/active-memory status --global
+/active-memory off --global
+/active-memory on --global
+```
+
+The global form writes `plugins.entries.active-memory.config.enabled`. It leaves
+`plugins.entries.active-memory.enabled` on so the command remains available to
+turn active memory back on later.
+
+If you want to see what active memory is doing in a live session, turn verbose
+mode on for that session:
+
+```text
+/verbose on
+```
+
+With verbose enabled, OpenClaw can show:
+
+- an active memory status line such as `Active Memory: ok 842ms recent 34 chars`
+- a readable debug summary such as `Active Memory Debug: Lemon pepper wings with blue cheese.`
+
+Those lines are derived from the same active memory pass that feeds the hidden
+system context, but they are formatted for humans instead of exposing raw prompt
+markup.
+
+By default, the blocking memory sub-agent transcript is temporary and deleted
+after the run completes.
+
+Example flow:
+
+```text
+/verbose on
+what wings should i order?
+```
+
+Expected visible reply shape:
+
+```text
+...normal assistant reply...
+
+🧩 Active Memory: ok 842ms recent 34 chars
+🔎 Active Memory Debug: Lemon pepper wings with blue cheese.
+```
+
+## When it runs
+
+Active memory uses two gates:
+
+1. **Config opt-in**
+ The plugin must be enabled, and the current agent id must appear in
+ `plugins.entries.active-memory.config.agents`.
+2. **Strict runtime eligibility**
+ Even when enabled and targeted, active memory only runs for eligible
+ interactive persistent chat sessions.
+
+The actual rule is:
+
+```text
+plugin enabled
++
+agent id targeted
++
+allowed chat type
++
+eligible interactive persistent chat session
+=
+active memory runs
+```
+
+If any of those fail, active memory does not run.
+
+## Session types
+
+`config.allowedChatTypes` controls which kinds of conversations may run Active
+Memory at all.
+
+The default is:
+
+```json5
+allowedChatTypes: ["direct"]
+```
+
+That means Active Memory runs by default in direct-message style sessions, but
+not in group or channel sessions unless you opt them in explicitly.
+
+Examples:
+
+```json5
+allowedChatTypes: ["direct"]
+```
+
+```json5
+allowedChatTypes: ["direct", "group"]
+```
+
+```json5
+allowedChatTypes: ["direct", "group", "channel"]
+```
+
+## Where it runs
+
+Active memory is a conversational enrichment feature, not a platform-wide
+inference feature.
+
+| 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
+
+Use active memory when:
+
+- the session is persistent and user-facing
+- the agent has meaningful long-term memory to search
+- continuity and personalization matter more than raw prompt determinism
+
+It works especially well for:
+
+- stable preferences
+- recurring habits
+- long-term user 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
+
+The runtime shape is:
+
+```mermaid
+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"]
+```
+
+The blocking memory sub-agent can use only:
+
+- `memory_search`
+- `memory_get`
+
+If the connection is weak, it should return `NONE`.
+
+## Query modes
+
+`config.queryMode` controls how much conversation the blocking memory sub-agent sees.
+
+## Prompt styles
+
+`config.promptStyle` controls how eager or strict the blocking memory sub-agent is
+when deciding whether to return memory.
+
+Available styles:
+
+- `balanced`: general-purpose default for `recent` mode
+- `strict`: least eager; best when you want very little bleed from nearby context
+- `contextual`: most continuity-friendly; best when conversation history should matter more
+- `recall-heavy`: more willing to surface 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, and recurring personal facts
+
+Default mapping when `config.promptStyle` is unset:
+
+```text
+message -> strict
+recent -> balanced
+full -> contextual
+```
+
+If you set `config.promptStyle` explicitly, that override wins.
+
+Example:
+
+```json5
+promptStyle: "preference-only"
+```
+
+## Model fallback policy
+
+If `config.model` is unset, Active Memory tries to resolve a model in this order:
+
+```text
+explicit plugin model
+-> current session model
+-> agent primary model
+-> optional built-in remote fallback
+```
+
+`config.modelFallbackPolicy` controls the last step.
+
+Default:
+
+```json5
+modelFallbackPolicy: "default-remote"
+```
+
+Other option:
+
+```json5
+modelFallbackPolicy: "resolved-only"
+```
+
+Use `resolved-only` if you want Active Memory to skip recall instead of falling
+back to the built-in remote default when no explicit or inherited model is
+available.
+
+## Advanced escape hatches
+
+These options are intentionally not part of the recommended setup.
+
+`config.thinking` can override the blocking memory sub-agent thinking level:
+
+```json5
+thinking: "medium"
+```
+
+Default:
+
+```json5
+thinking: "off"
+```
+
+Do not enable this by default. Active Memory runs in the reply path, so extra
+thinking time directly increases user-visible latency.
+
+`config.promptAppend` adds extra operator instructions after the default Active
+Memory prompt and before the conversation context:
+
+```json5
+promptAppend: "Prefer stable long-term preferences over one-off events."
+```
+
+`config.promptOverride` replaces the default Active Memory prompt. OpenClaw
+still appends the conversation context afterward:
+
+```json5
+promptOverride: "You are a memory search agent. Return NONE or one compact user fact."
+```
+
+Prompt customization is not recommended unless you are deliberately testing a
+different recall contract. The default prompt is tuned to return either `NONE`
+or compact user-fact context for the main model.
+
+### `message`
+
+Only the latest user message is sent.
+
+```text
+Latest user message only
+```
+
+Use this when:
+
+- you want the fastest behavior
+- you want the strongest bias toward stable preference recall
+- follow-up turns do not need conversational context
+
+Recommended timeout:
+
+- start around `3000` to `5000` ms
+
+### `recent`
+
+The latest user message plus a small recent conversational tail is sent.
+
+```text
+Recent conversation tail:
+user: ...
+assistant: ...
+user: ...
+
+Latest user message:
+...
+```
+
+Use this when:
+
+- you want a better balance of speed and conversational grounding
+- follow-up questions often depend on the last few turns
+
+Recommended timeout:
+
+- start around `15000` ms
+
+### `full`
+
+The full conversation is sent to the blocking memory sub-agent.
+
+```text
+Full conversation context:
+user: ...
+assistant: ...
+user: ...
+...
+```
+
+Use this when:
+
+- the strongest recall quality matters more than latency
+- the conversation contains important setup far back in the thread
+
+Recommended timeout:
+
+- increase it substantially compared with `message` or `recent`
+- start around `15000` ms or higher depending on thread size
+
+In general, timeout should increase with context size:
+
+```text
+message < recent < full
+```
+
+## Transcript persistence
+
+Active memory blocking memory sub-agent runs create a real `session.jsonl`
+transcript during the blocking memory sub-agent call.
+
+By default, that transcript is temporary:
+
+- it is written to a temp directory
+- it is used only for the blocking memory sub-agent run
+- it is deleted immediately after the run finishes
+
+If you want to keep those blocking memory sub-agent transcripts on disk for debugging or
+inspection, turn persistence on explicitly:
+
+```json5
+{
+ plugins: {
+ entries: {
+ "active-memory": {
+ enabled: true,
+ config: {
+ agents: ["main"],
+ persistTranscripts: true,
+ transcriptDir: "active-memory",
+ },
+ },
+ },
+ },
+}
+```
+
+When enabled, active memory stores transcripts in a separate directory under the
+target agent's sessions folder, not in the main user conversation transcript
+path.
+
+The default layout is conceptually:
+
+```text
+agents//sessions/active-memory/.jsonl
+```
+
+You can change the relative subdirectory with `config.transcriptDir`.
+
+Use this carefully:
+
+- blocking memory sub-agent transcripts can accumulate quickly on busy sessions
+- `full` query mode can duplicate a lot of conversation context
+- these transcripts contain hidden prompt context and recalled memories
+
+## Configuration
+
+All active memory configuration lives under:
+
+```text
+plugins.entries.active-memory
+```
+
+The most important fields are:
+
+| 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 |
+
+Useful tuning fields:
+
+| 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
+
+Start with `recent`.
+
+```json5
+{
+ plugins: {
+ entries: {
+ "active-memory": {
+ enabled: true,
+ config: {
+ agents: ["main"],
+ queryMode: "recent",
+ promptStyle: "balanced",
+ timeoutMs: 15000,
+ maxSummaryChars: 220,
+ logging: true,
+ },
+ },
+ },
+ },
+}
+```
+
+If you want to inspect live behavior while tuning, use `/verbose on` in the
+session instead of looking for a separate active-memory debug command.
+
+Then move to:
+
+- `message` if you want lower latency
+- `full` if you decide extra context is worth the slower blocking memory sub-agent
+
+## Debugging
+
+If active memory is not showing up where you expect:
+
+1. Confirm the plugin is enabled under `plugins.entries.active-memory.enabled`.
+2. Confirm the current agent id is listed in `config.agents`.
+3. Confirm you are testing through an interactive persistent chat session.
+4. Turn on `config.logging: true` and watch the gateway logs.
+5. Verify memory search itself works with `openclaw memory status --deep`.
+
+If memory hits are noisy, tighten:
+
+- `maxSummaryChars`
+
+If active memory is too slow:
+
+- lower `queryMode`
+- lower `timeoutMs`
+- reduce recent turn counts
+- reduce per-turn char caps
+
+## Related pages
+
+- [Memory Search](/concepts/memory-search)
+- [Memory configuration reference](/reference/memory-config)
+- [Plugin SDK setup](/plugins/sdk-setup)
diff --git a/docs/concepts/memory-search.md b/docs/concepts/memory-search.md
index c769513a0..795a7a0a2 100644
--- a/docs/concepts/memory-search.md
+++ b/docs/concepts/memory-search.md
@@ -138,5 +138,6 @@ earlier conversations. This is opt-in via
## Further reading
+- [Active Memory](/concepts/active-memory) -- sub-agent memory for interactive chat sessions
- [Memory](/concepts/memory) -- file layout, backends, tools
- [Memory configuration reference](/reference/memory-config) -- all config knobs
diff --git a/docs/reference/memory-config.md b/docs/reference/memory-config.md
index 93c3959cb..4d2234e68 100644
--- a/docs/reference/memory-config.md
+++ b/docs/reference/memory-config.md
@@ -17,10 +17,22 @@ conceptual overviews, see:
- [Builtin Engine](/concepts/memory-builtin) -- default SQLite backend
- [QMD Engine](/concepts/memory-qmd) -- local-first sidecar
- [Memory Search](/concepts/memory-search) -- search pipeline and tuning
+- [Active Memory](/concepts/active-memory) -- enabling the memory sub-agent for interactive sessions
All memory search settings live under `agents.defaults.memorySearch` in
`openclaw.json` unless noted otherwise.
+If you are looking for the **active memory** feature toggle and sub-agent config,
+that lives under `plugins.entries.active-memory` instead of `memorySearch`.
+
+Active memory uses a two-gate model:
+
+1. the plugin must be enabled and target the current agent id
+2. the request must be an eligible interactive persistent chat session
+
+See [Active Memory](/concepts/active-memory) for the activation model,
+plugin-owned config, transcript persistence, and safe rollout pattern.
+
---
## Provider selection