* refactor(openclaw)!: read config from plugin config instead of process.env The plugin loaded credentials and runtime settings from environment variables (HINDSIGHT_API_LLM_*, HINDSIGHT_EMBED_API_*, HINDSIGHT_BANK_ID) plus auto-detection of OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY / GROQ_API_KEY. That tripped OpenClaw's install-scanner env-harvesting rule and bypassed the framework's first-class SecretRef resolution. Switch to reading from the plugin config exclusively, with secrets configured via 'openclaw config set ... --ref-source env|file|exec'. Combined with the daemon lifecycle extraction in #949, this closes the remaining install-scanner findings the 0.5.x plugin was hitting. The plugin source now contains neither process.env nor child_process; the former moved to plugin config (resolved by OpenClaw before the plugin loads), and the latter lives in @vectorize-io/hindsight-all under node_modules where the scanner's directory walker skips it. The plugin can be installed without --dangerously-force-unsafe-install. BREAKING CHANGE: drops the llmApiKeyEnv plugin config field along with the HINDSIGHT_API_LLM_*, HINDSIGHT_EMBED_API_*, and HINDSIGHT_BANK_ID environment variables. Users must now configure llmProvider and llmApiKey explicitly via 'openclaw config set'. Migration guide is in hindsight-docs/docs-integrations/openclaw.md and the integration changelog. * chore(openclaw): pin published versions of hindsight-all and hindsight-client Phase 2 (#949) introduced @vectorize-io/hindsight-all and @vectorize-io/hindsight-client as plugin dependencies using 'file:' workspace paths. Those paths resolve inside the monorepo but break when the published tarball is installed outside it — 'openclaw plugins install @vectorize-io/hindsight-openclaw' failed with 'Cannot find module @vectorize-io/hindsight-all' because npm could not resolve the file: path from the extracted extension directory. Replace both with semver ranges targeting the published versions: @vectorize-io/hindsight-all ^0.1.0 @vectorize-io/hindsight-client ^0.5.0 Verified end-to-end: 'openclaw plugins install <local-tarball>' now succeeds without --dangerously-force-unsafe-install and without the workspace-symlink hack. npm pulls both dependencies from the registry into the extracted extension's node_modules, the plugin loads cleanly, and 'openclaw plugins doctor' reports no issues.
235 lines
12 KiB
Markdown
235 lines
12 KiB
Markdown
# Hindsight Memory Plugin for OpenClaw
|
|
|
|
Biomimetic long-term memory for [OpenClaw](https://openclaw.ai) using [Hindsight](https://vectorize.io/hindsight). Automatically captures conversations and intelligently recalls relevant context.
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Install the plugin
|
|
openclaw plugins install @vectorize-io/hindsight-openclaw
|
|
|
|
# 2. Configure the LLM provider used for memory extraction.
|
|
|
|
# Option A — OpenAI (or any OpenAI-compatible provider)
|
|
openclaw config set plugins.entries.hindsight-openclaw.config.llmProvider openai
|
|
openclaw config set plugins.entries.hindsight-openclaw.config.llmApiKey \
|
|
--ref-source env --ref-provider default --ref-id OPENAI_API_KEY
|
|
|
|
# Option B — Claude Code (no API key needed)
|
|
openclaw config set plugins.entries.hindsight-openclaw.config.llmProvider claude-code
|
|
|
|
# Option C — OpenAI Codex (no API key needed)
|
|
openclaw config set plugins.entries.hindsight-openclaw.config.llmProvider openai-codex
|
|
|
|
# 3. Start OpenClaw
|
|
openclaw gateway
|
|
```
|
|
|
|
That's it! The plugin will automatically start capturing and recalling memories.
|
|
|
|
`llmApiKey` is marked sensitive — `openclaw config set ... --ref-source env` writes a
|
|
SecretRef that resolves the value from your `OPENAI_API_KEY` environment variable at
|
|
runtime, so the key is never stored in plaintext on disk. `--ref-source file` and
|
|
`--ref-source exec` are also supported for mounted-secret and Vault-style setups.
|
|
|
|
## Migrating from 0.5.x
|
|
|
|
0.6.0 removes all process-environment reads from the plugin. Configuration that
|
|
previously came from shell env vars must now go through OpenClaw's plugin config
|
|
(with SecretRef for credentials). Concrete mappings:
|
|
|
|
| Old (0.5.x) | New (0.6.0) |
|
|
|---|---|
|
|
| `OPENAI_API_KEY=…` (auto-detected) | `openclaw config set plugins.entries.hindsight-openclaw.config.llmProvider openai` <br> `openclaw config set plugins.entries.hindsight-openclaw.config.llmApiKey --ref-source env --ref-id OPENAI_API_KEY` |
|
|
| `HINDSIGHT_API_LLM_PROVIDER=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.llmProvider …` |
|
|
| `HINDSIGHT_API_LLM_MODEL=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.llmModel …` |
|
|
| `HINDSIGHT_API_LLM_API_KEY=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.llmApiKey --ref-source env --ref-id …` |
|
|
| `HINDSIGHT_API_LLM_BASE_URL=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.llmBaseUrl …` |
|
|
| `HINDSIGHT_EMBED_API_URL=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.hindsightApiUrl …` |
|
|
| `HINDSIGHT_EMBED_API_TOKEN=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.hindsightApiToken --ref-source env --ref-id …` |
|
|
| `HINDSIGHT_BANK_ID=…` | `openclaw config set plugins.entries.hindsight-openclaw.config.bankId …` |
|
|
| `llmApiKeyEnv: "MY_KEY"` (plugin config) | `llmApiKey` configured as a SecretRef with `--ref-id MY_KEY` |
|
|
|
|
If your shell already exports `OPENAI_API_KEY`, the SecretRef config above resolves
|
|
to the same value at startup — no need to change your shell setup, just point the
|
|
plugin at the variable explicitly. Run `openclaw config validate` after migrating
|
|
to confirm the new shape parses cleanly.
|
|
|
|
## Features
|
|
|
|
- **Auto-capture** and **auto-recall** of memories each turn, injected into system prompt space so recalled memories stay out of the visible chat transcript
|
|
- **Memory isolation** — configurable per agent, channel, user, or provider via `dynamicBankGranularity`
|
|
- **Historical backfill CLI** — import prior OpenClaw session history into Hindsight using the active plugin bank-routing config by default
|
|
- **Retention controls** — choose which message roles to retain, toggle auto-retain on/off, and stamp retained documents with consistent tags/source metadata
|
|
|
|
## Configuration
|
|
|
|
Optional settings in `~/.openclaw/openclaw.json` under `plugins.entries.hindsight-openclaw.config`:
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `apiPort` | `9077` | Port for the local Hindsight daemon |
|
|
| `daemonIdleTimeout` | `0` | Seconds before daemon shuts down from inactivity (0 = never) |
|
|
| `embedPort` | `0` | Port for `hindsight-embed` server (`0` = auto-assign) |
|
|
| `embedVersion` | `"latest"` | hindsight-embed version |
|
|
| `embedPackagePath` | — | Local path to `hindsight-embed` package for development |
|
|
| `bankMission` | — | Agent identity/purpose stored on the memory bank. Helps the engine understand context for better fact extraction. Set once per bank — not a recall prompt. |
|
|
| `llmProvider` | — | LLM provider for memory extraction (`openai`, `anthropic`, `gemini`, `groq`, `ollama`, `openai-codex`, `claude-code`). Required unless `hindsightApiUrl` is set. |
|
|
| `llmModel` | provider default | LLM model used with `llmProvider` |
|
|
| `llmApiKey` | — | API key for the LLM provider. **Sensitive** — set via `openclaw config set ... --ref-source env --ref-id OPENAI_API_KEY` to reference an env var (or `--ref-source file`/`exec` for mounted-secret/Vault sources). |
|
|
| `llmBaseUrl` | — | Optional base URL override for OpenAI-compatible providers (e.g. `https://openrouter.ai/api/v1`) |
|
|
| `dynamicBankId` | `true` | Enable per-context memory banks |
|
|
| `bankId` | — | Static bank ID used when `dynamicBankId` is `false`. |
|
|
| `bankIdPrefix` | — | Prefix for bank IDs (e.g. `"prod"`) |
|
|
| `retainTags` | `[]` | Tags applied to every retained document, useful for cross-agent/source labeling (e.g. `source_system:openclaw`, `agent:agentname`) |
|
|
| `retainSource` | `"openclaw"` | `source` value written into retained document metadata |
|
|
| `dynamicBankGranularity` | `["agent", "channel", "user"]` | Fields used to derive bank ID. Options: `agent`, `channel`, `user`, `provider` |
|
|
| `excludeProviders` | `["heartbeat"]` | Message providers to skip for recall/retain (e.g. `heartbeat`, `slack`, `telegram`, `discord`) |
|
|
| `autoRecall` | `true` | Auto-inject memories before each turn. Set to `false` when the agent has its own recall tool. |
|
|
| `autoRetain` | `true` | Auto-retain conversations after each turn |
|
|
| `retainRoles` | `["user", "assistant"]` | Which message roles to retain. Options: `user`, `assistant`, `system`, `tool` |
|
|
| `retainEveryNTurns` | `1` | Retain every Nth turn. `1` = every turn (default). Values > 1 enable chunked retention with a sliding window. |
|
|
| `retainOverlapTurns` | `0` | Extra prior turns included when chunked retention fires. Window = `retainEveryNTurns + retainOverlapTurns`. Only applies when `retainEveryNTurns > 1`. |
|
|
| `recallBudget` | `"mid"` | Recall effort: `low`, `mid`, or `high`. Higher budgets use more retrieval strategies. |
|
|
| `recallMaxTokens` | `1024` | Max tokens for recall response. Controls how much memory context is injected per turn. |
|
|
| `recallTypes` | `["world", "experience"]` | Memory types to recall. Options: `world`, `experience`, `observation`. Excludes verbose `observation` entries by default. |
|
|
| `recallRoles` | `["user", "assistant"]` | Roles included when building prior context for recall query composition. Options: `user`, `assistant`, `system`, `tool`. |
|
|
| `recallTopK` | — | Max number of memories to inject per turn. Applied after API response as a hard cap. |
|
|
| `recallContextTurns` | `1` | Number of user turns to include when composing recall query context. `1` keeps latest-message-only behavior. |
|
|
| `recallMaxQueryChars` | `800` | Maximum character length for the composed recall query before calling recall. |
|
|
| `recallPromptPreamble` | built-in string | Prompt text placed above recalled memories in the injected `<hindsight_memories>` system-context block. |
|
|
| `hindsightApiUrl` | — | External Hindsight API URL (skips local daemon) |
|
|
| `hindsightApiToken` | — | Auth token for external API. **Sensitive** — set via `openclaw config set ... --ref-source env --ref-id HINDSIGHT_API_TOKEN`. |
|
|
| `ignoreSessionPatterns` | `[]` | Session key glob patterns to skip entirely — no recall, no retain (e.g. `["agent:*:cron:**"]`) |
|
|
| `statelessSessionPatterns` | `[]` | Session key glob patterns for read-only sessions — retain is always skipped; recall is skipped when `skipStatelessSessions` is `true` (e.g. `["agent:*:subagent:**", "agent:*:heartbeat:**"]`) |
|
|
| `skipStatelessSessions` | `true` | When `true`, sessions matching `statelessSessionPatterns` also skip recall. Set to `false` to allow recall but still skip retain. |
|
|
|
|
### Session pattern filtering
|
|
|
|
`ignoreSessionPatterns` and `statelessSessionPatterns` accept glob patterns matched against the session key (format: `agent:<agentId>:<type>:<uuid>`).
|
|
|
|
Glob syntax:
|
|
- `*` — matches any characters except `:` (single segment)
|
|
- `**` — matches anything including `:` (multiple segments)
|
|
|
|
| Pattern | Matches |
|
|
|---|---|
|
|
| `agent:*:cron:**` | All cron sessions for any agent |
|
|
| `agent:*:subagent:**` | All subagent sessions for any agent |
|
|
| `agent:main:**` | All sessions under the `main` agent |
|
|
|
|
**Difference between the two options:**
|
|
|
|
| | `ignoreSessionPatterns` | `statelessSessionPatterns` |
|
|
|---|---|---|
|
|
| Retain | Skipped | Always skipped |
|
|
| Recall | Skipped | Skipped only when `skipStatelessSessions: true` |
|
|
|
|
**Example config** — exclude cron jobs from memory entirely, allow subagents to read but not write memories:
|
|
|
|
```json
|
|
{
|
|
"ignoreSessionPatterns": ["agent:*:cron:**"],
|
|
"statelessSessionPatterns": ["agent:*:subagent:**"],
|
|
"skipStatelessSessions": false
|
|
}
|
|
```
|
|
|
|
## Retention details
|
|
|
|
Retained documents use stable session-scoped IDs like `openclaw:agent:agentname:discord:channel:123:turn:000001` (or `...:window:000002` for chunked retention), and include richer metadata such as `session_key`, `agent_id`, `provider`, `channel_id`, `thread_id`, `sender_id`, `turn_index`, and `retention_scope`.
|
|
|
|
## Documentation
|
|
|
|
For full documentation, configuration options, troubleshooting, and development guide, see:
|
|
|
|
**[OpenClaw Integration Documentation](https://vectorize.io/hindsight/sdks/integrations/openclaw)**
|
|
|
|
## Development
|
|
|
|
To test local changes to the Hindsight package before publishing:
|
|
|
|
1. Add `embedPackagePath` to your plugin config in `~/.openclaw/openclaw.json`:
|
|
```json
|
|
{
|
|
"plugins": {
|
|
"entries": {
|
|
"hindsight-openclaw": {
|
|
"enabled": true,
|
|
"config": {
|
|
"embedPackagePath": "/path/to/hindsight-wt3/hindsight-embed"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
2. The plugin will use `uv run --directory <path> hindsight-embed` instead of `uvx hindsight-embed@latest`
|
|
|
|
3. To use a specific profile for testing:
|
|
```bash
|
|
# Check daemon status
|
|
uvx hindsight-embed@latest -p openclaw daemon status
|
|
|
|
# View logs
|
|
tail -f ~/.hindsight/profiles/openclaw.log
|
|
|
|
# List profiles
|
|
uvx hindsight-embed@latest profile list
|
|
```
|
|
|
|
## Backfilling Existing OpenClaw History
|
|
|
|
The package includes a config-aware backfill CLI for importing historical OpenClaw sessions into Hindsight.
|
|
|
|
By default it mirrors the active plugin settings for:
|
|
|
|
- `dynamicBankId`
|
|
- `dynamicBankGranularity`
|
|
- `bankIdPrefix`
|
|
- local daemon vs external `hindsightApiUrl`
|
|
|
|
Dry-run example:
|
|
|
|
```bash
|
|
npx --package @vectorize-io/hindsight-openclaw hindsight-openclaw-backfill \
|
|
--openclaw-root ~/.openclaw \
|
|
--dry-run
|
|
```
|
|
|
|
Direct invocation from a built checkout:
|
|
|
|
```bash
|
|
node dist/backfill.js --openclaw-root ~/.openclaw --dry-run
|
|
```
|
|
|
|
Migration-oriented overrides are explicit:
|
|
|
|
```bash
|
|
node dist/backfill.js \
|
|
--openclaw-root ~/.openclaw \
|
|
--bank-strategy agent \
|
|
--agent proj-run \
|
|
--resume \
|
|
--max-pending-operations 10
|
|
```
|
|
|
|
Useful options:
|
|
|
|
- `--agent <id>` limit import to selected agents
|
|
- `--exclude-archive` ignore `sessions-archive-from-migration_backup`
|
|
- `--bank-strategy mirror-config|agent|fixed`
|
|
- `--resume` skip only entries already finalized as completed
|
|
- `--checkpoint <path>` store progress outside the default location
|
|
- `--wait-until-drained` block until the touched bank queues have finished and checkpoint state can be finalized
|
|
|
|
## Links
|
|
|
|
- [Hindsight Documentation](https://vectorize.io/hindsight)
|
|
- [OpenClaw Documentation](https://openclaw.ai)
|
|
- [GitHub Repository](https://github.com/vectorize-io/hindsight)
|
|
|
|
## License
|
|
|
|
MIT
|