@unblocklabs/unblock-memory 0.3.21 → 0.3.23
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 +86 -990
- package/dist/src/config.d.ts +0 -5
- package/dist/src/config.js +2 -21
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/manager.d.ts +0 -1
- package/dist/src/manager.js +2 -22
- package/dist/src/people-store.d.ts +37 -3
- package/dist/src/people-store.js +23 -9
- package/dist/src/people-tools.js +5 -5
- package/dist/src/plugin.js +13 -63
- package/dist/src/slack-directory.js +3 -2
- package/docs/configuration.md +380 -0
- package/docs/peoplesql.md +223 -0
- package/docs/response-audit.md +217 -0
- package/docs/retrieval.md +576 -0
- package/openclaw.plugin.json +7 -23
- package/package.json +6 -2
- package/skills/memory-curator/SKILL.md +5 -0
- package/skills/people-whisperer/SKILL.md +10 -0
- package/dist/src/xsearch-bm25.d.ts +0 -4
- package/dist/src/xsearch-bm25.js +0 -56
- package/dist/src/xsearch.d.ts +0 -62
- package/dist/src/xsearch.js +0 -124
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
[Overview](../README.md) · [Retrieval](retrieval.md) · [People](peoplesql.md) · [Response audit](response-audit.md)
|
|
4
|
+
|
|
5
|
+
All plugin settings below belong under
|
|
6
|
+
`plugins.entries.unblock-memory.config`, not at the top level of OpenClaw.
|
|
7
|
+
Unknown keys are rejected. Restart/reload the Gateway after changing plugin
|
|
8
|
+
settings; a rotated credential file is reread without a restart.
|
|
9
|
+
|
|
10
|
+
## Feature gates and fallbacks
|
|
11
|
+
|
|
12
|
+
| Feature | Required settings/dependencies | TypeSafe disabled / no key | Provider or unreadable-key failure |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| Ordinary search/get | Installed/enabled memory slot; configured corpora | Unchanged local retrieval | Unchanged; its own indexing/embedding errors still matter |
|
|
15
|
+
| Skill Whisperer | `skillWhisperer.enabled`, skills corpus, host hooks | Best local vector candidate meeting `minScore` | No hint; does not fall back |
|
|
16
|
+
| Memory Whisperer | `memoryWhisperer.enabled`, explicit approved corpora, host hooks | No hints | No hints |
|
|
17
|
+
| Complementary hints | Enabled Memory Whisperer + `complementaryHints` | No additional judgment; base hints also require a key | Keep baseline hints unless the total deadline expires |
|
|
18
|
+
| People store/tools | `people.enabled` | Available; automatic save review needs primer/key or verified manual alternative | Storage/inspection still available |
|
|
19
|
+
| People Whisperer | People + `people.whisperer.enabled`, host hooks, eligible person/dossier, no prior thread receipt | Unchanged local lookup | Unchanged local lookup |
|
|
20
|
+
| People Primer / automatic dossier save review | People + `peoplePrimer.enabled`, approved corpora | No judgment; save requires source-specific manual verification | No automatic save; verify/retry instead |
|
|
21
|
+
| Quality audit / cluster review | `qualityAudit.enabled`, approved corpora; cluster review also needs fresh analysis | No judgment | Unavailable/partial; preserve evidence and retry as documented |
|
|
22
|
+
| Ordinary claim review | `evidenceReview.enabled`, approved corpora | No judgment | Unavailable; no claim verified |
|
|
23
|
+
| Response quality/sentiment | `responseAudit.enabled`, approved humans/chat types | No inference | Unavailable; successful assessment stages stay cached |
|
|
24
|
+
| Clustering | Configured local `analysis.executable` | Unchanged | Unchanged; worker failures do not disable ordinary search |
|
|
25
|
+
|
|
26
|
+
Whisperers, people storage, the primer and audits default off. `typesafe.enabled` defaults true but does not
|
|
27
|
+
enable any feature; `sentimentEnabled` defaults true only **within an enabled
|
|
28
|
+
response audit**. `peoplePrimer` controls automatic dossier-save review;
|
|
29
|
+
`evidenceReview` is a different advisory tool. Disabling people injection does
|
|
30
|
+
not disable people tools/storage or erase dossiers.
|
|
31
|
+
|
|
32
|
+
## Shared TypeSafe credentials
|
|
33
|
+
|
|
34
|
+
All plugin TypeSafe features use `plugins.entries.unblock-memory.config.typesafe`:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"typesafe": {
|
|
39
|
+
"enabled": true,
|
|
40
|
+
"apiKeyFile": "/absolute/path/to/secrets/unblock-memory-typesafe.env",
|
|
41
|
+
"timeoutMs": 1500
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This is a **plugin config fragment**, not a top-level OpenClaw configuration.
|
|
47
|
+
The key file can contain a plaintext key or dotenv entries:
|
|
48
|
+
|
|
49
|
+
```dotenv
|
|
50
|
+
TYPESAFE_API_KEY="YOUR_TYPESAFE_KEY"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Credentials come from inline `typesafe.apiKey`, an absolute `typesafe.apiKeyFile`,
|
|
54
|
+
or (when neither is configured) the Gateway process's `TYPESAFE_API_KEY` environment
|
|
55
|
+
variable. Configure at most one of `apiKey` and `apiKeyFile`; prefer a private file
|
|
56
|
+
over a secret in config. Defaults are `enabled: true` and `timeoutMs: 1500`.
|
|
57
|
+
|
|
58
|
+
The file is reread when a feature resolves credentials, so replacing its contents
|
|
59
|
+
does not require a Gateway restart. Restart/reload the Gateway after changing the
|
|
60
|
+
configured path or other plugin settings. A dotenv file is not executed as shell
|
|
61
|
+
code and does not change the process environment. Workspace `.env` files are not
|
|
62
|
+
auto-discovered, and an interactive shell's exported key need not reach a managed
|
|
63
|
+
Gateway service.
|
|
64
|
+
|
|
65
|
+
Missing/empty files or dotenv files without `TYPESAFE_API_KEY` count as no key.
|
|
66
|
+
An explicit file never falls back to an unrelated environment key. Missing or
|
|
67
|
+
unreadable credentials do not break normal memory functionality or Gateway startup;
|
|
68
|
+
the feature-specific fallback/skip behavior above applies. **Unreadable files and
|
|
69
|
+
provider errors are not Skill Whisperer's no-key fallback:** they suppress its hint.
|
|
70
|
+
Use `memory_diagnostics` for credential availability; it does not verify provider
|
|
71
|
+
acceptance. Keep secret files mode `600`, secret directories mode `700`, and keys
|
|
72
|
+
out of Git, chat, shell arguments and logs.
|
|
73
|
+
|
|
74
|
+
The plugin reads only `TYPESAFE_API_KEY` from the environment. Standalone QMD also
|
|
75
|
+
supports `TYPESAFE_API_KEY_FILE`; these are separate credential resolvers.
|
|
76
|
+
`typesafe.timeoutMs` is not a universal total deadline: People Primer and dossier
|
|
77
|
+
save review use `peoplePrimer.timeoutMs` per request; Memory Whisperer has its
|
|
78
|
+
own overall budget.
|
|
79
|
+
|
|
80
|
+
## Example profiles
|
|
81
|
+
|
|
82
|
+
These are **alternative plugin config fragments**, not additive whole-host files.
|
|
83
|
+
Merge only the intended settings. If supplying `corpora`, preserve every desired
|
|
84
|
+
existing entry: the array replaces the default, and exactly one `memory` is required.
|
|
85
|
+
Use the README's host wrapper and [host controls](#host-controls) separately.
|
|
86
|
+
|
|
87
|
+
### Sessions, including DMs explicitly
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"corpora": [
|
|
92
|
+
{ "name": "memory", "kind": "files", "paths": ["MEMORY.md", "USER.md", "memory/**/*.md"] },
|
|
93
|
+
{ "name": "sessions", "kind": "sessions", "chatTypes": ["channel", "group", "direct"], "syncIntervalMinutes": 60 }
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Omit `direct` when DMs should not be indexed. Start `memory_sync_sessions({})`
|
|
99
|
+
and inspect `memory_sync_status({})` for an immediate refresh; the scheduled first
|
|
100
|
+
refresh waits an interval.
|
|
101
|
+
|
|
102
|
+
### Skill Whisperer, local only
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"corpora": [
|
|
107
|
+
{ "name": "memory", "kind": "files", "paths": ["MEMORY.md", "USER.md", "memory/**/*.md"] },
|
|
108
|
+
{ "name": "skills", "kind": "skills", "paths": ["skills/**/SKILL.md", ".agents/skills/**/SKILL.md", "~/.agents/skills/**/SKILL.md", "~/.openclaw/skills/**/SKILL.md", "~/.openclaw/plugin-skills/**/SKILL.md"] }
|
|
109
|
+
],
|
|
110
|
+
"typesafe": { "enabled": false },
|
|
111
|
+
"skillWhisperer": { "enabled": true }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Select only desired skill locations. To use TypeSafe selection instead, enable
|
|
116
|
+
`typesafe` and configure credentials; the selected skill still is not auto-invoked.
|
|
117
|
+
|
|
118
|
+
### Memory Whisperer over approved knowledge
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"corpora": [
|
|
123
|
+
{ "name": "memory", "kind": "files", "paths": ["MEMORY.md", "USER.md", "memory/**/*.md"] },
|
|
124
|
+
{ "name": "knowledge", "kind": "files", "paths": ["knowledge/**/*.md"] }
|
|
125
|
+
],
|
|
126
|
+
"typesafe": { "apiKeyFile": "/absolute/path/to/secrets/unblock-memory-typesafe.env" },
|
|
127
|
+
"memoryWhisperer": { "enabled": true, "corpora": ["knowledge"] }
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Create the private key file first. Approve only knowledge suitable for every
|
|
132
|
+
audience of this agent. For exact-current-session hints, configure a sessions
|
|
133
|
+
corpus and add `sessions` to `memoryWhisperer.corpora`; missing session identity
|
|
134
|
+
excludes that corpus. This does not make ordinary search current-session-only.
|
|
135
|
+
|
|
136
|
+
### People storage, without injection
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{ "people": { "enabled": true, "whisperer": { "enabled": false } } }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### People injection and optional evidence primer
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"people": { "enabled": true, "whisperer": { "enabled": true } },
|
|
147
|
+
"peoplePrimer": { "enabled": true, "corpora": ["memory"] },
|
|
148
|
+
"typesafe": { "apiKeyFile": "/absolute/path/to/secrets/unblock-memory-typesafe.env" }
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The default memory corpus exists. This separately approves its evidence for
|
|
153
|
+
TypeSafe; it does not create a dossier or schedule maintenance. Use the
|
|
154
|
+
[people workflow](peoplesql.md). Adding `sessions` to primer approval, after
|
|
155
|
+
configuring that corpus, approves **all indexed sessions**, unlike Memory Whisperer.
|
|
156
|
+
|
|
157
|
+
### Optional analysis worker
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{ "analysis": { "executable": "/absolute/path/to/unblock-cluster/bin/unblock-memory-analysis" } }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Set this only after [installing the worker](retrieval.md#memory-analysis). No
|
|
164
|
+
clustering or curation schedule is created. Response-audit setup and a dry-run-first
|
|
165
|
+
workflow are in [its own guide](response-audit.md).
|
|
166
|
+
|
|
167
|
+
## Settings reference
|
|
168
|
+
|
|
169
|
+
The tables show resolved defaults. For source-specific entries,
|
|
170
|
+
`corpora[sessions]` means the array entry with `name: "sessions"`, not a literal
|
|
171
|
+
configuration key. The manifest schema and config resolvers are the machine
|
|
172
|
+
contract; these tables explain their effects.
|
|
173
|
+
|
|
174
|
+
## Sources and base runtime
|
|
175
|
+
|
|
176
|
+
| Setting | Default | Meaning / supported range |
|
|
177
|
+
| --- | --- | --- |
|
|
178
|
+
| `corpora` | One files corpus `memory`: `MEMORY.md`, `USER.md`, `memory/**/*.md` | Explicit array replaces defaults; must contain exactly one `memory`; `all` is a search selector, not a corpus name |
|
|
179
|
+
| `corpora[].name` | Required for explicit entries | Unique name; `sessions` and `skills` reserved for corresponding kinds |
|
|
180
|
+
| `corpora[].kind` | Required for explicit entries | `files`, `sessions`, or `skills` |
|
|
181
|
+
| `corpora[].paths` | Required for files/skills | Nonempty exact-file/directory/glob list; workspace-relative, absolute or `~/`; directory means recursive Markdown; does not grant host write trust |
|
|
182
|
+
| `corpora[sessions].chatTypes` | `['channel','group']` | Nonempty subset of channel/group/direct; DMs require `direct` |
|
|
183
|
+
| `corpora[sessions].maxExpandedTokens` | `500` | 1–10,000; use full turn/message when it fits, otherwise preserve full matched chunk; not a total result-size hard cap |
|
|
184
|
+
| `corpora[sessions].syncIntervalMinutes` | `60` | 0–1,440; zero manual-only; first scheduled sync after one interval; requires running Gateway |
|
|
185
|
+
| `keepEmbeddingModelWarm` | `true` | Retain embedding model/context after first use; false allows five-minute idle disposal |
|
|
186
|
+
| `analysis.executable` | Unset | Optional absolute local worker path; enables ability to recluster, not automatic scheduling |
|
|
187
|
+
|
|
188
|
+
## TypeSafe and whisperers
|
|
189
|
+
|
|
190
|
+
| Setting | Default | Meaning / supported range |
|
|
191
|
+
| --- | --- | --- |
|
|
192
|
+
| `typesafe.enabled` | `true` | Shared plugin provider gate; no feature is opted in merely by adding a key |
|
|
193
|
+
| `typesafe.apiKey` | Unset | Explicit inline key; mutually exclusive with key file; prefer file |
|
|
194
|
+
| `typesafe.apiKeyFile` | Unset | Absolute raw-key or dotenv file, reread at credential resolution; explicit missing file never falls back to a different key |
|
|
195
|
+
| `typesafe.timeoutMs` | `1500` | 1–10,000 per request for Skill/Memory Whisperer, quality/claim/cluster review and response audit; **primer and dossier save use `peoplePrimer.timeoutMs` instead** |
|
|
196
|
+
| `skillWhisperer.enabled` | `false` | Requires explicit skills corpus and appropriate host hook access |
|
|
197
|
+
| `skillWhisperer.historyMessages` | `5` | Nonnegative integer; prior visible messages used for routing |
|
|
198
|
+
| `skillWhisperer.minScore` | `0.5` | 0–1, **local vector fallback only**, ignored for TypeSafe shortlist admission |
|
|
199
|
+
| `skillWhisperer.cooldownTurns` | `10` | Nonnegative user-turn count; no fallback to weaker cooling-down alternatives |
|
|
200
|
+
| `memoryWhisperer.enabled` | `false` | Requires explicit approved non-skill corpora, TypeSafe key and host hooks |
|
|
201
|
+
| `memoryWhisperer.corpora` | `[]` | Explicit known corpus names; required nonempty when enabled; no `all` or skills |
|
|
202
|
+
| `memoryWhisperer.historyMessages` | `5` | 0–50, retrieval history count, not judge-history limit |
|
|
203
|
+
| `memoryWhisperer.minUsefulness` | `0.9` | 0–1, minimum Noul yes-probability per candidate |
|
|
204
|
+
| `memoryWhisperer.maxHints` | `2` | 1–2 |
|
|
205
|
+
| `memoryWhisperer.cooldownTurns` | `10` | 0–1,000; recently injected evidence |
|
|
206
|
+
| `memoryWhisperer.timeoutMs` | `3000` | 1–10,000 total whisper deadline, not just the provider timeout |
|
|
207
|
+
| `memoryWhisperer.complementaryHints` | `false` | Optional extra redundancy judgment; does not expand retrieval or enable the feature |
|
|
208
|
+
|
|
209
|
+
No configured plugin credential means fallback to **`TYPESAFE_API_KEY` only** in
|
|
210
|
+
the Gateway environment. Unlike QMD's resolver, the plugin does not read a
|
|
211
|
+
`TYPESAFE_API_KEY_FILE` environment variable. Do not conflate these contracts.
|
|
212
|
+
Missing/empty key and unreadable/erroring key are different for Skill Whisperer:
|
|
213
|
+
the former allows vector fallback; the latter suppresses the hint.
|
|
214
|
+
|
|
215
|
+
## People
|
|
216
|
+
|
|
217
|
+
| Setting | Default | Meaning / supported range |
|
|
218
|
+
| --- | --- | --- |
|
|
219
|
+
| `people.enabled` | `false` | Store, Slack identity observation, people tools; independent of injection |
|
|
220
|
+
| `people.whisperer.enabled` | `false` | Exact-identity prompt injection; requires people enabled |
|
|
221
|
+
| `people.whisperer.maxChars` | `1200` | 1–4,000; also the **stored new-dossier blurb character limit even when injection is off**; independent 70-word ceiling remains |
|
|
222
|
+
| `people.todos.maxOpen` | `1000` | 1–10,000; bounded open data-quality todos with overflow accounting |
|
|
223
|
+
| `peoplePrimer.enabled` | `false` | Requires people enabled + explicit approved corpora; controls evidence primer and automatic save review |
|
|
224
|
+
| `peoplePrimer.corpora` | `[]` | Explicit configured non-skill evidence approvals; sessions means all indexed sessions |
|
|
225
|
+
| `peoplePrimer.hitsPerQuestion` | `30` | 1–40 vector results for each of three questions, before provider grading |
|
|
226
|
+
| `peoplePrimer.minScore` | `0.35` | 0–1 vector admission threshold |
|
|
227
|
+
| `peoplePrimer.minUsefulness` | `0.8` | 0.5–1; all background eligibility dimensions must pass |
|
|
228
|
+
| `peoplePrimer.maxEvidencePerQuestion` | `3` | 1–10 selected evidence references per question, **not** a cap on grading work |
|
|
229
|
+
| `peoplePrimer.timeoutMs` | `30000` | 1–60,000 per provider request, also used for draft/save review; tool's overall limit is 120 seconds |
|
|
230
|
+
|
|
231
|
+
## Audits and advisory reviews
|
|
232
|
+
|
|
233
|
+
| Setting | Default | Meaning / supported range |
|
|
234
|
+
| --- | --- | --- |
|
|
235
|
+
| `qualityAudit.enabled` | `false` | On-demand chunk-quality and sampled-cluster review |
|
|
236
|
+
| `qualityAudit.corpora` | `[]` | Explicit non-skill approval; nonempty when enabled; sessions means all indexed sessions |
|
|
237
|
+
| `qualityAudit.minNoise` | `0.8` | 0–1 threshold for model noise flags; deterministic empty/encoding indicators have separate rules |
|
|
238
|
+
| `evidenceReview.enabled` | `false` | Ordinary atomic-claim review tool; does not turn on dossier save review |
|
|
239
|
+
| `evidenceReview.corpora` | `[]` | Explicit non-skill approval; nonempty when enabled |
|
|
240
|
+
| `responseAudit.enabled` | `false` | Operator-only response evaluation; requires approved senders and TypeSafe |
|
|
241
|
+
| `responseAudit.sentimentEnabled` | `true` | Within opted-in audit; false removes emotion questions without disabling quality judgments |
|
|
242
|
+
| `responseAudit.senderIds` | `[]` | Up to 50 approved Slack sender IDs; nonempty when enabled; trusted human/owner metadata also required, explicit bots excluded |
|
|
243
|
+
| `responseAudit.chatTypes` | `['direct']` | Nonempty approved subset of direct/group/channel |
|
|
244
|
+
| `responseAudit.historyMessages` | `6` | 0–20 preceding visible messages |
|
|
245
|
+
| `responseAudit.lookbackDays` | `30` | 1–90 days |
|
|
246
|
+
| `responseAudit.maxEpisodes` | `20` | 1–100 per run; a run need not clear the backlog |
|
|
247
|
+
| `responseAudit.intervalMinutes` | `60` | 0–1,440; zero manual-only; persisted per-agent due time, bounded catch-up |
|
|
248
|
+
| `responseAudit.memoryCorpora` | `[]` | Optional file-only corpus approvals for current-index memory-gap investigation; separate from response transcript approval |
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
## Host controls
|
|
252
|
+
|
|
253
|
+
These are **outside** `plugins.entries.unblock-memory.config`:
|
|
254
|
+
|
|
255
|
+
- `plugins.slots.memory: "unblock-memory"` selects the memory owner. Installation,
|
|
256
|
+
plugin enablement and any host allowlists remain separate.
|
|
257
|
+
- `plugins.entries.unblock-memory.hooks.allowConversationAccess` allows the
|
|
258
|
+
non-bundled plugin's conversation hooks. `allowPromptInjection` controls prompt
|
|
259
|
+
mutation. For whisperers, configure the plugin entry with this fragment:
|
|
260
|
+
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"plugins": {
|
|
264
|
+
"entries": {
|
|
265
|
+
"unblock-memory": {
|
|
266
|
+
"hooks": { "allowConversationAccess": true, "allowPromptInjection": true }
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Host hook timeouts may bound work independently of the plugin's internal deadline.
|
|
274
|
+
The flags do not enable any whisperer by themselves.
|
|
275
|
+
|
|
276
|
+
Optional `memory_people_sync` may need `tools.allow`; agent skill allowlists must
|
|
277
|
+
include `people-whisperer` and/or `memory-curator` when used. Indexing a skill for
|
|
278
|
+
routing neither authorizes nor installs it.
|
|
279
|
+
|
|
280
|
+
### Compaction memory writes
|
|
281
|
+
|
|
282
|
+
The plugin supplies OpenClaw a pre-compaction memory-flush plan unless
|
|
283
|
+
`agents.defaults.compaction.memoryFlush.enabled` is false. This is a
|
|
284
|
+
**host-triggered agent write**, not an independent plugin timer. It is separate
|
|
285
|
+
from session sync, all whisperers and dossier maintenance.
|
|
286
|
+
|
|
287
|
+
Its prompt writes durable information only to `memory/YYYY-MM-DD.md`, appending
|
|
288
|
+
if the file exists, never overwriting it or bootstrap files. When nothing merits
|
|
289
|
+
storage, `NO_REPLY` is appropriate. The date uses
|
|
290
|
+
`agents.defaults.userTimezone`, otherwise the system timezone.
|
|
291
|
+
|
|
292
|
+
Supported host settings: `enabled`, `softThresholdTokens` (default 4,000),
|
|
293
|
+
`forceFlushTranscriptBytes` (default 2 MiB), and optional `model`. The plugin
|
|
294
|
+
plan has a fixed 20,000-token reserve floor and supplies its own prompts; custom
|
|
295
|
+
host `memoryFlush.prompt` / `systemPrompt` are not used by this resolver.
|
|
296
|
+
|
|
297
|
+
Disable this plan with this **host config fragment**:
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
{ "agents": { "defaults": { "compaction": { "memoryFlush": { "enabled": false } } } } }
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Or customize its supported thresholds and date timezone:
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"agents": {
|
|
308
|
+
"defaults": {
|
|
309
|
+
"userTimezone": "America/New_York",
|
|
310
|
+
"compaction": {
|
|
311
|
+
"memoryFlush": { "enabled": true, "softThresholdTokens": 6000, "forceFlushTranscriptBytes": "3mb" }
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Agent and audience scope
|
|
319
|
+
|
|
320
|
+
Per-person injection state, dossier existence, availability and thread receipts
|
|
321
|
+
are stored state, not config switches. See [people lifecycle](peoplesql.md#injection-and-person-state).
|
|
322
|
+
|
|
323
|
+
Normal memory tools can access the agent's configured non-skill corpora. Corpus
|
|
324
|
+
selectors are not audience ACLs. Per-feature TypeSafe approvals constrain that
|
|
325
|
+
feature's remote processing, not general retrieval access. This is an agent/fleet
|
|
326
|
+
boundary, not multi-tenant authorization. Approve sources for the agent's audiences.
|
|
327
|
+
|
|
328
|
+
## TypeSafe data scope
|
|
329
|
+
|
|
330
|
+
| Feature | Evidence sent when explicitly enabled/approved |
|
|
331
|
+
| --- | --- |
|
|
332
|
+
| Skill selection | Bounded visible current/recent conversation + shortlisted skill names/descriptions; not skill procedures or source-path fields |
|
|
333
|
+
| Memory hints | Bounded visible conversation + up to 8 complete excerpts, corpus names and relevant session dates; exact current session only for session hits |
|
|
334
|
+
| Complementarity | Up to 4 already-qualified excerpts for pairwise redundancy checks |
|
|
335
|
+
| People primer | Person identity, agent name, approved retrieved excerpts and source/session metadata; all indexed sessions eligible if approved, not just the current chat |
|
|
336
|
+
| Dossier save/draft review | Proposed blurb, person/agent names and 1–3 exact approved indexed evidence ranges, at most 6,000 characters total; existing dossier is not evidence |
|
|
337
|
+
| Chunk quality | Up to 4 complete chunks of at most 6,000 characters each per request + source kinds; no conversation or source-path fields |
|
|
338
|
+
| Ordinary claim review | One proposed claim + up to 3 approved indexed ranges, at most 6,000 characters total |
|
|
339
|
+
| Cluster review | Up to 6 eligible complete sampled chunks, each at most 2,000 characters; conclusions only concern the sample |
|
|
340
|
+
| Response audit | Approved visible request/answer/context/feedback and bounded later response evidence, separated by assessment stage; optional current-index whole-short-document evidence from approved file corpora |
|
|
341
|
+
| Standalone QMD query | Query, optional intent, selected excerpts, source paths and evaluation time; separate process/SDK credentials and collection scope |
|
|
342
|
+
|
|
343
|
+
Omitting tool-result/thinking/system fields does not remove their content if it
|
|
344
|
+
was quoted in ordinary visible text. Provider judgments are advisory; probability
|
|
345
|
+
or score is not proof. Enabling a feature approves only that feature's documented processing.
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
## Storage, upgrades and recovery
|
|
349
|
+
|
|
350
|
+
Each agent's state lives under the configured OpenClaw state directory, normally
|
|
351
|
+
`~/.openclaw/agents/<agentId>/unblock-memory/`. `index.sqlite` is rebuildable;
|
|
352
|
+
`unblock-memory.sqlite` holds durable people, curation and response-audit state.
|
|
353
|
+
Disabling a feature does not delete its data.
|
|
354
|
+
|
|
355
|
+
### Durable database migration
|
|
356
|
+
|
|
357
|
+
Each agent has two active plugin databases: rebuildable `index.sqlite` and durable
|
|
358
|
+
`unblock-memory.sqlite`. The latter uses WAL, private permissions and component
|
|
359
|
+
schema versions. Store modules and tool access remain separate: consolidating files
|
|
360
|
+
does not expose operator response audits to memory searches or whisperers.
|
|
361
|
+
|
|
362
|
+
When upgrading from separate `curation.sqlite`, `people.sqlite` and
|
|
363
|
+
`response-audit.sqlite` files, **stop the Gateway and any plugin CLI writers first**.
|
|
364
|
+
On first durable-store access, the plugin imports all existing files, even for
|
|
365
|
+
disabled features, in one transaction. It includes committed WAL data, verifies
|
|
366
|
+
row counts/values and foreign keys, and records completion. Missing stores are
|
|
367
|
+
normal; unsupported or invalid data aborts the import without a partial cutover.
|
|
368
|
+
Restarting retries an incomplete import. QMD and transcript databases are untouched.
|
|
369
|
+
|
|
370
|
+
The old files remain untouched as **inert recovery copies**, not active stores.
|
|
371
|
+
Completed migration never reimports them or writes to them. Do not run old and new
|
|
372
|
+
plugin versions together: old writers can continue changing their separate files.
|
|
373
|
+
Back up the new database with SQLite's online backup API (or with all writers
|
|
374
|
+
stopped and WAL safely checkpointed); copying only a live `.sqlite` file is unsafe.
|
|
375
|
+
|
|
376
|
+
To roll back before any new writes, stop all writers, preserve the new database and
|
|
377
|
+
its WAL/SHM sidecars, and restore the old plugin against the retained legacy files.
|
|
378
|
+
**After new writes, those files are stale**: an old-version rollback requires an
|
|
379
|
+
explicit reverse data migration or accepting the loss of post-upgrade changes.
|
|
380
|
+
Keep recovery files until the upgrade has been verified; cleanup is a separate step.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# People dossiers and whispering
|
|
2
|
+
|
|
3
|
+
[Overview](../README.md) · [Configuration and credentials](configuration.md)
|
|
4
|
+
|
|
5
|
+
PeopleSQL stores identity, dossier and change history. The agent authors a brief
|
|
6
|
+
recognition snippet; People Whisperer injects only its saved blurb. Enable the
|
|
7
|
+
store with `people.enabled`; enable injection separately with
|
|
8
|
+
`people.whisperer.enabled`. The optional `peoplePrimer` approves evidence preparation
|
|
9
|
+
and automatic save review, not a maintenance scheduler. For independent setup
|
|
10
|
+
examples, see the [configuration profiles](configuration.md#example-profiles).
|
|
11
|
+
|
|
12
|
+
## Optional People Dossier Primer
|
|
13
|
+
|
|
14
|
+
`memory_people_prime({ personId, agentName? })` prepares evidence for an existing person;
|
|
15
|
+
it does **not** generate claims, update dossiers, or inject context. With
|
|
16
|
+
`people.enabled: true`, opt in separately:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"peoplePrimer": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"corpora": ["memory", "knowledge", "sessions"],
|
|
23
|
+
"hitsPerQuestion": 30,
|
|
24
|
+
"minScore": 0.35,
|
|
25
|
+
"minUsefulness": 0.8,
|
|
26
|
+
"maxEvidencePerQuestion": 3,
|
|
27
|
+
"timeoutMs": 30000
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This is a plugin config fragment. List only configured, approved non-skill corpora. The feature is **off by
|
|
33
|
+
default** and requires shared TypeSafe credentials. Disabled TypeSafe or missing/
|
|
34
|
+
unreadable credentials safely skip the primer; agents can still research normally.
|
|
35
|
+
Enabling it approves sending the person's identity, retrieved excerpts and optional
|
|
36
|
+
draft snippet to TypeSafe. Existing dossiers are not sent as grading evidence.
|
|
37
|
+
Sessions includes all indexed conversations;
|
|
38
|
+
results are available to the agent's tool callers, so scope approval accordingly.
|
|
39
|
+
Primer and dossier-save requests use `peoplePrimer.timeoutMs`, not
|
|
40
|
+
`typesafe.timeoutMs`; the total tool deadline is two minutes.
|
|
41
|
+
|
|
42
|
+
Three default questions cover explicit role/organization, enduring organizational
|
|
43
|
+
background, and the person's relationship to the agent (not its business mission).
|
|
44
|
+
Preferences, working styles, priorities, feedback and task history are excluded.
|
|
45
|
+
Each uses QMD vector search (no query expansion) for up to 30 hits, configurable
|
|
46
|
+
up to 40. All unique eligible hits above the vector threshold are graded, not just
|
|
47
|
+
the final top three. Complete excerpts over 6,000 characters are counted and skipped,
|
|
48
|
+
not silently truncated. Duplicate source spans across questions share a request;
|
|
49
|
+
Independent attribution, explicit-background, durability, recognition-value and
|
|
50
|
+
question-usefulness judgments run together; every dimension must pass the threshold.
|
|
51
|
+
Every candidate is graded against all three questions, regardless of which search
|
|
52
|
+
found it. Mixed excerpts may supply a useful background fact without making their
|
|
53
|
+
surrounding behavioral content eligible for the snippet.
|
|
54
|
+
Provider concurrency is four, with a two-minute overall tool deadline.
|
|
55
|
+
|
|
56
|
+
Supply the agent's human-facing name when no identity name is configured; otherwise
|
|
57
|
+
questions use "the assistant", never an internal routing ID such as `main`.
|
|
58
|
+
The output includes a deduplicated source-linked excerpt list referenced by each
|
|
59
|
+
question's evidence IDs, a bounded uncertain-review shortlist,
|
|
60
|
+
and retrieval/cache/failure counts. Coverage is `evidence_found`, `uncertain` or
|
|
61
|
+
`unknown`, not a claim that a question has been definitively answered. Partial
|
|
62
|
+
provider failures are explicit; absence of selected hits does not prove absence of
|
|
63
|
+
evidence. The agent must verify dates, speakers and contradictions before writing.
|
|
64
|
+
Memory evidence never grants permissions or establishes that an old request is
|
|
65
|
+
still open.
|
|
66
|
+
|
|
67
|
+
`memory_people_update({ action: "replace_dossier", personId, dossier, reason,
|
|
68
|
+
agentName? })` automatically checks the proposed blurb before saving. Exact
|
|
69
|
+
`qmd://path#Lstart-Lend` claim evidence locators supply up to three indexed ranges
|
|
70
|
+
from the primer's approved corpora (120 lines each, 6,000 characters total).
|
|
71
|
+
Support confidence and background-only/explicit-support probabilities must all
|
|
72
|
+
be >=0.9. `needs_review` or `review_unavailable` leaves the dossier and history
|
|
73
|
+
unchanged; missing keys and failures never count as approval. A concurrent dossier
|
|
74
|
+
edit/deletion returns `conflict` instead of overwriting the newer change.
|
|
75
|
+
|
|
76
|
+
After independently verifying every assertion and background eligibility, an agent
|
|
77
|
+
can supply a source-specific `manualVerification` explanation (up to 400 characters)
|
|
78
|
+
for direct human corrections, non-indexed evidence or disabled/unavailable/incorrect
|
|
79
|
+
reviews. This explicit path skips TypeSafe, records manual provenance in change
|
|
80
|
+
history and keeps all structural limits. It is not a provider pass. Normal success
|
|
81
|
+
returns `status: "ok"`, `saved: true` and `verification: "typesafe" | "manual"`.
|
|
82
|
+
The skill documents when to use each path. Sources outside approved corpora are
|
|
83
|
+
rejected before egress; no separate `evidenceReview` toggle is needed.
|
|
84
|
+
|
|
85
|
+
For optional read-only diagnostics, `memory_people_prime({ personId, agentName?,
|
|
86
|
+
draft: { blurb, citations: [{ path, from, lines }] } })` still reviews a snippet
|
|
87
|
+
without writing. Agents do not need this extra call in the normal update workflow.
|
|
88
|
+
|
|
89
|
+
Judgments are cached privately in `unblock-memory.sqlite` (maximum 2,000 entries), keyed
|
|
90
|
+
by person, agent, exact evidence/context, questions,
|
|
91
|
+
and judge version. No source text or credentials are stored in the cache.
|
|
92
|
+
Retrieval reruns against the current index; unchanged judgments are reused.
|
|
93
|
+
This is on-demand preparation, not a new scheduler or incremental session scanner.
|
|
94
|
+
Use it from an existing People Whisperer maintenance cron. Refresh stale session
|
|
95
|
+
indexes with `memory_sync_sessions` before priming when needed.
|
|
96
|
+
|
|
97
|
+
## People store and maintenance
|
|
98
|
+
|
|
99
|
+
PeopleSQL is an optional agent-local people store. When `people.enabled` is
|
|
100
|
+
true, incoming Slack messages with a canonical agent session key and exact
|
|
101
|
+
account and sender IDs create or refresh an injection-enabled person record.
|
|
102
|
+
Incomplete Slack identities create a bounded, deduplicated todo without storing
|
|
103
|
+
message content. Other channels are ignored.
|
|
104
|
+
|
|
105
|
+
PeopleSQL registers these tools when enabled:
|
|
106
|
+
|
|
107
|
+
- `memory_people_inspect` lists active people, reads one exact person, reads one
|
|
108
|
+
person's dossier change history, or lists bounded actionable todos;
|
|
109
|
+
- `memory_people_update` replaces or deletes dossiers, toggles one person's
|
|
110
|
+
injection, and manages company, todo, deletion, or restoration state;
|
|
111
|
+
- `memory_people_prime` prepares evidence when the separately opted-in primer is
|
|
112
|
+
enabled, otherwise returns disabled; and
|
|
113
|
+
- the optional `memory_people_sync` enriches one active OpenClaw Slack account;
|
|
114
|
+
its tool input accepts an account ID, not a token.
|
|
115
|
+
|
|
116
|
+
The inspect and update tools are part of the normal agent tool surface; they do
|
|
117
|
+
not depend on sender-owner authorization. Directory sync remains optional and
|
|
118
|
+
may need to be allowed explicitly through `tools.allow`. The sync is bounded to
|
|
119
|
+
200 normalized directory entries per call and is safe to rerun. Unblock Memory
|
|
120
|
+
keeps normalized ID, name, handle, avatar, bot and deactivation fields. Slack requires the
|
|
121
|
+
`users:read` scope. Each invocation starts at the beginning of the directory;
|
|
122
|
+
there is no caller-visible continuation cursor. Repeating a capped call does not
|
|
123
|
+
guarantee coverage beyond 200 entries, and sync does not reactivate unavailable people.
|
|
124
|
+
|
|
125
|
+
The agent owns dossier generation and refresh. It can list people, inspect one
|
|
126
|
+
person's current dossier, search ordinary memory and sessions with
|
|
127
|
+
`memory_search`/`memory_get`, and replace the dossier when that would improve a
|
|
128
|
+
future conversation. The plugin owns no dossier-maintenance workflow or refresh
|
|
129
|
+
schedule. A dossier's `reviewedAt` value records its last successful write; it
|
|
130
|
+
is not scheduling state. Dossier generation belongs to the agent; prompt injection
|
|
131
|
+
performs no model call. The optional primer grades evidence and reviews draft snippets.
|
|
132
|
+
The goal is recognition, not a behavioral profile: one short paragraph of at most
|
|
133
|
+
70 words identifying the person and their enduring organization/agent relationship.
|
|
134
|
+
New writes allow only `role`/`relationship` sections and explicit `observed`/`reported`
|
|
135
|
+
claims; priorities, preferences and inferred profiles belong outside dossiers.
|
|
136
|
+
Legacy dossiers remain readable, but must be deliberately rewritten by the agent
|
|
137
|
+
before replacement. No automatic destructive migration or blanket deletion occurs.
|
|
138
|
+
|
|
139
|
+
Every `replace_dossier` and `delete_dossier` action requires a concise `reason`
|
|
140
|
+
(up to 500 characters for replacements, 1,000 for deletions). Replacement history
|
|
141
|
+
also records whether TypeSafe checks passed or a manual attestation was used.
|
|
142
|
+
The plugin transactionally records that reason with its authoritative before and
|
|
143
|
+
after dossier snapshots. List small newest-first summaries with
|
|
144
|
+
`memory_people_inspect({ view: "dossier_changes", personId, limit?, offset? })`,
|
|
145
|
+
then fetch one exact diff with
|
|
146
|
+
`memory_people_inspect({ view: "dossier_change", personId, changeId })`. List
|
|
147
|
+
responses include `nextOffset`, so all history remains reachable without loading
|
|
148
|
+
many dossiers into one tool result. Because the injected snippet is the dossier's
|
|
149
|
+
`blurb`, its changes are included in the same history. A complete new serialized
|
|
150
|
+
dossier is capped at 64 KiB; larger legacy dossiers remain readable and repairable.
|
|
151
|
+
|
|
152
|
+
## Injection and person state
|
|
153
|
+
|
|
154
|
+
Set `people.whisperer.enabled` to inject context. For each exact Slack sender,
|
|
155
|
+
the plugin prepends that person's stored dossier blurb, bounded by `maxChars`,
|
|
156
|
+
once per `(Slack thread, person)`. Receipts are durable across retries and
|
|
157
|
+
Gateway restarts, while different people in one thread are handled independently.
|
|
158
|
+
Unthreaded DMs use their OpenClaw session as the conversational scope. Unknown,
|
|
159
|
+
unavailable, disabled, or dossierless people produce no context. Injection
|
|
160
|
+
remains subject to OpenClaw's `allowPromptInjection` policy.
|
|
161
|
+
|
|
162
|
+
The package includes a `$people-whisperer` skill with the canonical agent
|
|
163
|
+
procedure and dossier shape. For a manual refresh, ask:
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
Use $people-whisperer to maintain this person's brief background snippet.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For an optional cron or isolated agent session, use this goal:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
Use $people-whisperer to maintain brief background snippets for people you interact
|
|
173
|
+
with. Follow the packaged skill, including source verification and write results.
|
|
174
|
+
Update only when useful; several people or nobody is fine. Report changes and gaps.
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Choose any cadence appropriate for the agent; the plugin does not require or
|
|
178
|
+
track one. If session transcripts are a source, configure a `sessions` corpus
|
|
179
|
+
(including `direct` when DMs matter) and refresh it with
|
|
180
|
+
`memory_sync_sessions`. Ordinary `memory_search` calls accept targeted queries,
|
|
181
|
+
corpora, session metadata filters, score thresholds, and up to 20 results per
|
|
182
|
+
call; People Whisperer itself imposes no evidence-window limit.
|
|
183
|
+
|
|
184
|
+
### Pause, correct, delete or restore
|
|
185
|
+
|
|
186
|
+
| Action | Effect | Preserved / follow-up |
|
|
187
|
+
| --- | --- | --- |
|
|
188
|
+
| `set_injection` with `enabled:false` | Pause future injection for this person | Person, dossier and history remain |
|
|
189
|
+
| `replace_dossier` | Save a verified full replacement | Prior snapshot/reason remain in history; existing thread receipts are not reset |
|
|
190
|
+
| `delete_dossier` | Remove the current dossier | Person and transactional before/after history remain; no new blurb injection |
|
|
191
|
+
| `soft_delete_person` | Mark unavailable and turn injection off | Identity/dossier/history remain; creates a review todo |
|
|
192
|
+
| `restore_person` | Mark active again | Injection stays **off**; inspect and explicitly re-enable if appropriate |
|
|
193
|
+
| `set_injection` with `enabled:true` | Enable the person-level injection gate | Still needs global whispering, host permissions, a dossier and an unserved thread |
|
|
194
|
+
|
|
195
|
+
Slack deactivation marks the **whole linked person** unavailable and disables
|
|
196
|
+
injection, even when other identities are linked. Directory sync skips unavailable
|
|
197
|
+
people rather than automatically restoring them.
|
|
198
|
+
|
|
199
|
+
Tool inputs for a deliberate pause and later restore/re-enable, using an actual ID:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{ "action": "set_injection", "personId": "PERSON_ID", "enabled": false }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{ "action": "restore_person", "personId": "PERSON_ID" }
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`restore_person` is for an unavailable person, not a paused active person. After
|
|
210
|
+
inspection, use `set_injection` with `enabled:true` for either one when wanted.
|
|
211
|
+
None of these operations erases raw memory or dossier history.
|
|
212
|
+
|
|
213
|
+
`memory_people_inspect`'s `injectionEligible` and `contribution` are a
|
|
214
|
+
**record-level preview**, not proof that a hook will inject: they do not account
|
|
215
|
+
for the global whisperer switch, host permissions or an existing thread receipt.
|
|
216
|
+
Changing a dossier or restarting the Gateway does not re-inject it in an already
|
|
217
|
+
served thread. A same-run retry replays its saved contribution; a different thread
|
|
218
|
+
can receive the current blurb. Do not delete receipts as routine troubleshooting.
|
|
219
|
+
|
|
220
|
+
For agent research/write steps and the dossier schema, use the packaged
|
|
221
|
+
[People Whisperer skill](../skills/people-whisperer/SKILL.md). If the agent has a
|
|
222
|
+
skill allowlist, include `people-whisperer`. General [search and session filtering](retrieval.md)
|
|
223
|
+
are shared memory features, not people-specific controls.
|