@nowledge/openclaw-nowledge-mem 0.3.0 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,76 @@
2
2
 
3
3
  All notable changes to the Nowledge Mem OpenClaw plugin will be documented in this file.
4
4
 
5
+ ## [0.6.5] - 2026-02-26
6
+
7
+ ### Added — Thread tools + sourceThreadId linkage
8
+
9
+ **Two new tools for conversation retrieval.** The plugin now provides 9 tools total.
10
+
11
+ - `nowledge_mem_thread_search` — Search past conversations by keyword. Returns matched threads with message snippets and relevance scores. Use when the user asks about a past discussion or wants to find a specific conversation.
12
+ - `nowledge_mem_thread_fetch` — Fetch full messages from a specific thread with pagination support. Use to progressively retrieve long conversations. Accepts `offset` and `limit` for paginated retrieval.
13
+
14
+ **Memories now link back to their source conversations.**
15
+
16
+ Every memory distilled from a conversation now includes `sourceThreadId` in search results (`memory_search`) and individual lookups (`memory_get`). This enables the progressive retrieval workflow: search memories, see which thread they came from, fetch the full conversation for context.
17
+
18
+ **New client methods:**
19
+
20
+ - `client.searchThreadsFull(query, { limit, source })` — Full-featured thread search (throws on error, supports source filter). CLI-first with API fallback.
21
+ - `client.fetchThread(threadId, { offset, limit })` — Fetch messages from a thread with pagination. CLI-first with API fallback.
22
+
23
+ **Save deduplication.**
24
+
25
+ Before saving, the plugin checks for near-identical existing memories (≥90% similarity). If a match is found, the save is skipped and the existing memory is returned — preventing obvious duplicates at the plugin level. Deeper semantic dedup is handled by the Knowledge Agent's EVOLVES chains in the background.
26
+
27
+ **Context-aware behavioral guidance.**
28
+
29
+ The always-on hook now tells the agent about `nowledge_mem_thread_fetch` for following up on `sourceThreadId` links. When `sessionContext` is enabled, the guidance adjusts to note that relevant memories have already been injected — reducing redundant `memory_search` calls.
30
+
31
+ ## [0.6.4] - 2026-02-26
32
+
33
+ ### Changed — Thread search enrichment + sessionDigest default on
34
+
35
+ **`memory_search` now includes relevant conversation threads.**
36
+
37
+ When you search memories, the response now also includes `relatedThreads` — snippets from past conversations that match the query. This uses the backend's BM25 thread search (`GET /threads/search`). Thread search is best-effort: if it fails or returns nothing, the memory results are returned as before. No new tool for the agent to learn — thread context surfaces automatically alongside memories.
38
+
39
+ **`sessionDigest` now defaults to `true`.**
40
+
41
+ Previously, session digest (thread capture + LLM distillation at session end) was off by default. The cost is negligible — one lightweight triage call per session end, full distillation only when worthwhile. With this change, conversations are captured and distilled automatically out of the box. Users who explicitly set `sessionDigest: false` are unaffected.
42
+
43
+ **Behavioral hook updated.**
44
+
45
+ The always-on guidance now mentions that `memory_search` returns conversation snippets alongside memories, so the agent knows to use the enriched results.
46
+
47
+ ### Added
48
+
49
+ - `client.searchThreads(query, limit)` — calls `GET /threads/search` API. Returns top matching threads with message snippets and relevance scores. Best-effort: never throws.
50
+ - Version bumped to 0.6.4.
51
+
52
+ ## [0.4.0] - 2026-02-26
53
+
54
+ ### Changed — Rename config + always-on behavioral guidance
55
+
56
+ **Renamed config options** (old names still work as silent aliases):
57
+
58
+ | Old name | New name |
59
+ |----------|----------|
60
+ | `autoRecall` | `sessionContext` |
61
+ | `autoCapture` | `sessionDigest` |
62
+ | `captureMinInterval` | `digestMinInterval` |
63
+ | `maxRecallResults` | `maxContextResults` |
64
+
65
+ Existing configs with old names continue to work — aliases are resolved transparently in `parseConfig()`. New names take precedence if both are present.
66
+
67
+ **Added: Always-on behavioral hook**
68
+
69
+ The agent now receives brief behavioral guidance (~50 tokens) on every turn via `before_prompt_build`, telling it to proactively save and search. This fires in ALL modes, including tool-only (default). Previously, without `sessionContext` enabled, the agent had no system-level instruction to use memory tools — most LLMs ignored the "call proactively" hints in tool descriptions. This is the single most impactful change for memory adoption.
70
+
71
+ **Migrated: `before_prompt_build` for session context**
72
+
73
+ Session context injection (formerly "autoRecall") now uses the modern `before_prompt_build` hook instead of legacy `before_agent_start`. Both the behavioral hook and session context coexist — OpenClaw concatenates multiple `prependContext` values with `\n\n`.
74
+
5
75
  ## [0.3.0] - 2026-02-23
6
76
 
7
77
  ### Changed — Architecture overhaul: tool-first, LLM-based capture
package/CLAUDE.md CHANGED
@@ -28,26 +28,29 @@ Reflects Nowledge Mem's genuine v0.6 strengths:
28
28
  src/
29
29
  index.js — plugin registration (tools, hooks, commands, CLI)
30
30
  client.js — CLI wrapper with API fallback; credential handling
31
- config.js — strict config parsing (apiUrl, apiKey, autoRecall, etc.)
31
+ config.js — strict config parsing (apiUrl, apiKey, sessionContext, etc.)
32
32
  hooks/
33
- recall.js — before_agent_start: inject Working Memory + recalled memories
34
- capture.js — quality-gated memory note + thread append
33
+ behavioral.js — always-on behavioral guidance (~50 tokens/turn)
34
+ recall.js — before_prompt_build: inject Working Memory + recalled memories
35
+ capture.js — thread capture + LLM triage/distillation at session lifecycle events
35
36
  tools/
36
- memory-search.js — OpenClaw compat; multi-signal; bi-temporal; relevance_reason
37
- memory-get.js — OpenClaw compat; supports MEMORY.md alias
38
- save.js — structured capture: unit_type, labels, temporal, importance
39
- context.js — Working Memory daily briefing (read-only)
37
+ memory-search.js — OpenClaw compat; multi-signal; bi-temporal; relevance_reason; sourceThreadId
38
+ memory-get.js — OpenClaw compat; supports MEMORY.md alias; sourceThreadId
39
+ save.js — structured capture: unit_type, labels, temporal, importance; pre-save dedup check
40
+ context.js — Working Memory daily briefing (read + section-level patch)
40
41
  connections.js — graph exploration: edge types, relationship strength, provenance
41
42
  timeline.js — activity feed: daily grouping, event_type filter, memoryId hints
42
43
  forget.js — memory deletion by ID or search
44
+ thread-search.js — search past conversations by keyword
45
+ thread-fetch.js — fetch full messages from a thread with pagination
43
46
  openclaw.plugin.json — manifest + config schema (version, uiHints, configSchema)
44
47
  ```
45
48
 
46
- ## Tool Surface (7 tools)
49
+ ## Tool Surface (9 tools)
47
50
 
48
51
  ### OpenClaw Memory Slot (required for system prompt activation)
49
- - `memory_search` — multi-signal: BM25 + embedding + label + graph + decay. Returns `matchedVia` ("Text Match 100% + Semantic 69%"), `importance`, bi-temporal filters (`event_date_from/to`, `recorded_date_from/to`). Mode: `"multi-signal"`.
50
- - `memory_get` — retrieve by `nowledgemem://memory/<id>` path or bare ID. `MEMORY.md` → Working Memory.
52
+ - `memory_search` — multi-signal: BM25 + embedding + label + graph + decay. Returns `matchedVia` ("Text Match 100% + Semantic 69%"), `importance`, bi-temporal filters (`event_date_from/to`, `recorded_date_from/to`). Also returns `relatedThreads` (past conversation snippets matching the query) and `sourceThreadId` (link to source conversation). Mode: `"multi-signal"`.
53
+ - `memory_get` — retrieve by `nowledgemem://memory/<id>` path or bare ID. `MEMORY.md` → Working Memory. Returns `sourceThreadId` when available.
51
54
 
52
55
  ### Nowledge Mem Native (differentiators)
53
56
  - `nowledge_mem_save` — structured capture: `unit_type`, `labels[]`, `event_start`, `event_end`, `temporal_context`, `importance`. All fields wired to CLI and API.
@@ -56,10 +59,15 @@ openclaw.plugin.json — manifest + config schema (version, uiHints, configSchem
56
59
  - `nowledge_mem_timeline` — activity feed via `nmem f`. Groups by day. `event_type` filter. Exact date range via `date_from`/`date_to` (YYYY-MM-DD). Entries include `(id: <memoryId>)` for chaining to connections.
57
60
  - `nowledge_mem_forget` — delete by ID or fuzzy query.
58
61
 
62
+ ### Thread Tools (progressive conversation retrieval)
63
+ - `nowledge_mem_thread_search` — search past conversations by keyword. Returns threads with matched message snippets, relevance scores, and message counts. Supports `source` filter.
64
+ - `nowledge_mem_thread_fetch` — fetch full messages from a specific thread. Supports pagination via `offset` + `limit` for progressive retrieval of long conversations.
65
+
59
66
  ## Hook Surface
60
67
 
61
- - `before_agent_start` — auto-recall: Working Memory + `searchRich()` with `relevanceReason` in context
62
- - `agent_end` — quality-gated memory note + thread append (requires `autoCapture: true`)
68
+ - `before_prompt_build` (always-on) — behavioral guidance: brief note telling agent to save/search proactively. Adjusts when sessionContext is on to avoid redundant searches.
69
+ - `before_prompt_build` (sessionContext) — session context: Working Memory + `searchRich()` with `relevanceReason` in context
70
+ - `agent_end` — thread capture + LLM triage/distillation (requires `sessionDigest: true`)
63
71
  - `after_compaction` — thread append
64
72
  - `before_reset` — thread append
65
73
 
@@ -73,9 +81,10 @@ openclaw.plugin.json — manifest + config schema (version, uiHints, configSchem
73
81
 
74
82
  | Key | Type | Default | Description |
75
83
  |-----|------|---------|-------------|
76
- | `autoRecall` | boolean | `false` | Inject context at session start |
77
- | `autoCapture` | boolean | `false` | Capture notes/threads at session end |
78
- | `maxRecallResults` | integer 1–20 | `5` | How many memories to recall |
84
+ | `sessionContext` | boolean | `false` | Inject Working Memory + relevant memories at prompt time |
85
+ | `sessionDigest` | boolean | `true` | Thread capture + LLM distillation at session end |
86
+ | `maxContextResults` | integer 1–20 | `5` | How many memories to inject at prompt time |
87
+ | `digestMinInterval` | integer | `300` | Minimum seconds between session digests |
79
88
  | `apiUrl` | string | `""` | Remote server URL. Empty = local (127.0.0.1:14242) |
80
89
  | `apiKey` | string | `""` | API key. Injected as `NMEM_API_KEY` env var only. Never logged. |
81
90
 
@@ -98,6 +107,9 @@ openclaw.plugin.json — manifest + config schema (version, uiHints, configSchem
98
107
  | `nmem --json wm read` | `client.readWorkingMemory()` | Working Memory read |
99
108
  | `nmem --json wm patch --heading "## S" --content/--append` | `client.patchWorkingMemory()` | Section-level WM update |
100
109
  | `nmem --json m delete <id>` | `client.execJson()` in forget.js | Delete |
110
+ | `GET /threads/search?query=&limit=` | `client.searchThreads()` | Thread search enrichment (best-effort, API-only) |
111
+ | `nmem --json t search <q> --limit N` | `client.searchThreadsFull()` | Full thread search (CLI-first, API fallback) |
112
+ | `nmem --json t show <id> --limit N --offset O` | `client.fetchThread()` | Fetch thread messages with pagination |
101
113
 
102
114
  All commands have API fallback for older CLI versions.
103
115
 
package/README.md CHANGED
@@ -32,7 +32,7 @@ Start Nowledge Mem desktop app or run `nmem serve`, then configure:
32
32
  }
33
33
  ```
34
34
 
35
- That's it. The agent gets 7 tools and calls them on demand. No extra tokens wasted.
35
+ That's it. The agent gets 9 tools and calls them on demand. No extra tokens wasted.
36
36
 
37
37
  ### Remote mode
38
38
 
@@ -57,15 +57,138 @@ Connect to a Nowledge Mem server running elsewhere — on a VPS, a home server,
57
57
 
58
58
  The `apiKey` is injected as `NMEM_API_KEY` into the nmem CLI process — never passed as a CLI argument, never logged.
59
59
 
60
+ ## How It Works
61
+
62
+ ### Per-Turn Flow
63
+
64
+ Every user message triggers hooks before the agent sees it, then the agent decides which tools to call.
65
+
66
+ ```mermaid
67
+ flowchart TD
68
+ A["User sends message"] --> B["before_prompt_build hook"]
69
+
70
+ B --> C["Behavioral guidance(always, ~110 tokens)"]
71
+ B -.->|"sessionContext: true"| D["Working Memory +relevant memories (~1-2 KB)"]
72
+
73
+ C --> E["Agent processes message(9 tools available)"]
74
+ D --> E
75
+
76
+ E --> F{"Needs past context?"}
77
+ F -->|"Yes"| G["memory_search"]
78
+ G --> R
79
+
80
+ E --> H{"Something worth keeping?"}
81
+ H -->|"Yes"| I["nowledge_mem_save(typed, labeled, temporal)"]
82
+ I --> R
83
+
84
+ E --> R["Respond to user"]
85
+ ```
86
+
87
+ ### When Each Tool Gets Called
88
+
89
+ The behavioral hook nudges the agent to **search before answering** and **save after deciding**. Here's when each tool fires:
90
+
91
+ | Scenario | Tool | What happens |
92
+ |----------|------|--------------|
93
+ | User asks a question | `memory_search` | Search knowledge base before answering. Also returns `relatedThreads` snippets and `sourceThreadId`. |
94
+ | Agent needs full memory text | `memory_get` | Read one memory by ID or path. `MEMORY.md` alias reads Working Memory. Returns `sourceThreadId`. |
95
+ | Decision made, insight learned | `nowledge_mem_save` | Structured save with `unit_type`, `labels`, `event_start`, `importance`. |
96
+ | "What was I doing last week?" | `nowledge_mem_timeline` | Activity feed grouped by day. Supports exact date ranges. |
97
+ | "How is X connected to Y?" | `nowledge_mem_connections` | Graph walk: edges, entities, EVOLVES chains, document provenance. |
98
+ | Need today's focus/priorities | `nowledge_mem_context` | Read Working Memory daily briefing. Supports section-level patch. |
99
+ | Memory has `sourceThreadId` | `nowledge_mem_thread_fetch` | Fetch full source conversation. Pagination via `offset` + `limit`. |
100
+ | "Find our discussion about X" | `nowledge_mem_thread_search` | Search past conversations by keyword. Returns matched snippets. |
101
+ | "Forget X" | `nowledge_mem_forget` | Delete by ID or search query. |
102
+
103
+ ### Session Lifecycle (Automatic Capture)
104
+
105
+ When sessions end, conversations are captured and optionally distilled. No user action needed.
106
+
107
+ ```mermaid
108
+ flowchart TD
109
+ A["Session lifecycle event"] --> B{"Event type"}
110
+
111
+ B -->|"agent_end"| C["Append messages to thread(idempotent, deduped)"]
112
+ B -->|"after_compaction"| D["Append messages to thread(checkpoint only)"]
113
+ B -->|"before_reset"| E["Append messages to thread(checkpoint only)"]
114
+
115
+ C --> F{"sessionDigest enabled+ enough messages+ cooldown passed?"}
116
+ F -->|"Yes"| G["LLM triage (~100 tokens):worth distilling?"]
117
+ F -->|"No"| H["Done — thread saved"]
118
+ G -->|"Decisions, insights,preferences found"| I["Full distillation ->structured memories(with sourceThreadId)"]
119
+ G -->|"Routine chat"| H
120
+
121
+ D --> H
122
+ E --> H
123
+ ```
124
+
125
+ **Key points:**
126
+ - Thread capture is **unconditional** — every conversation is saved and searchable via `nowledge_mem_thread_search`
127
+ - LLM distillation only runs at `agent_end`, not during compaction/reset checkpoints
128
+ - Distilled memories carry `sourceThreadId`, linking them back to the source conversation
129
+ - Cooldown (`digestMinInterval`, default 300s) prevents burst distillation
130
+
131
+ ### Progressive Retrieval (Memory -> Thread -> Messages)
132
+
133
+ Memories distilled from conversations carry a `sourceThreadId`. This creates a retrieval chain:
134
+
135
+ ```mermaid
136
+ flowchart TD
137
+ A["memory_search'PostgreSQL decision'"] --> B["Result includessourceThreadId"]
138
+ B --> C["nowledge_mem_thread_fetch(offset=0, limit=50)"]
139
+ C --> D["50 messageshasMore: true"]
140
+ D --> E["nowledge_mem_thread_fetch(offset=50, limit=50)"]
141
+ E --> F["Next page"]
142
+ ```
143
+
144
+ Direct conversation search also works:
145
+
146
+ ```mermaid
147
+ flowchart LR
148
+ G["nowledge_mem_thread_search 'database architecture'"] --> H["Threads with matched snippets"]
149
+ H --> I["nowledge_mem_thread_fetch(threadId from results)"]
150
+ I --> J["Full messages"]
151
+ ```
152
+
153
+ Two entry points:
154
+ 1. **From a memory** — `memory_search` or `memory_get` returns `sourceThreadId` -> fetch the source conversation
155
+ 2. **Direct search** — `nowledge_mem_thread_search` finds conversations by keyword -> fetch any result
156
+
157
+ ### Three Modes at a Glance
158
+
159
+ ```mermaid
160
+ flowchart LR
161
+ subgraph "default" ["Default (recommended)"]
162
+ direction TB
163
+ D1["Every turn: behavioral guidance (~50 tokens)"]
164
+ D2["Agent calls 9 tools on demand"]
165
+ D3["Session end: thread capture + LLM distillation"]
166
+ end
167
+
168
+ subgraph context ["Session Context"]
169
+ direction TB
170
+ C1["Every turn: guidance + Working Memory+ recalled memories (~1-2 KB)"]
171
+ C2["Agent calls 9 tools on demand"]
172
+ C3["Session end: thread capture + LLM distillation"]
173
+ end
174
+
175
+ subgraph minimal ["Minimal"]
176
+ direction TB
177
+ M1["Every turn: behavioral guidance (~50 tokens)"]
178
+ M2["Agent calls 9 tools on demand"]
179
+ M3["No automatic capture"]
180
+ end
181
+ ```
182
+
60
183
  ## Tools
61
184
 
62
185
  ### OpenClaw Memory Compatibility
63
186
 
64
187
  These satisfy the OpenClaw memory slot contract and activate the "Memory Recall" section in OpenClaw's system prompt.
65
188
 
66
- **memory_search** — Multi-signal recall using embedding, BM25, label match, graph signals, and recency decay. Returns structured source paths (`nowledgemem://memory/<id>`) for follow-up with `memory_get` or `nowledge_mem_connections`.
189
+ **memory_search** — Multi-signal recall using embedding, BM25, label match, graph signals, and recency decay. Returns structured source paths (`nowledgemem://memory/<id>`) for follow-up with `memory_get` or `nowledge_mem_connections`. Also returns relevant past conversation snippets (`relatedThreads`) and `sourceThreadId` (link to the conversation the memory was distilled from) when available.
67
190
 
68
- **memory_get** — Read a specific memory by ID or path. Supports `MEMORY.md` alias for Working Memory.
191
+ **memory_get** — Read a specific memory by ID or path. Supports `MEMORY.md` alias for Working Memory. Returns `sourceThreadId` when the memory was distilled from a conversation.
69
192
 
70
193
  ### Nowledge Mem Native
71
194
 
@@ -118,21 +241,44 @@ last_n_days: 7
118
241
 
119
242
  **nowledge_mem_forget** — Delete a memory by ID or search query. Supports user confirmation when multiple matches are found.
120
243
 
244
+ ### Thread Tools
245
+
246
+ **nowledge_mem_thread_search** — Search past conversations by keyword. Returns matched threads with message snippets and relevance scores. Use when the user asks about a past discussion or wants to find a conversation from a specific time.
247
+
248
+ **nowledge_mem_thread_fetch** — Fetch full messages from a conversation thread with pagination. Pass a `sourceThreadId` from memory results or a `threadId` from thread search. Supports `offset` and `limit` for progressive retrieval of long conversations.
249
+
250
+ ```
251
+ threadId: "openclaw-db-arch-a1b2c3"
252
+ offset: 0, limit: 50
253
+ -> Thread: "Database architecture discussion" (128 messages)
254
+ [user] We need to decide on the database for task events...
255
+ [assistant] Based on the requirements, PostgreSQL with JSONB...
256
+ ... (126 more messages, use offset=50 for next page)
257
+ ```
258
+
121
259
  ## Operating Modes
122
260
 
123
- The plugin supports three modes. The default (tool-only) gives the agent full access to all tools with zero token overhead.
261
+ The plugin supports three modes. Choose based on how much you want to guarantee versus how much token budget you're willing to spend.
262
+
263
+ | Mode | Config | Behavior | Tradeoff |
264
+ |------|--------|----------|----------|
265
+ | **Default** (recommended) | `sessionContext: false, sessionDigest: true` | Agent calls 9 tools on demand. Behavioral guidance every turn (~50 tokens). Conversations captured + distilled at session end. | Lowest cost. Agent decides when to search — usually smart, occasionally forgets. |
266
+ | **Session context** | `sessionContext: true` | Working Memory + relevant memories injected at prompt time, plus all 9 tools still available. | ~1-2 KB/turn. Guarantees context is always present. Best for short sessions or critical workflows. |
267
+ | **Minimal** | `sessionDigest: false` | Tool-only, no automatic capture. | Zero overhead beyond guidance. Use when you handle memory manually. |
268
+
269
+ **Which mode should you use?**
270
+
271
+ - **Most users**: start with default. The agent gets behavioral guidance nudging it to search before answering and save after deciding. It works well for most conversations.
272
+ - **Short sessions or critical accuracy**: enable `sessionContext`. This guarantees relevant memories are present from the first turn — the agent doesn't need to decide whether to search. The tradeoff is ~1-2 KB of context per turn.
273
+ - **Full manual control**: set `sessionDigest: false`. You control what gets saved (via `/remember` or `nowledge_mem_save`) and nothing is captured automatically.
124
274
 
125
- | Mode | Config | Behavior |
126
- |------|--------|----------|
127
- | **Tool-only** (default) | `autoRecall: false, autoCapture: false` | Agent calls tools on demand. Zero overhead. |
128
- | **Auto-recall** | `autoRecall: true` | Working Memory + relevant memories injected at session start. |
129
- | **Auto-capture** | `autoCapture: true` | Thread capture + LLM distillation at session end. |
275
+ ### Session Context (`sessionContext`, default: false)
130
276
 
131
- ### Auto-Recall (`autoRecall`, default: false)
277
+ When enabled, the plugin injects Working Memory and relevant search results at prompt time. The behavioral guidance automatically adjusts to tell the agent that context is already present — use `memory_search` only for specific follow-up queries, not broad recall. This prevents the agent from redundantly searching for the same context that was just injected.
132
278
 
133
- When enabled, the plugin injects Working Memory and relevant search results at session start. Useful for giving the agent immediate context without waiting for it to search proactively.
279
+ Useful for giving the agent immediate context without waiting for it to search proactively.
134
280
 
135
- ### Auto-Capture (`autoCapture`, default: false)
281
+ ### Session Digest (`sessionDigest`, default: true)
136
282
 
137
283
  When enabled, two things happen at `agent_end`, `after_compaction`, and `before_reset`:
138
284
 
@@ -140,6 +286,30 @@ When enabled, two things happen at `agent_end`, `after_compaction`, and `before_
140
286
 
141
287
  **2. LLM distillation (when worthwhile).** A lightweight LLM triage determines if the conversation has save-worthy content. If yes, a full distillation pass creates structured memories with types, labels, and temporal data. Language-agnostic — works in any language.
142
288
 
289
+ ## Design Decisions
290
+
291
+ Honest answers to common questions about how the memory system works.
292
+
293
+ **Does the agent always search before answering?**
294
+
295
+ No. The behavioral guidance nudges the agent to search, but doesn't force it. This is a deliberate tradeoff — forcing a search on every turn would add latency and cost for messages that don't need past context (like "hello" or "thanks"). In practice, modern LLMs follow behavioral guidance reliably for knowledge-related questions. If guaranteed recall matters for your use case, enable `sessionContext: true` — that injects relevant memories at prompt time, before the agent even processes your message.
296
+
297
+ **What stops the agent from saving duplicate memories?**
298
+
299
+ Two layers. First, the plugin checks for near-identical existing memories before every save. If a memory with ≥90% similarity already exists, the save is skipped and the existing memory is returned instead. Second, Nowledge Mem's Knowledge Agent runs in the background and handles deeper deduplication — it identifies semantic overlap across memories and links them via EVOLVES chains (replaces, enriches, confirms, or challenges). The plugin handles obvious duplicates; the Knowledge Agent handles subtle ones.
300
+
301
+ **When `sessionContext` is on, will the agent search again and get duplicate context?**
302
+
303
+ The behavioral guidance adjusts when `sessionContext` is enabled. Instead of "search with memory_search when prior context would help," it tells the agent "relevant memories have already been injected — use memory_search only for specific follow-up queries." This reduces redundant searches. The injected context and manual search results are in different XML blocks, so even if overlap occurs, it doesn't confuse the agent — it just sees the same fact confirmed from two sources.
304
+
305
+ **What happens to conversations I don't explicitly save?**
306
+
307
+ With `sessionDigest` enabled (the default), every conversation is saved as a searchable thread — you can find it later with `nowledge_mem_thread_search`. On top of that, a lightweight LLM triage checks if the conversation contained decisions, insights, or preferences worth keeping as structured memories. If yes, they're extracted with proper types, labels, and temporal context. If the conversation was routine ("fix this typo"), nothing extra is saved.
308
+
309
+ **Can memories be wrong or outdated?**
310
+
311
+ Yes. Memories are what you or the AI saved at a point in time. Nowledge Mem's EVOLVES chains track how understanding changes — a newer memory can supersede, enrich, or challenge an older one. The Knowledge Agent identifies these relationships automatically. When you search, the relevance scoring considers recency, so newer memories rank higher by default.
312
+
143
313
  ## Slash Commands
144
314
 
145
315
  | Command | Description |
@@ -159,9 +329,12 @@ openclaw nowledge-mem status
159
329
 
160
330
  | Key | Type | Default | Description |
161
331
  |-----|------|---------|-------------|
162
- | `autoRecall` | boolean | `false` | Inject Working Memory + relevant memories at session start |
163
- | `autoCapture` | boolean | `false` | Thread capture + LLM distillation at session end |
164
- | `maxRecallResults` | integer | `5` | Max memories to recall at session start (only used when autoRecall is enabled) |
332
+ | `sessionContext` | boolean | `false` | Inject Working Memory + relevant memories at prompt time |
333
+ | `sessionDigest` | boolean | `true` | Thread capture + LLM distillation at session end |
334
+ | `maxContextResults` | integer | `5` | Max memories to inject at prompt time (1–20, only used when sessionContext is enabled) |
335
+ | `digestMinInterval` | integer | `300` | Minimum seconds between session digests for the same thread (0–86400) |
336
+ | `apiUrl` | string | `""` | Remote server URL. Empty = local (`http://127.0.0.1:14242`) |
337
+ | `apiKey` | string | `""` | API key for remote access. Injected as `NMEM_API_KEY` env var — never logged |
165
338
 
166
339
  ## What Makes This Different
167
340
 
@@ -1,19 +1,23 @@
1
1
  {
2
2
  "id": "openclaw-nowledge-mem",
3
- "version": "0.3.0",
3
+ "version": "0.6.5",
4
4
  "kind": "memory",
5
5
  "uiHints": {
6
- "autoRecall": {
7
- "label": "Auto-recall at session start",
8
- "help": "Inject Working Memory and relevant memories at session start. Off by default \u2014 the agent can call memory_search on demand instead."
6
+ "sessionContext": {
7
+ "label": "Session context injection",
8
+ "help": "Inject Working Memory and relevant memories at prompt time. Off by default — the agent can call memory_search on demand instead."
9
9
  },
10
- "autoCapture": {
11
- "label": "Auto-capture at session end",
12
- "help": "Capture conversation threads and distill key memories via LLM at session end"
10
+ "sessionDigest": {
11
+ "label": "Session digest at end",
12
+ "help": "Capture conversation threads and distill key memories via LLM at session end. On by default — negligible cost, one triage call per session."
13
13
  },
14
- "maxRecallResults": {
15
- "label": "Max recall results",
16
- "help": "How many memories to inject for each recall cycle (1\u201320)"
14
+ "digestMinInterval": {
15
+ "label": "Minimum digest interval (seconds)",
16
+ "help": "Minimum seconds between session digests for the same thread. Prevents heartbeat-driven burst captures. Set to 0 for no limit."
17
+ },
18
+ "maxContextResults": {
19
+ "label": "Max context results",
20
+ "help": "How many memories to inject for each context cycle (1–20)"
17
21
  },
18
22
  "apiUrl": {
19
23
  "label": "Server URL (remote mode)",
@@ -21,29 +25,36 @@
21
25
  },
22
26
  "apiKey": {
23
27
  "label": "API key (remote mode)",
24
- "help": "Required when connecting to a remote server. Never logged or passed as a CLI argument \u2014 injected as NMEM_API_KEY env var only.",
28
+ "help": "Required when connecting to a remote server. Never logged or passed as a CLI argument — injected as NMEM_API_KEY env var only.",
25
29
  "secret": true
26
30
  }
27
31
  },
28
32
  "configSchema": {
29
33
  "type": "object",
30
34
  "properties": {
31
- "autoRecall": {
35
+ "sessionContext": {
32
36
  "type": "boolean",
33
37
  "default": false,
34
- "description": "Inject Working Memory and recalled memories at session start. Off by default \u2014 the agent queries memory on demand via tools."
38
+ "description": "Inject Working Memory and recalled memories at prompt time. Off by default — the agent queries memory on demand via tools."
35
39
  },
36
- "autoCapture": {
40
+ "sessionDigest": {
37
41
  "type": "boolean",
38
- "default": false,
39
- "description": "Capture conversation threads and distill key memories via LLM at session end"
42
+ "default": true,
43
+ "description": "Capture conversation threads and distill key memories via LLM at session end. On by default."
44
+ },
45
+ "digestMinInterval": {
46
+ "type": "integer",
47
+ "default": 300,
48
+ "minimum": 0,
49
+ "maximum": 86400,
50
+ "description": "Minimum seconds between session digests for the same thread (0 = no limit). Prevents heartbeat-driven burst captures."
40
51
  },
41
- "maxRecallResults": {
52
+ "maxContextResults": {
42
53
  "type": "integer",
43
54
  "default": 5,
44
55
  "minimum": 1,
45
56
  "maximum": 20,
46
- "description": "Maximum memories to recall at session start (only used when autoRecall is enabled)"
57
+ "description": "Maximum memories to inject at prompt time (only used when sessionContext is enabled)"
47
58
  },
48
59
  "apiUrl": {
49
60
  "type": "string",
@@ -53,7 +64,7 @@
53
64
  "apiKey": {
54
65
  "type": "string",
55
66
  "default": "",
56
- "description": "API key for remote access. Stored in plugin config, injected as NMEM_API_KEY env var \u2014 never logged."
67
+ "description": "API key for remote access. Stored in plugin config, injected as NMEM_API_KEY env var — never logged."
57
68
  }
58
69
  },
59
70
  "additionalProperties": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowledge/openclaw-nowledge-mem",
3
- "version": "0.3.0",
3
+ "version": "0.6.5",
4
4
  "type": "module",
5
5
  "description": "Nowledge Mem memory plugin for OpenClaw, local-first personal knowledge base",
6
6
  "author": {