* 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.
12 KiB
Hindsight Memory Plugin for OpenClaw
Biomimetic long-term memory for OpenClaw using Hindsight. Automatically captures conversations and intelligently recalls relevant context.
Quick Start
# 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 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:
{
"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
Development
To test local changes to the Hindsight package before publishing:
- Add
embedPackagePathto your plugin config in~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"hindsight-openclaw": {
"enabled": true,
"config": {
"embedPackagePath": "/path/to/hindsight-wt3/hindsight-embed"
}
}
}
}
}
-
The plugin will use
uv run --directory <path> hindsight-embedinstead ofuvx hindsight-embed@latest -
To use a specific profile for testing:
# 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:
dynamicBankIddynamicBankGranularitybankIdPrefix- local daemon vs external
hindsightApiUrl
Dry-run example:
npx --package @vectorize-io/hindsight-openclaw hindsight-openclaw-backfill \
--openclaw-root ~/.openclaw \
--dry-run
Direct invocation from a built checkout:
node dist/backfill.js --openclaw-root ~/.openclaw --dry-run
Migration-oriented overrides are explicit:
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-archiveignoresessions-archive-from-migration_backup--bank-strategy mirror-config|agent|fixed--resumeskip only entries already finalized as completed--checkpoint <path>store progress outside the default location--wait-until-drainedblock until the touched bank queues have finished and checkpoint state can be finalized
Links
License
MIT