@joshuaswarren/openclaw-engram 8.0.1 → 8.0.3
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/README.md +49 -822
- package/dist/index.js +107 -7
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,346 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
A local-first memory plugin for [OpenClaw](https://github.com/openclaw/openclaw) that gives AI agents persistent, searchable long-term memory across conversations.
|
|
4
4
|
|
|
5
|
-
Engram uses **LLM-powered extraction**
|
|
5
|
+
Engram uses **LLM-powered extraction** to identify what's worth remembering, stores memories as plain **markdown files** on disk, and retrieves relevant context via **[QMD](https://github.com/tobi/qmd)** hybrid search (BM25 + vector + reranking).
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
Most AI memory systems are either too noisy (store everything) or too lossy (store nothing useful). Engram takes a different approach:
|
|
10
|
-
|
|
11
|
-
- **Signal detection first** -- A fast local regex scan classifies each turn before any API call happens. High-signal turns (corrections, preferences, identity statements) trigger immediate extraction; low-signal turns are batched.
|
|
12
|
-
- **Structured extraction** -- An LLM analyzes buffered turns and extracts typed memories (facts, preferences, corrections, entities, decisions, relationships, principles, commitments, moments, skills) with confidence scores.
|
|
13
|
-
- **Automatic consolidation** -- Periodic consolidation passes merge duplicates, update entity profiles, refresh the behavioral profile, and expire stale memories.
|
|
14
|
-
- **Local-first storage** -- All memories are plain markdown files with YAML frontmatter. No database, no vendor lock-in. Grep them, version them, back them up however you like.
|
|
15
|
-
- **Privacy by default** -- Memories never leave your machine unless you choose to sync them. The LLM extraction call is the only external API call.
|
|
16
|
-
|
|
17
|
-
## Features
|
|
18
|
-
|
|
19
|
-
### Core Features
|
|
20
|
-
- **10 memory categories**: fact, preference, correction, entity, decision, relationship, principle, commitment, moment, skill
|
|
21
|
-
- **Confidence tiers**: explicit (0.95-1.0), implied (0.70-0.94), inferred (0.40-0.69), speculative (0.00-0.39)
|
|
22
|
-
- **TTL on speculative memories**: Auto-expire after 30 days if unconfirmed
|
|
23
|
-
- **Lineage tracking**: Memories track their parent IDs through consolidation merges and updates
|
|
24
|
-
- **Entity profiles**: Accumulates facts about people, projects, tools, and companies into per-entity files, with automatic name normalization and periodic deduplication
|
|
25
|
-
- **Behavioral profile**: A living `profile.md` that evolves as the system learns about the user, with automatic cap and pruning to control token usage
|
|
26
|
-
- **Identity reflection**: Optional self-reflection that helps the agent improve over sessions
|
|
27
|
-
- **Question generation**: Generates 1-3 curiosity questions per extraction to drive deeper engagement
|
|
28
|
-
- **Commitment lifecycle**: Tracks promises and deadlines with configurable decay (default 90 days)
|
|
29
|
-
- **Auto-consolidation**: IDENTITY.md reflections are automatically summarized when they exceed 8KB
|
|
30
|
-
- **Smart buffer**: Configurable trigger logic (signal-based, turn count, or time-based)
|
|
31
|
-
- **QMD integration**: Hybrid search with BM25, vector embeddings, and reranking
|
|
32
|
-
- **Graceful degradation**: Works without QMD (falls back to direct file reads) and without an API key (retrieval-only mode)
|
|
33
|
-
- **Portability**: Import/export/backup your memory store via CLI (v2.3)
|
|
34
|
-
- **CLI**: Search, inspect, and manage memories from the command line
|
|
35
|
-
- **Agent tools**: `memory_search`, `memory_store`, `memory_profile`, `memory_entities`, `memory_promote`
|
|
36
|
-
|
|
37
|
-
### v1.2.0 Advanced Features
|
|
38
|
-
|
|
39
|
-
All advanced features are **disabled by default** for gradual adoption. Enable them in your config as needed.
|
|
40
|
-
|
|
41
|
-
#### Importance Scoring (Zero-LLM)
|
|
42
|
-
- **Local heuristic scoring** at extraction time — no API calls
|
|
43
|
-
- Five tiers: `critical` (0.9-1.0), `high` (0.7-0.9), `normal` (0.4-0.7), `low` (0.2-0.4), `trivial` (0.0-0.2)
|
|
44
|
-
- Scores based on: explicit importance markers, personal info, instructions, emotional content, factual density
|
|
45
|
-
- Extracts salient keywords for improved search relevance
|
|
46
|
-
- Used for **ranking** (not exclusion) — all memories are still stored and searchable
|
|
47
|
-
|
|
48
|
-
#### Access Tracking
|
|
49
|
-
- Tracks `accessCount` and `lastAccessed` for each memory
|
|
50
|
-
- Batched updates during consolidation (zero retrieval latency impact)
|
|
51
|
-
- Enables "working set" prioritization — frequently accessed memories surface higher
|
|
52
|
-
- CLI: `openclaw engram access` to view most accessed memories
|
|
53
|
-
|
|
54
|
-
#### Recency Boosting
|
|
55
|
-
- Recent memories ranked higher in search results
|
|
56
|
-
- Configurable weight (0-1, default 0.2)
|
|
57
|
-
- Exponential decay with 7-day half-life
|
|
58
|
-
|
|
59
|
-
#### Automatic Chunking
|
|
60
|
-
- Sentence-boundary splitting for long memories (>150 tokens)
|
|
61
|
-
- Target ~200 tokens per chunk with 2-sentence overlap
|
|
62
|
-
- Each chunk maintains `parentId` and `chunkIndex` for context reconstruction
|
|
63
|
-
- Preserves coherent thoughts — never splits mid-sentence
|
|
64
|
-
|
|
65
|
-
#### Contradiction Detection
|
|
66
|
-
- QMD similarity search finds candidate conflicts (fast, cheap)
|
|
67
|
-
- LLM verification confirms actual contradictions (prevents false positives)
|
|
68
|
-
- Auto-resolve when confidence > 0.9
|
|
69
|
-
- Full audit trail: old memory marked `status: superseded` with `supersededBy` link
|
|
70
|
-
- Nothing is deleted — superseded memories remain searchable explicitly
|
|
71
|
-
|
|
72
|
-
#### Memory Linking (Knowledge Graph)
|
|
73
|
-
- Typed relationships: `follows`, `references`, `contradicts`, `supports`, `related`
|
|
74
|
-
- LLM suggests links during extraction based on semantic connections
|
|
75
|
-
- Links stored in frontmatter with strength scores (0-1)
|
|
76
|
-
- Enables graph traversal between related memories
|
|
77
|
-
|
|
78
|
-
#### Conversation Threading
|
|
79
|
-
- Auto-detect thread boundaries (session change or 30-minute gap)
|
|
80
|
-
- Auto-generate thread titles from top TF-IDF keywords
|
|
81
|
-
- Group memories into conversation threads for context reconstruction
|
|
82
|
-
- CLI: `openclaw engram threads` to view threads
|
|
83
|
-
|
|
84
|
-
#### Memory Summarization
|
|
85
|
-
- Triggered when memory count exceeds threshold (default 1000)
|
|
86
|
-
- Compresses old, low-importance, unprotected memories into summaries
|
|
87
|
-
- **Archive, not delete** — source memories marked `status: archived`, still searchable
|
|
88
|
-
- Protected: recent memories, high-importance, entities, commitments/preferences/decisions
|
|
89
|
-
- Summaries stored in `summaries/` directory
|
|
90
|
-
|
|
91
|
-
#### Topic Extraction
|
|
92
|
-
- TF-IDF analysis of the entire memory corpus
|
|
93
|
-
- Extracts top N topics (default 50) during consolidation
|
|
94
|
-
- Stored in `state/topics.json`
|
|
95
|
-
- CLI: `openclaw engram topics` to view extracted topics
|
|
96
|
-
|
|
97
|
-
### v2.2 Advanced Retrieval
|
|
98
|
-
|
|
99
|
-
All v2.2 retrieval features are **disabled by default**. Enable them only if you can tolerate a small latency increase.
|
|
100
|
-
|
|
101
|
-
- **Heuristic query expansion** (`queryExpansionEnabled`): Runs a few deterministic, cheap expanded queries (no LLM calls) and merges results.
|
|
102
|
-
- **LLM re-ranking** (`rerankEnabled`): Re-scores the top N retrieved memories using a short, timeboxed request.
|
|
103
|
-
- Default mode: **local-only** (`rerankProvider: "local"`), fail-open on errors/timeouts.
|
|
104
|
-
- **Note:** If QMD is enabled (`qmdEnabled: true`), QMD's `query` command already includes built-in reranking via its bundled reranker model. Enabling `rerankEnabled` on top of QMD results in **redundant double reranking**, which adds latency for marginal quality gain. **Recommendation: keep `rerankEnabled: false` when using QMD.**
|
|
105
|
-
- **Feedback loop** (`feedbackEnabled` + `memory_feedback` tool): Store thumbs up/down locally and apply it as a small ranking bias.
|
|
106
|
-
- **Negative examples** (`negativeExamplesEnabled` + `memory_feedback_last_recall` tool): Track retrieved-but-not-useful memories and apply a small ranking penalty.
|
|
107
|
-
- **Slow query log** (`slowLogEnabled` + `slowLogThresholdMs`): Logs durations and metadata (never content) for local LLM and QMD operations.
|
|
108
|
-
|
|
109
|
-
### v2.3 Import / Export / Backup
|
|
110
|
-
|
|
111
|
-
Engram supports **portable exports** and **safe backups** via CLI:
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
openclaw engram export --format json --out /tmp/engram-export
|
|
115
|
-
openclaw engram export --format sqlite --out /tmp/engram.sqlite
|
|
116
|
-
openclaw engram export --format md --out /tmp/engram-md
|
|
117
|
-
|
|
118
|
-
openclaw engram import --from /tmp/engram-export --format auto
|
|
119
|
-
openclaw engram backup --out-dir /tmp/engram-backups --retention-days 14
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
If namespaces are enabled (v3.0+), the CLI accepts `--namespace <ns>` for export/import/backup.
|
|
123
|
-
|
|
124
|
-
Details: `docs/import-export.md`
|
|
125
|
-
|
|
126
|
-
### v2.4 Context Retention Hardening
|
|
127
|
-
|
|
128
|
-
- **Extended hourly summaries** (structured topics/decisions/action items/rejections) are optional:
|
|
129
|
-
- Config: `hourlySummariesExtendedEnabled`, `hourlySummariesIncludeToolStats`
|
|
130
|
-
- **Conversation semantic recall hook** (optional): index transcript chunks and inject top-K relevant past chunks:
|
|
131
|
-
- Config: `conversationIndexEnabled`, `conversationIndexQmdCollection`, `conversationRecallTopK`, `conversationIndexMinUpdateIntervalMs`, `conversationIndexEmbedOnUpdate`
|
|
132
|
-
- Tool: `conversation_index_update` (optional `embed: true` override)
|
|
133
|
-
|
|
134
|
-
Details: `docs/context-retention.md`
|
|
135
|
-
|
|
136
|
-
### v3.0 Namespaces (Multi-Agent Memory)
|
|
137
|
-
|
|
138
|
-
Optional namespaces let multiple agents share a memory store with isolation:
|
|
139
|
-
|
|
140
|
-
- Config: `namespacesEnabled`, `defaultNamespace`, `sharedNamespace`, `namespacePolicies`
|
|
141
|
-
- Tooling: `memory_store` supports `namespace`; `memory_promote` copies curated items into the shared namespace.
|
|
142
|
-
|
|
143
|
-
Details: `docs/namespaces.md`
|
|
144
|
-
|
|
145
|
-
### v4.0 Shared Context (Cross-Agent Shared Intelligence)
|
|
146
|
-
|
|
147
|
-
Optional shared-context is a **file-based shared brain** (priorities, agent outputs, feedback, roundtables):
|
|
148
|
-
|
|
149
|
-
- Config: `sharedContextEnabled`, `sharedContextDir`, `sharedContextMaxInjectChars`
|
|
150
|
-
- Tools: `shared_context_write_output`, `shared_priorities_append`, `shared_feedback_record`, `shared_context_curate_daily`
|
|
151
|
-
|
|
152
|
-
Details: `docs/shared-context.md`
|
|
153
|
-
|
|
154
|
-
### v5.0 Compounding Engine
|
|
155
|
-
|
|
156
|
-
Optional compounding turns shared feedback into persistent learning:
|
|
157
|
-
|
|
158
|
-
- Writes: `memoryDir/compounding/weekly/<YYYY-Www>.md`, `memoryDir/compounding/mistakes.json`
|
|
159
|
-
- Tool: `compounding_weekly_synthesize`
|
|
160
|
-
- Injection: `compoundingInjectEnabled` (default true when compounding is enabled)
|
|
161
|
-
|
|
162
|
-
Details: `docs/compounding.md`
|
|
163
|
-
|
|
164
|
-
### v6.0 Fact Deduplication & Archival
|
|
165
|
-
|
|
166
|
-
Two features to keep the memory store lean and fast as it grows:
|
|
167
|
-
|
|
168
|
-
#### Content-Hash Deduplication
|
|
169
|
-
|
|
170
|
-
Prevents storing semantically identical facts. Before writing any new fact, Engram computes a normalized SHA-256 hash of the content (lowercase, strip punctuation, collapse whitespace) and checks it against a persistent index. Duplicates are silently skipped.
|
|
171
|
-
|
|
172
|
-
- **Zero false positives** — exact content match only (after normalization)
|
|
173
|
-
- **Persistent index** — stored as `state/fact-hashes.txt`, survives restarts
|
|
174
|
-
- **Seeding** — on first enable, the index auto-loads from existing facts on disk
|
|
175
|
-
- Config: `factDeduplicationEnabled` (default `true`)
|
|
176
|
-
|
|
177
|
-
#### Fact Archival
|
|
178
|
-
|
|
179
|
-
Automatically moves old, low-importance, rarely-accessed facts out of the hot search index into an `archive/` directory. Archived facts are still on disk but excluded from QMD queries, keeping retrieval fast.
|
|
180
|
-
|
|
181
|
-
Archival runs during the periodic consolidation pass. A fact is archived when **all** of these are true:
|
|
182
|
-
- Age exceeds `factArchivalAgeDays` (default 90)
|
|
183
|
-
- Importance score is below `factArchivalMaxImportance` (default 0.3)
|
|
184
|
-
- Access count is at or below `factArchivalMaxAccessCount` (default 2)
|
|
185
|
-
- Category is not in `factArchivalProtectedCategories` (default: commitment, preference, decision, principle)
|
|
186
|
-
- Status is `active` (not already superseded/archived)
|
|
187
|
-
- Not a correction memory
|
|
188
|
-
|
|
189
|
-
Config: `factArchivalEnabled` (default `false`), plus the threshold settings above.
|
|
190
|
-
|
|
191
|
-
## Architecture
|
|
192
|
-
|
|
193
|
-
```
|
|
194
|
-
Conversation turn arrives
|
|
195
|
-
|
|
|
196
|
-
v
|
|
197
|
-
Signal scan (local regex, <10ms, free)
|
|
198
|
-
|
|
|
199
|
-
v
|
|
200
|
-
Append to smart buffer
|
|
201
|
-
|
|
|
202
|
-
v
|
|
203
|
-
Trigger check:
|
|
204
|
-
HIGH signal? --> Extract NOW (single LLM call)
|
|
205
|
-
Buffer >= N? --> Extract BATCH
|
|
206
|
-
Time > T? --> Extract BATCH
|
|
207
|
-
else --> Keep buffering
|
|
208
|
-
|
|
|
209
|
-
v
|
|
210
|
-
If extracted: content-hash dedup check (skip duplicates)
|
|
211
|
-
|
|
|
212
|
-
v
|
|
213
|
-
Write new markdown files to disk
|
|
214
|
-
|
|
|
215
|
-
v
|
|
216
|
-
Every Nth extraction: Consolidation pass
|
|
217
|
-
- Merge/dedup memories
|
|
218
|
-
- Merge fragmented entity files
|
|
219
|
-
- Update entity profiles
|
|
220
|
-
- Update behavioral profile (with cap enforcement)
|
|
221
|
-
- Clean expired commitments and TTL memories
|
|
222
|
-
- Archive old, low-importance facts (v6.0)
|
|
223
|
-
- Auto-consolidate identity reflections
|
|
224
|
-
|
|
|
225
|
-
v
|
|
226
|
-
Background: qmd update (re-index new files)
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
Performance note for conversation indexing:
|
|
230
|
-
- `conversation_index_update` now runs `qmd update` only by default.
|
|
231
|
-
- `qmd embed` is optional (`conversationIndexEmbedOnUpdate: true` or tool param `embed: true`).
|
|
232
|
-
- Re-indexing is min-interval gated per session (`conversationIndexMinUpdateIntervalMs`, default 15m).
|
|
233
|
-
|
|
234
|
-
### Retrieval Flow
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
Agent session starts
|
|
238
|
-
|
|
|
239
|
-
v
|
|
240
|
-
Read profile.md directly (free, instant)
|
|
241
|
-
|
|
|
242
|
-
v
|
|
243
|
-
QMD search memory collection (relevant memories)
|
|
244
|
-
|
|
|
245
|
-
v
|
|
246
|
-
QMD search global collections (workspace context)
|
|
247
|
-
|
|
|
248
|
-
v
|
|
249
|
-
Optionally inject highest-priority open question
|
|
250
|
-
|
|
|
251
|
-
v
|
|
252
|
-
Combine and inject into system prompt
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
## Hourly Summaries (Cron)
|
|
256
|
-
|
|
257
|
-
Engram can generate **hourly summaries** of conversation activity, written to disk under the configured `memoryDir` summaries folder.
|
|
258
|
-
|
|
259
|
-
In most installs, the safest setup is to drive this via OpenClaw cron using an **agent turn** (not a tool call directly):
|
|
260
|
-
- `sessionTarget: "isolated"`
|
|
261
|
-
- `payload.kind: "agentTurn"` that calls `memory_summarize_hourly`
|
|
262
|
-
- `delivery.mode: "none"` (so it never posts to Discord)
|
|
263
|
-
|
|
264
|
-
Why: some OpenClaw installations restrict `sessionTarget: "main"` to `payload.kind: "systemEvent"` only. If you configure `main` + `toolCall`, it may be repeatedly skipped and summaries will silently stop.
|
|
265
|
-
|
|
266
|
-
## Storage Layout
|
|
267
|
-
|
|
268
|
-
All memories are stored as markdown files with YAML frontmatter:
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
~/.openclaw/workspace/memory/local/
|
|
272
|
-
├── profile.md # Living behavioral profile (auto-updated)
|
|
273
|
-
├── entities/ # One markdown file per tracked entity
|
|
274
|
-
│ ├── person-jane-doe.md
|
|
275
|
-
│ ├── project-my-app.md
|
|
276
|
-
│ └── tool-qmd.md
|
|
277
|
-
├── facts/ # Memory entries organized by date
|
|
278
|
-
│ └── YYYY-MM-DD/
|
|
279
|
-
│ ├── fact-1738789200000-a1b2.md
|
|
280
|
-
│ └── preference-1738789200000-c3d4.md
|
|
281
|
-
├── corrections/ # High-weight correction memories
|
|
282
|
-
│ └── correction-1738789200000-e5f6.md
|
|
283
|
-
├── archive/ # Archived low-value facts (v6.0)
|
|
284
|
-
│ └── YYYY-MM-DD/
|
|
285
|
-
│ └── fact-1738789200000-a1b2.md
|
|
286
|
-
├── questions/ # Generated curiosity questions
|
|
287
|
-
│ └── q-m1abc-xy.md
|
|
288
|
-
├── threads/ # Conversation threads (v1.2.0)
|
|
289
|
-
│ └── thread-1738789200000-a1b2.json
|
|
290
|
-
├── summaries/ # Memory summaries (v1.2.0)
|
|
291
|
-
│ └── summary-1738789200000-a1b2.json
|
|
292
|
-
├── config/
|
|
293
|
-
│ └── aliases.json # Entity name aliases
|
|
294
|
-
└── state/
|
|
295
|
-
├── buffer.json # Current unbatched turns (survives restarts)
|
|
296
|
-
├── meta.json # Extraction count, timestamps, totals
|
|
297
|
-
├── topics.json # Extracted topics (v1.2.0)
|
|
298
|
-
└── fact-hashes.txt # Content-hash dedup index (v6.0)
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### Memory File Format
|
|
302
|
-
|
|
303
|
-
Each memory file uses YAML frontmatter:
|
|
304
|
-
|
|
305
|
-
```yaml
|
|
306
|
-
---
|
|
307
|
-
id: fact-1738789200000-a1b2
|
|
308
|
-
category: fact
|
|
309
|
-
created: 2026-02-05T12:00:00.000Z
|
|
310
|
-
updated: 2026-02-05T12:00:00.000Z
|
|
311
|
-
source: extraction
|
|
312
|
-
confidence: 0.85
|
|
313
|
-
confidenceTier: implied
|
|
314
|
-
tags: ["tools", "preferences"]
|
|
315
|
-
entityRef: tool-qmd
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
QMD supports hybrid search combining BM25 and vector embeddings with reranking.
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## Installation
|
|
322
|
-
|
|
323
|
-
### Prerequisites
|
|
324
|
-
|
|
325
|
-
- [OpenClaw](https://github.com/openclaw/openclaw) gateway
|
|
326
|
-
- An OpenAI API key (for extraction; retrieval works without one)
|
|
327
|
-
- [QMD](https://github.com/tobi/qmd) (optional, for hybrid search)
|
|
328
|
-
|
|
329
|
-
### Quick Start (Recommended: npm via OpenClaw)
|
|
7
|
+
## Quick Install
|
|
330
8
|
|
|
331
9
|
```bash
|
|
332
|
-
# Install from npm (records install provenance in openclaw.json.plugins.installs)
|
|
333
10
|
openclaw plugins install @joshuaswarren/openclaw-engram --pin
|
|
334
11
|
```
|
|
335
12
|
|
|
336
|
-
|
|
13
|
+
Enable in `openclaw.json`:
|
|
337
14
|
|
|
338
15
|
```jsonc
|
|
339
16
|
{
|
|
340
17
|
"plugins": {
|
|
341
18
|
"allow": ["openclaw-engram"],
|
|
342
|
-
"slots": {
|
|
343
|
-
"memory": "openclaw-engram"
|
|
344
|
-
},
|
|
19
|
+
"slots": { "memory": "openclaw-engram" },
|
|
345
20
|
"entries": {
|
|
346
21
|
"openclaw-engram": {
|
|
347
22
|
"enabled": true,
|
|
@@ -354,514 +29,66 @@ Then enable and configure in `openclaw.json`:
|
|
|
354
29
|
}
|
|
355
30
|
```
|
|
356
31
|
|
|
357
|
-
Reload
|
|
358
|
-
|
|
359
|
-
```bash
|
|
360
|
-
kill -USR1 $(pgrep openclaw-gateway)
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
### Developer Install (from Git)
|
|
364
|
-
|
|
365
|
-
Use this only if you are actively developing the plugin.
|
|
366
|
-
|
|
367
|
-
```bash
|
|
368
|
-
# Clone into the OpenClaw extensions directory
|
|
369
|
-
git clone https://github.com/joshuaswarren/openclaw-engram.git \
|
|
370
|
-
~/.openclaw/extensions/openclaw-engram
|
|
371
|
-
|
|
372
|
-
# Install dependencies and build
|
|
373
|
-
cd ~/.openclaw/extensions/openclaw-engram
|
|
374
|
-
npm ci
|
|
375
|
-
npm run build
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
### Set Up QMD Collection (Optional)
|
|
379
|
-
|
|
380
|
-
If you have QMD installed, add a collection pointing at the memory directory. Add to `~/.config/qmd/index.yml`:
|
|
381
|
-
|
|
382
|
-
```yaml
|
|
383
|
-
openclaw-engram:
|
|
384
|
-
path: ~/.openclaw/workspace/memory/local
|
|
385
|
-
extensions: [.md]
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
Then index:
|
|
389
|
-
|
|
390
|
-
```bash
|
|
391
|
-
qmd update && qmd embed
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### Recommended QMD Patches (as of 2026-02-14)
|
|
395
|
-
|
|
396
|
-
The following upstream QMD pull requests contain important performance and stability fixes that have not yet been merged. We recommend applying them locally to your QMD installation at `~/.bun/install/global/node_modules/qmd/`:
|
|
397
|
-
|
|
398
|
-
1. **[PR #166](https://github.com/tobi/qmd/pull/166) — HTTP daemon crash fix** (fixes [#163](https://github.com/tobi/qmd/issues/163))
|
|
399
|
-
- The HTTP daemon (`qmd mcp --http --daemon`) crashes on the second MCP request due to transport reuse.
|
|
400
|
-
- **Fix**: In `src/mcp.ts`, add `sessionIdGenerator: () => crypto.randomUUID()` to the `WebStandardStreamableHTTPServerTransport` constructor.
|
|
401
|
-
- Without this fix, the daemon is unusable for sequential requests.
|
|
402
|
-
|
|
403
|
-
2. **[PR #112](https://github.com/tobi/qmd/pull/112) — Model override environment variables**
|
|
404
|
-
- Adds `QMD_EMBED_MODEL`, `QMD_GENERATE_MODEL`, `QMD_RERANK_MODEL`, and `QMD_MODEL_CACHE_DIR` env vars.
|
|
405
|
-
- Allows swapping in smaller/faster models at runtime (e.g., Jina Reranker v1-tiny for 185x faster cold-start reranking).
|
|
406
|
-
- **Fix**: In `src/llm.ts`, change the `LlamaCpp` constructor to check `process.env.QMD_*` vars as fallback between config and defaults.
|
|
407
|
-
|
|
408
|
-
3. **[PR #117](https://github.com/tobi/qmd/pull/117) — SQLite pathological join fix**
|
|
409
|
-
- SQLite may choose a disastrous join order for FTS queries with collection filters, making `qmd search -c <collection>` extremely slow on large indexes.
|
|
410
|
-
- **Fix**: In `src/store.ts`, change `JOIN` to `CROSS JOIN` in `searchFTS()` and move join predicates into the `WHERE` clause to preserve left-to-right evaluation order starting from the FTS MATCH.
|
|
411
|
-
- Particularly important for large collections (90K+ files like the engram memory store).
|
|
412
|
-
|
|
413
|
-
Check [tobi/qmd](https://github.com/tobi/qmd) periodically — once these PRs are merged upstream, a simple `bun install -g github:tobi/qmd` will include them and these local patches can be removed.
|
|
414
|
-
|
|
415
|
-
### Restart the Gateway
|
|
32
|
+
Reload:
|
|
416
33
|
|
|
417
34
|
```bash
|
|
418
35
|
kill -USR1 $(pgrep openclaw-gateway)
|
|
419
36
|
```
|
|
420
37
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
```bash
|
|
424
|
-
tail -f ~/.openclaw/logs/gateway.log
|
|
425
|
-
# Should see: [gateway] openclaw-engram: started
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
## Configuration
|
|
429
|
-
|
|
430
|
-
All settings are defined in `openclaw.json` under `plugins.entries.openclaw-engram.config`:
|
|
431
|
-
|
|
432
|
-
For a full v2.3-v5 setup (including cron and QMD conversation-index collections) and tuning guidance, see:
|
|
433
|
-
- `docs/README.md` (docs map, v8 reorg entrypoint)
|
|
434
|
-
- `docs/setup-config-tuning.md`
|
|
435
|
-
- `docs/import-export.md`
|
|
436
|
-
- `docs/context-retention.md`
|
|
437
|
-
- `docs/namespaces.md`
|
|
438
|
-
- `docs/shared-context.md`
|
|
439
|
-
- `docs/compounding.md`
|
|
440
|
-
|
|
441
|
-
Bootstrap config path override (for service environments) can be set via env var:
|
|
442
|
-
- `OPENCLAW_ENGRAM_CONFIG_PATH=/absolute/path/to/openclaw.json`
|
|
443
|
-
- Fallback: `OPENCLAW_CONFIG_PATH`
|
|
444
|
-
|
|
445
|
-
### Core Settings
|
|
446
|
-
|
|
447
|
-
| Setting | Default | Description |
|
|
448
|
-
|---------|---------|-------------|
|
|
449
|
-
| `openaiApiKey` | `(env fallback)` | OpenAI API key or `${ENV_VAR}` reference |
|
|
450
|
-
| `model` | `gpt-5.2` | OpenAI model for extraction/consolidation |
|
|
451
|
-
| `reasoningEffort` | `low` | Reasoning effort: `none`, `low`, `medium`, `high` |
|
|
452
|
-
| `memoryDir` | `~/.openclaw/workspace/memory/local` | Memory storage directory |
|
|
453
|
-
| `workspaceDir` | `~/.openclaw/workspace` | Workspace directory (for IDENTITY.md) |
|
|
454
|
-
| `debug` | `false` | Enable debug logging |
|
|
455
|
-
|
|
456
|
-
### File Hygiene (Memory File Limits / Truncation Risk)
|
|
457
|
-
|
|
458
|
-
OpenClaw may bootstrap workspace markdown files (for example `IDENTITY.md`, `MEMORY.md`) into the prompt on every message.
|
|
459
|
-
If those files become large, they can be silently truncated by the gateway's bootstrap budget, which causes "memory loss" without an explicit error.
|
|
460
|
-
|
|
461
|
-
Engram can optionally:
|
|
462
|
-
- Lint selected workspace files and warn when they are approaching a configured size budget.
|
|
463
|
-
- Rotate oversized markdown files into an archive directory, replacing the original with a lean index plus a small tail excerpt for continuity.
|
|
464
|
-
|
|
465
|
-
This is **off by default** because it can modify workspace files.
|
|
466
|
-
|
|
467
|
-
Example config:
|
|
468
|
-
|
|
469
|
-
```json
|
|
470
|
-
{
|
|
471
|
-
"fileHygiene": {
|
|
472
|
-
"enabled": true,
|
|
473
|
-
"lintEnabled": true,
|
|
474
|
-
"lintPaths": ["IDENTITY.md", "MEMORY.md"],
|
|
475
|
-
"lintBudgetBytes": 20000,
|
|
476
|
-
"lintWarnRatio": 0.8,
|
|
477
|
-
"rotateEnabled": true,
|
|
478
|
-
"rotatePaths": ["IDENTITY.md"],
|
|
479
|
-
"rotateMaxBytes": 18000,
|
|
480
|
-
"rotateKeepTailChars": 2000,
|
|
481
|
-
"archiveDir": ".engram-archive",
|
|
482
|
-
"runMinIntervalMs": 300000,
|
|
483
|
-
"warningsLogEnabled": false
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### Buffer & Trigger Settings
|
|
489
|
-
|
|
490
|
-
| Setting | Default | Description |
|
|
491
|
-
|---------|---------|-------------|
|
|
492
|
-
| `triggerMode` | `smart` | `smart`, `every_n`, or `time_based` |
|
|
493
|
-
| `bufferMaxTurns` | `5` | Max buffered turns before forced extraction |
|
|
494
|
-
| `bufferMaxMinutes` | `15` | Max minutes before forced extraction |
|
|
495
|
-
| `highSignalPatterns` | `[]` | Custom regex patterns for immediate extraction |
|
|
496
|
-
| `consolidateEveryN` | `3` | Run consolidation every N extractions |
|
|
497
|
-
|
|
498
|
-
### Retrieval Settings
|
|
499
|
-
|
|
500
|
-
| Setting | Default | Description |
|
|
501
|
-
|---------|---------|-------------|
|
|
502
|
-
| `maxMemoryTokens` | `2000` | Max tokens injected into system prompt |
|
|
503
|
-
| `qmdEnabled` | `true` | Use QMD for hybrid search |
|
|
504
|
-
| `qmdCollection` | `openclaw-engram` | QMD collection name |
|
|
505
|
-
| `qmdMaxResults` | `8` | Max QMD results per search |
|
|
506
|
-
| `qmdPath` | `(auto)` | Optional absolute path to `qmd` binary (bypasses PATH discovery) |
|
|
507
|
-
|
|
508
|
-
### v8.0 Phase 1 (Experimental, Token-Budget Focused)
|
|
509
|
-
|
|
510
|
-
All options below are safe to leave disabled initially; enable incrementally.
|
|
511
|
-
|
|
512
|
-
| Setting | Default | Description |
|
|
513
|
-
|---------|---------|-------------|
|
|
514
|
-
| `recallPlannerEnabled` | `true` | Lightweight retrieve-vs-think gating (`no_recall`/`minimal`/`full`/`graph_mode`) |
|
|
515
|
-
| `recallPlannerMaxQmdResultsMinimal` | `4` | QMD cap when planner selects `minimal` |
|
|
516
|
-
| `intentRoutingEnabled` | `false` | Write intent metadata (goal/action/entityTypes) and boost compatible recalls |
|
|
517
|
-
| `intentRoutingBoost` | `0.12` | Maximum additive score boost from intent compatibility |
|
|
518
|
-
| `verbatimArtifactsEnabled` | `false` | Persist quote-first artifact anchors for high-confidence extracted memories |
|
|
519
|
-
| `verbatimArtifactsMinConfidence` | `0.8` | Minimum extraction confidence for artifact writes |
|
|
520
|
-
| `verbatimArtifactsMaxRecall` | `5` | Maximum artifact anchors injected per recall |
|
|
521
|
-
| `verbatimArtifactCategories` | `["decision","correction","principle","commitment"]` | Categories eligible for artifact extraction |
|
|
522
|
-
|
|
523
|
-
### Local / OpenAI-Compatible Endpoint Settings
|
|
524
|
-
|
|
525
|
-
| Setting | Default | Description |
|
|
526
|
-
|---------|---------|-------------|
|
|
527
|
-
| `localLlmEnabled` | `false` | Enable local/compatible endpoint for extraction + consolidation |
|
|
528
|
-
| `localLlmUrl` | `http://localhost:1234/v1` | Base URL for OpenAI-compatible endpoint |
|
|
529
|
-
| `localLlmModel` | `local-model` | Model ID to use on the endpoint |
|
|
530
|
-
| `localLlmApiKey` | `(unset)` | Optional API key for authenticated endpoints |
|
|
531
|
-
| `localLlmHeaders` | `(unset)` | Optional extra headers (for proxy/provider-specific auth/routing) |
|
|
532
|
-
| `localLlmAuthHeader` | `true` | Send `Authorization: Bearer <localLlmApiKey>` when key is set |
|
|
533
|
-
| `localLlmFallback` | `true` | Fall back to gateway model chain when local endpoint fails |
|
|
534
|
-
|
|
535
|
-
Example (`openclaw.json` plugin config):
|
|
536
|
-
|
|
537
|
-
```json
|
|
538
|
-
{
|
|
539
|
-
"localLlmEnabled": true,
|
|
540
|
-
"localLlmUrl": "https://your-openai-compatible-endpoint.example/v1",
|
|
541
|
-
"localLlmModel": "your-model-id",
|
|
542
|
-
"localLlmApiKey": "${YOUR_ENDPOINT_API_KEY}",
|
|
543
|
-
"localLlmHeaders": {
|
|
544
|
-
"X-Provider-Routing": "engram-extraction"
|
|
545
|
-
},
|
|
546
|
-
"localLlmAuthHeader": true,
|
|
547
|
-
"localLlmFallback": true
|
|
548
|
-
}
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
### V2 Feature Settings
|
|
552
|
-
|
|
553
|
-
| Setting | Default | Description |
|
|
554
|
-
|---------|---------|-------------|
|
|
555
|
-
| `identityEnabled` | `true` | Enable agent identity reflections |
|
|
556
|
-
| `injectQuestions` | `false` | Inject open questions into the system prompt |
|
|
557
|
-
| `commitmentDecayDays` | `90` | Days before fulfilled/expired commitments are removed |
|
|
558
|
-
|
|
559
|
-
### v2.2 Advanced Retrieval Settings
|
|
560
|
-
|
|
561
|
-
See `docs/advanced-retrieval.md` for details and recommended safe defaults.
|
|
562
|
-
|
|
563
|
-
| Setting | Default | Description |
|
|
564
|
-
|---------|---------|-------------|
|
|
565
|
-
| `queryExpansionEnabled` | `false` | Heuristic query expansion (no LLM calls) |
|
|
566
|
-
| `queryExpansionMaxQueries` | `4` | Max expanded queries (including original) |
|
|
567
|
-
| `queryExpansionMinTokenLen` | `3` | Minimum token length for expansion |
|
|
568
|
-
| `rerankEnabled` | `false` | Enable LLM re-ranking (timeboxed; fail-open) |
|
|
569
|
-
| `rerankProvider` | `local` | `local` (no cloud calls). `cloud` is reserved/experimental (no-op in v2.2.0). |
|
|
570
|
-
| `rerankMaxCandidates` | `20` | Max candidates sent to re-ranker |
|
|
571
|
-
| `rerankTimeoutMs` | `8000` | Rerank timeout (ms) |
|
|
572
|
-
| `rerankCacheEnabled` | `true` | Cache reranks in-memory |
|
|
573
|
-
| `rerankCacheTtlMs` | `3600000` | Rerank cache TTL (ms) |
|
|
574
|
-
| `feedbackEnabled` | `false` | Enable `memory_feedback` tool and ranking bias |
|
|
575
|
-
| `negativeExamplesEnabled` | `false` | Enable negative examples + ranking penalty (opt-in) |
|
|
576
|
-
| `negativeExamplesPenaltyPerHit` | `0.05` | Penalty per "not useful" hit |
|
|
577
|
-
| `negativeExamplesPenaltyCap` | `0.25` | Maximum total penalty applied |
|
|
578
|
-
| `localLlmHomeDir` | `(auto)` | Optional home directory override for LM Studio settings + helper paths |
|
|
579
|
-
| `localLmsCliPath` | `(auto)` | Optional absolute path to `lms` CLI |
|
|
580
|
-
| `localLmsBinDir` | `(auto)` | Optional bin dir prepended to PATH for `lms` execution |
|
|
581
|
-
|
|
582
|
-
### v1.2.0 Advanced Feature Settings
|
|
583
|
-
|
|
584
|
-
#### Access Tracking & Retrieval
|
|
585
|
-
|
|
586
|
-
| Setting | Default | Description |
|
|
587
|
-
|---------|---------|-------------|
|
|
588
|
-
| `accessTrackingEnabled` | `true` | Track memory access counts and recency |
|
|
589
|
-
| `accessTrackingBufferMaxSize` | `100` | Max entries in access buffer before flush |
|
|
590
|
-
| `recencyWeight` | `0.2` | Weight for recency boosting (0-1) |
|
|
591
|
-
| `boostAccessCount` | `true` | Boost frequently accessed memories in search |
|
|
592
|
-
|
|
593
|
-
#### Chunking
|
|
594
|
-
|
|
595
|
-
| Setting | Default | Description |
|
|
596
|
-
|---------|---------|-------------|
|
|
597
|
-
| `chunkingEnabled` | `false` | Enable automatic chunking of long memories |
|
|
598
|
-
| `chunkingTargetTokens` | `200` | Target tokens per chunk |
|
|
599
|
-
| `chunkingMinTokens` | `150` | Minimum tokens to trigger chunking |
|
|
600
|
-
| `chunkingOverlapSentences` | `2` | Number of sentences to overlap between chunks |
|
|
601
|
-
|
|
602
|
-
#### Contradiction Detection
|
|
603
|
-
|
|
604
|
-
| Setting | Default | Description |
|
|
605
|
-
|---------|---------|-------------|
|
|
606
|
-
| `contradictionDetectionEnabled` | `false` | Enable LLM-verified contradiction detection |
|
|
607
|
-
| `contradictionSimilarityThreshold` | `0.7` | QMD similarity threshold to trigger check |
|
|
608
|
-
| `contradictionMinConfidence` | `0.9` | Minimum LLM confidence to auto-resolve |
|
|
609
|
-
| `contradictionAutoResolve` | `true` | Automatically supersede contradicted memories |
|
|
610
|
-
|
|
611
|
-
#### Memory Linking
|
|
38
|
+
→ **[Getting Started](docs/getting-started.md)** for QMD setup, first-time config, and verification.
|
|
612
39
|
|
|
613
|
-
|
|
614
|
-
|---------|---------|-------------|
|
|
615
|
-
| `memoryLinkingEnabled` | `false` | Enable automatic memory linking |
|
|
616
|
-
|
|
617
|
-
#### Conversation Threading
|
|
618
|
-
|
|
619
|
-
| Setting | Default | Description |
|
|
620
|
-
|---------|---------|-------------|
|
|
621
|
-
| `threadingEnabled` | `false` | Enable conversation threading |
|
|
622
|
-
| `threadingGapMinutes` | `30` | Minutes of gap to start a new thread |
|
|
623
|
-
|
|
624
|
-
#### Memory Summarization
|
|
625
|
-
|
|
626
|
-
| Setting | Default | Description |
|
|
627
|
-
|---------|---------|-------------|
|
|
628
|
-
| `summarizationEnabled` | `false` | Enable automatic memory compression |
|
|
629
|
-
| `summarizationTriggerCount` | `1000` | Memory count threshold to trigger |
|
|
630
|
-
| `summarizationRecentToKeep` | `300` | Number of recent memories to keep uncompressed |
|
|
631
|
-
| `summarizationImportanceThreshold` | `0.3` | Only compress memories with importance below this |
|
|
632
|
-
| `summarizationProtectedTags` | `["commitment", "preference", "decision", "principle"]` | Tags that protect memories from compression |
|
|
633
|
-
|
|
634
|
-
#### Topic Extraction
|
|
635
|
-
|
|
636
|
-
| Setting | Default | Description |
|
|
637
|
-
|---------|---------|-------------|
|
|
638
|
-
| `topicExtractionEnabled` | `true` | Enable topic extraction during consolidation |
|
|
639
|
-
| `topicExtractionTopN` | `50` | Number of top topics to extract |
|
|
640
|
-
|
|
641
|
-
### v6.0 Deduplication & Archival Settings
|
|
642
|
-
|
|
643
|
-
| Setting | Default | Description |
|
|
644
|
-
|---------|---------|-------------|
|
|
645
|
-
| `factDeduplicationEnabled` | `true` | Content-hash dedup prevents storing identical facts |
|
|
646
|
-
| `factArchivalEnabled` | `false` | Automatically archive old, low-value facts |
|
|
647
|
-
| `factArchivalAgeDays` | `90` | Minimum age (days) before a fact is eligible for archival |
|
|
648
|
-
| `factArchivalMaxImportance` | `0.3` | Only archive facts with importance below this threshold |
|
|
649
|
-
| `factArchivalMaxAccessCount` | `2` | Only archive facts accessed this many times or fewer |
|
|
650
|
-
| `factArchivalProtectedCategories` | `["commitment", "preference", "decision", "principle"]` | Categories that are never archived |
|
|
40
|
+
## How It Works
|
|
651
41
|
|
|
652
|
-
|
|
42
|
+
1. **Signal scan** — Fast local regex classifies each turn (<10 ms, no API call).
|
|
43
|
+
2. **Smart buffer** — high-signal turns extract immediately; others batch.
|
|
44
|
+
3. **Extraction** — One LLM call produces typed memories with confidence scores.
|
|
45
|
+
4. **Storage** — Plain markdown + YAML frontmatter files; no database.
|
|
46
|
+
5. **Retrieval** — QMD hybrid search injects relevant context before each agent session.
|
|
47
|
+
6. **Consolidation** — Periodic pass merges duplicates, updates entity profiles, expires stale entries.
|
|
653
48
|
|
|
654
|
-
|
|
655
|
-
- **`every_n`**: Extracts every N turns. Simple and predictable.
|
|
656
|
-
- **`time_based`**: Extracts when `bufferMaxMinutes` elapsed since last extraction.
|
|
49
|
+
→ **[Architecture Overview](docs/architecture/overview.md)** for internals.
|
|
657
50
|
|
|
658
|
-
|
|
51
|
+
## Memory Categories
|
|
659
52
|
|
|
660
|
-
|
|
53
|
+
10 typed categories: `fact`, `preference`, `correction`, `entity`, `decision`, `relationship`, `principle`, `commitment`, `moment`, `skill`.
|
|
661
54
|
|
|
662
|
-
|
|
663
|
-
2. `config.openaiApiKey` as literal string -- used directly
|
|
664
|
-
3. `process.env.OPENAI_API_KEY` -- implicit fallback
|
|
665
|
-
4. None -- extraction disabled, retrieval-only mode (plugin still loads and serves memories)
|
|
55
|
+
### v8.0 Memory OS (current)
|
|
666
56
|
|
|
667
|
-
**
|
|
57
|
+
- **Memory Boxes** (`memoryBoxesEnabled`) — Topic-windowed episode boxes with trace linking.
|
|
58
|
+
- **Episode/Note dual store** (`episodeNoteModeEnabled`) — Episodes preserve event fidelity; notes reconsolidate stable beliefs.
|
|
59
|
+
- **Verbatim Artifacts** (`verbatimArtifactsEnabled`) — High-confidence decisions/constraints stored as trusted retrieval anchors.
|
|
60
|
+
- **Recall Planner** (`recallPlannerEnabled`, default `true`) — Lightweight retrieve-vs-think gating.
|
|
668
61
|
|
|
669
62
|
## Agent Tools
|
|
670
63
|
|
|
671
|
-
The plugin registers tools that agents can call during conversations:
|
|
672
|
-
|
|
673
64
|
| Tool | Description |
|
|
674
65
|
|------|-------------|
|
|
675
|
-
| `memory_search` |
|
|
676
|
-
| `memory_store` |
|
|
677
|
-
| `
|
|
678
|
-
| `
|
|
679
|
-
| `
|
|
680
|
-
| `
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
|
685
|
-
|
|
686
|
-
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
66
|
+
| `memory_search` | Semantic search over memories |
|
|
67
|
+
| `memory_store` | Manually store a memory |
|
|
68
|
+
| `memory_profile` | Retrieve the behavioral profile |
|
|
69
|
+
| `memory_entities` | List tracked entities |
|
|
70
|
+
| `memory_promote` | Promote to shared namespace |
|
|
71
|
+
| `memory_feedback` | Record thumbs up/down signal |
|
|
72
|
+
|
|
73
|
+
## Docs
|
|
74
|
+
|
|
75
|
+
| Guide | Contents |
|
|
76
|
+
|-------|----------|
|
|
77
|
+
| [Getting Started](docs/getting-started.md) | Install, QMD setup, first-time config |
|
|
78
|
+
| [Config Reference](docs/config-reference.md) | Every setting, default, and description |
|
|
79
|
+
| [Operations](docs/operations.md) | Backup, export, hourly summaries, CLI |
|
|
80
|
+
| [Architecture: Overview](docs/architecture/overview.md) | System design and data model |
|
|
81
|
+
| [Architecture: Retrieval Pipeline](docs/architecture/retrieval-pipeline.md) | How recall works |
|
|
82
|
+
| [Architecture: Memory Lifecycle](docs/architecture/memory-lifecycle.md) | Write, consolidation, expiry |
|
|
83
|
+
| [Advanced Retrieval](docs/advanced-retrieval.md) | Reranking, query expansion, feedback |
|
|
84
|
+
| [Import / Export](docs/import-export.md) | Portable backups and migration |
|
|
85
|
+
| [Namespaces](docs/namespaces.md) | Multi-agent memory isolation |
|
|
86
|
+
| [Shared Context](docs/shared-context.md) | Cross-agent shared intelligence |
|
|
87
|
+
| [Compounding](docs/compounding.md) | Weekly synthesis and mistake learning |
|
|
88
|
+
| [Context Retention](docs/context-retention.md) | Transcript indexing and hourly summaries |
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
697
91
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
openclaw engram backup --out-dir /tmp/engram-backups --namespace main
|
|
702
|
-
openclaw engram profile # Display the behavioral profile
|
|
703
|
-
openclaw engram entities # List all tracked entities
|
|
704
|
-
openclaw engram entities person-name # View specific entity details
|
|
705
|
-
openclaw engram questions # List open curiosity questions
|
|
706
|
-
openclaw engram identity # Show agent identity reflections
|
|
707
|
-
|
|
708
|
-
# v1.2.0 commands
|
|
709
|
-
openclaw engram access # Show most accessed memories
|
|
710
|
-
openclaw engram access -n 30 # Show top 30 most accessed
|
|
711
|
-
openclaw engram flush-access # Manually flush access tracking buffer
|
|
712
|
-
|
|
713
|
-
openclaw engram importance # Show importance score distribution
|
|
714
|
-
openclaw engram importance -l high # Filter by importance level
|
|
715
|
-
openclaw engram importance -n 20 # Show top 20 most important
|
|
716
|
-
|
|
717
|
-
openclaw engram chunks # Show chunking statistics
|
|
718
|
-
openclaw engram chunks -p <id> # Show chunks for a specific parent
|
|
719
|
-
|
|
720
|
-
openclaw engram threads # List conversation threads
|
|
721
|
-
openclaw engram threads -t <id> # Show details for a specific thread
|
|
722
|
-
|
|
723
|
-
openclaw engram topics # Show extracted topics
|
|
724
|
-
openclaw engram topics -n 30 # Show top 30 topics
|
|
725
|
-
|
|
726
|
-
openclaw engram summaries # Show memory summaries
|
|
727
|
-
openclaw engram summaries -n 10 # Show top 10 most recent summaries
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
## Migration
|
|
731
|
-
|
|
732
|
-
Import memories from existing OpenClaw memory systems:
|
|
733
|
-
|
|
734
|
-
```bash
|
|
735
|
-
cd ~/.openclaw/extensions/openclaw-engram
|
|
736
|
-
|
|
737
|
-
# Full migration (context files + Supermemory + Honcho)
|
|
738
|
-
npx tsx scripts/migrate.ts
|
|
739
|
-
|
|
740
|
-
# Preview without writing anything
|
|
741
|
-
npx tsx scripts/migrate.ts --dry-run
|
|
742
|
-
|
|
743
|
-
# Migrate specific sources
|
|
744
|
-
npx tsx scripts/migrate.ts --source=context # Context files only
|
|
745
|
-
npx tsx scripts/migrate.ts --source=supermemory # Supermemory daily logs
|
|
746
|
-
npx tsx scripts/migrate.ts --source=honcho # Honcho API conclusions
|
|
747
|
-
```
|
|
748
|
-
|
|
749
|
-
The migration script:
|
|
750
|
-
- Deduplicates against existing engram memories
|
|
751
|
-
- Categorizes each memory (fact, preference, correction, decision)
|
|
752
|
-
- Writes proper frontmatter with source attribution
|
|
753
|
-
- Seeds `profile.md` from context files (if it doesn't exist yet)
|
|
754
|
-
- Prints a detailed report with counts per source
|
|
755
|
-
|
|
756
|
-
After migration, re-index QMD:
|
|
757
|
-
|
|
758
|
-
```bash
|
|
759
|
-
qmd update && qmd embed
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
## How It Works
|
|
763
|
-
|
|
764
|
-
### Extraction
|
|
765
|
-
|
|
766
|
-
When a trigger fires, the buffered conversation turns are sent to the OpenAI Responses API with a structured output schema (Zod). Empty or whitespace-only turns are filtered out before the API call to avoid errors. The LLM returns:
|
|
767
|
-
|
|
768
|
-
- **Facts**: Typed memories with category, content, confidence score, tags, and optional entity reference
|
|
769
|
-
- **Entities**: Named entities with their type and newly learned facts
|
|
770
|
-
- **Profile updates**: Standalone behavioral statements about the user
|
|
771
|
-
- **Questions**: 1-3 curiosity questions the agent wants answered in future sessions
|
|
772
|
-
- **Identity reflection**: A brief self-reflection on the agent's own behavior
|
|
773
|
-
|
|
774
|
-
### Consolidation
|
|
775
|
-
|
|
776
|
-
Every N extractions, a consolidation pass:
|
|
777
|
-
|
|
778
|
-
1. Compares recent memories against older ones
|
|
779
|
-
2. For each memory, decides: ADD, MERGE, UPDATE, INVALIDATE, or SKIP
|
|
780
|
-
3. MERGE and UPDATE actions track lineage (parent memory IDs)
|
|
781
|
-
4. Updates entity profiles and the behavioral profile
|
|
782
|
-
5. **Merges fragmented entity files** — entities with variant names that resolve to the same canonical form are automatically merged
|
|
783
|
-
6. Cleans expired commitments (fulfilled/expired + past decay period)
|
|
784
|
-
7. Removes TTL-expired speculative memories
|
|
785
|
-
8. **Archives old, low-importance, rarely-accessed facts** (v6.0, when `factArchivalEnabled`)
|
|
786
|
-
9. Auto-consolidates IDENTITY.md if it exceeds 8KB
|
|
787
|
-
|
|
788
|
-
### Entity Normalization
|
|
789
|
-
|
|
790
|
-
Entity names are automatically normalized to prevent fragmentation:
|
|
791
|
-
|
|
792
|
-
- Names are lowercased and hyphenated (`BlendSupply` → `blend-supply`)
|
|
793
|
-
- A configurable alias table maps common variants to canonical names
|
|
794
|
-
- Type preferences resolve cross-type duplicates (e.g., `company` wins over `other`)
|
|
795
|
-
- The periodic merge pass consolidates any entities that escaped normalization
|
|
796
|
-
|
|
797
|
-
### Profile Management
|
|
798
|
-
|
|
799
|
-
The behavioral profile (`profile.md`) is injected into every agent's system prompt to provide user context. To prevent unbounded growth:
|
|
800
|
-
|
|
801
|
-
- **Smart consolidation** (threshold: 600 lines): When the profile exceeds this limit during a consolidation pass, the LLM consolidates it — merging duplicate or near-duplicate bullets, removing stale information, and preserving `##` section headers
|
|
802
|
-
- Consolidation targets roughly 400 lines, prioritizing quality and durability of observations
|
|
803
|
-
- All section structure is preserved; only redundant or superseded bullets are removed
|
|
804
|
-
|
|
805
|
-
### Confidence Tiers
|
|
806
|
-
|
|
807
|
-
| Tier | Range | Meaning | TTL |
|
|
808
|
-
|------|-------|---------|-----|
|
|
809
|
-
| Explicit | 0.95-1.0 | Direct user statement ("I prefer X") | None |
|
|
810
|
-
| Implied | 0.70-0.94 | Strong contextual inference | None |
|
|
811
|
-
| Inferred | 0.40-0.69 | Pattern recognition from limited evidence | None |
|
|
812
|
-
| Speculative | 0.00-0.39 | Tentative hypothesis, needs confirmation | 30 days |
|
|
813
|
-
|
|
814
|
-
## Development
|
|
815
|
-
|
|
816
|
-
```bash
|
|
817
|
-
# Watch mode (rebuilds on file changes)
|
|
818
|
-
npm run dev
|
|
819
|
-
|
|
820
|
-
# Type checking
|
|
821
|
-
npm run check-types
|
|
822
|
-
|
|
823
|
-
# Build for production
|
|
824
|
-
npm run build
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
### Project Structure
|
|
828
|
-
|
|
829
|
-
```
|
|
830
|
-
src/
|
|
831
|
-
├── index.ts # Plugin entry point (hooks, tools, CLI registration)
|
|
832
|
-
├── orchestrator.ts # Central coordinator (extraction, consolidation, retrieval)
|
|
833
|
-
├── extraction.ts # OpenAI Responses API client
|
|
834
|
-
├── storage.ts # File-based storage manager (markdown + YAML frontmatter)
|
|
835
|
-
├── buffer.ts # Smart buffer with configurable trigger logic
|
|
836
|
-
├── signal.ts # Local signal detection (regex, zero cost)
|
|
837
|
-
├── schemas.ts # Zod schemas for structured LLM output
|
|
838
|
-
├── types.ts # TypeScript type definitions
|
|
839
|
-
├── config.ts # Config parser with env var resolution
|
|
840
|
-
├── qmd.ts # QMD CLI client (search, update, collection management)
|
|
841
|
-
├── tools.ts # Agent tool definitions
|
|
842
|
-
├── cli.ts # CLI subcommand definitions
|
|
843
|
-
├── logger.ts # Logging utilities
|
|
844
|
-
├── chunking.ts # [v1.2.0] Sentence-boundary chunking for long memories
|
|
845
|
-
├── importance.ts # [v1.2.0] Zero-LLM heuristic importance scoring
|
|
846
|
-
├── threading.ts # [v1.2.0] Conversation threading with TF-IDF titles
|
|
847
|
-
└── topics.ts # [v1.2.0] TF-IDF topic extraction across corpus
|
|
848
|
-
scripts/
|
|
849
|
-
└── migrate.ts # Migration from Honcho, Supermemory, context files
|
|
850
|
-
```
|
|
851
|
-
|
|
852
|
-
## Contributing
|
|
853
|
-
|
|
854
|
-
We welcome both issues and pull requests, including AI-assisted contributions.
|
|
855
|
-
|
|
856
|
-
- Report bugs: open a GitHub issue (use templates)
|
|
857
|
-
- Propose features: open a GitHub issue with scope and expected impact
|
|
858
|
-
- Submit PRs: keep scope focused, include tests, and update the changelog
|
|
859
|
-
|
|
860
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines, review expectations, and changelog policy.
|
|
861
|
-
See [CONTRIBUTORS.md](CONTRIBUTORS.md) for contributor recognition.
|
|
862
|
-
|
|
863
|
-
**Important:** This is a public repository. Never commit personal data, API keys, memory content, or user-specific configuration. See [CLAUDE.md](CLAUDE.md) and [SECURITY.md](SECURITY.md).
|
|
864
|
-
|
|
865
|
-
## License
|
|
866
|
-
|
|
867
|
-
MIT
|
|
92
|
+
- [OpenClaw](https://github.com/openclaw/openclaw) gateway
|
|
93
|
+
- OpenAI API key (extraction only; retrieval works without one)
|
|
94
|
+
- [QMD](https://github.com/tobi/qmd) (optional, recommended for hybrid search)
|