Voice
Memory Hindsight
Native Hindsight memory engine for OpenClaw: memory slot provider runtime, recallToolNames, audience-routed banks, flush and hindsight_* tools.
Install
openclaw plugins install npm:@etzelm/openclaw-memory-hindsight
README
# @etzelm/openclaw-memory-hindsight
A native [Hindsight](https://github.com/vectorize-io/hindsight) memory engine for
[OpenClaw](https://docs.openclaw.ai), packaged as a third-party plugin (plugin id
`hindsight-native`). It owns the memory slot and plugs Hindsight into the host's memory
contracts instead of only hooking prompts:
- **Provider runtime**: `memory.status`, `memory.search` (v2) and `memory.get` in the Gateway,
CLI and Control UI read Hindsight through the host's audience-checked provider API.
- **Auto-recall** before each prompt and **auto-retain** of each finished run (one document per
run, replaced on re-delivery).
- **Agent tools** `hindsight_retain`, `hindsight_recall`, `hindsight_reflect`.
- **Recall tool declaration** (`recallToolNames`): Active Memory uses `hindsight_recall` and
`hindsight_reflect` without a `toolsAllow` list.
- **Pre-compaction flush, tools arm**: before compaction the host runs a silent turn that saves
durable context through `hindsight_retain` (deduplicated per flush id, stable document ids).
- **/learn**: lessons persist through `hindsight_retain` on hosts that have the learn seam
(see [Compatibility](#compatibility)).
- **Audience-based banks**: the host-minted memory audience picks the bank. Owner-private
sessions use the agent's bank (same id as the vendor plugin's per-agent bank, so existing
memory carries over); group chats and other senders get a separate
`<bank>::conv::<hash>` bank per conversation, so their memories never surface in the owner's
private recall.
It only imports `openclaw/plugin-sdk/*`. The single runtime dependency is `typebox`.
> **Runtime support:** memory works on turns that run on OpenClaw's embedded agent runtime. On
> CLI-backed runtimes such as `claude-cli`, OpenClaw (through at least 2026.11.1) does not give
> plugin hooks a memory audience, so this plugin recalls, retains and exposes tools for none of
> those turns. See [Limitations](#limitations).
## Install
Needs OpenClaw 2026.10.1 or newer and a reachable Hindsight API.
From npm:
```sh
openclaw plugins install npm:@etzelm/openclaw-memory-hindsight
```
Released hosts through 2026.10.9 also resolve the bare name
(`openclaw plugins install @etzelm/openclaw-memory-hindsight`) from npm. Newer hosts resolve bare
package names from ClawHub, so the `npm:` prefix keeps the source fixed.
From ClawHub:
```sh
openclaw plugins install clawhub:@etzelm/openclaw-memory-hindsight
```
From GitHub source. `dist/` is not committed and `git:` installs do not run a build, so build a
tarball and install that:
```sh
git clone https://github.com/etzelm/openclaw-memory-hindsight.git
cd openclaw-memory-hindsight
npm ci && npm pack
openclaw plugins install npm-pack:./etzelm-openclaw-memory-hindsight-0.1.1.tgz --force --accept-capabilities
```
`--force` confirms the "outside ClawHub review" warning for a local archive. Every install asks for
capability consent (`--accept-capabilities`) because the plugin reads conversation messages in
`agent_end` (auto-retain) and registers memory-slot surfaces. The installer also reports a
`runtime-code-generation` compatibility note for `typebox` (its schema compiler uses
`Function`); tool schemas are only built, not compiled, by this plugin.
Then configure it, select it for the memory slot, allow it, and restart the Gateway:
```json5
{
plugins: {
allow: [/* ... */, "hindsight-native"], // only if you use an allowlist
slots: { memory: "hindsight-native" },
entries: {
"hindsight-native": {
enabled: true,
hooks: { allowConversationAccess: true }, // auto-retain reads the finished run
config: {
hindsightApiUrl: "http://localhost:8888",
hindsightApiToken: { source: "file", provider: "hindsight", id: "value" },
},
},
},
},
secrets: {
providers: {
hindsight: {
source: "file",
path: "~/.openclaw/secrets/hindsight-api-token",
mode: "singleValue",
},
},
},
}
```
Memory Core can stay enabled as the dreaming sidecar. When another plugin owns the slot it
registers no `memory_search`/`memory_get` tools (host fix openclaw#191028), so there is no recall
tool conflict.
## Configuration
| Key | Default | Meaning |
| --------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------- |
| `hindsightApiUrl` | required | Base URL of the Hindsight API |
| `hindsightApiToken` | none | Bearer token; use a SecretRef |
| `memoryMode` | `hybrid` | `hybrid`: auto-recall and tools; `context`: auto-recall only, no tools, no flush; `tools`: tools only |
| `autoRecall` / `autoRetain` | `true` | Turn the hooks on or off |
| `recallBudget` | `mid` | Hindsight recall budget: `low`, `mid`, `high` |
| `recallTypes` | all | Subset of `world`, `experience`, `observation` |
| `preferObservations` | Hindsight default | Prefer consolidated observations in recall |
| `recallPromptPreamble` | built in | Text above the injected `<hindsight_memories>` block |
| `retainMission` | none | Applied to each bank once before its first write |
| `retainContext` | built in | Context string sent with each retain |
| `excludeProviders` | `[]` | Message providers that never recall or retain (for example `heartbeat`) |
| `skipOperationalSessions` | `true` | Skip cron, heartbeat and subagent sessions |
| `agentBankMap` | `{}` | Agent id to bank id, so several agents share one owner bank |
| `allowInsecureHttp` | `false` | Allow plain http to a non-loopback `hindsightApiUrl` (token and conversation text unencrypted) |
Fixed values (not configurable): recall max tokens 1024, query cap 800 characters, recall
timeout 10 s, retain and reflect timeout 30 s, memory get timeout 10 s (each combined with the
host's abort signal when there is one), retained roles user and assistant, JSON transcript format, recall injected before
the user message (outside the system prompt, so the cached prefix stays stable).
Config changes apply without a restart: the plugin re-reads its entry from the host's current
config snapshot (`api.runtime.config.current()`), falling back to the register-time
`api.pluginConfig`.
### Mapping from `@vectorize-io/hindsight-openclaw`
| Vendor key | Here |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `hindsightApiUrl`, `hindsightApiToken`, `memoryMode`, `autoRecall`, `autoRetain`, `recallBudget`, `recallTypes`, `preferObservations`, `recallPromptPreamble`, `retainMission`, `retainContext`, `excludeProviders`, `skipOperationalSessions`, `agentBankMap` | Same key, same meaning |
| `dynamicBankId`, `dynamicBankGranularity`, `bankIdPrefix` | Replaced by audience routing: owner bank = agent id (or `agentBankMap`), conversations get their own bank |
| `retainRoles`, `recallRoles`, `retainFormat`, `recallMaxTokens`, `recallMaxQueryChars`, `recallTimeoutMs`, `recallInjectionPosition`, `retainSource` | Fixed values (see above) |
| `retainToolCalls`, `retainEveryNTurns`, `retainOverlapTurns`, `recallContextTurns`, `retainTags`, `retainQueue*`, `enableKnowledgeTools`, `allowKnowledgeDelete`, daemon keys (`apiPort`, `embedPort`, `embedVersion`, `daemonIdleTimeout`), `llm*`, `debug*`, `log*`, `skipStatelessSessions` | Not supported; remove them (unknown keys are rejected) |
## Compared with `@vectorize-io/hindsight-openclaw`
Both plugins talk to the same Hindsight API and use the same per-agent owner bank ids. Differences
as of the vendor plugin 1.2.0:
- **`recallToolNames`**: this plugin d
... (truncated)
voice
Comments
Sign in to leave a comment