Hindsight Memory Provider for Hermes Agent
Long-term memory with knowledge graph, entity resolution, and multi-strategy retrieval. Supports cloud, local embedded, and local external modes.
A Hermes Agent memory-provider plugin, installed from
the Hermes plugin catalog. It used to ship inside Hermes as plugins/memory/hindsight/; Nous Research
moved every memory provider out of the core tree, so it is now maintained by the Hindsight team in
vectorize-io/hindsight
and the catalog pins it from there.
Install
Hindsight is in the Hermes plugin catalog, so the name is all you need:
hermes plugins install hindsight
hermes memory setup # select "hindsight"
plugins install asks for confirmation before enabling the plugin. Pass --enable (or
--no-enable) to skip the prompt, which is what you want in a script or an unattended run.
Dependencies in pyproject.toml are installed into the Hermes venv and survive hermes update.
Hermes asks before preparing them: an update that finds new plugin dependencies prints
<plugin> declares Python dependencies and waits for a yes. An unattended hermes update will
sit at that prompt rather than finish.
hermes plugins enable is not what activates a memory provider — Hermes treats providers as
kind: exclusive and its plugin-enable gate deliberately skips them. A provider is activated by
memory.provider: <name> in config.yaml, which hermes memory setup writes.
How local_embedded runs
The Hindsight server is not a dependency of Hermes' venv. local_embedded starts it as a
separate process — an installed hindsight-api binary, else a uvx hindsight-api fallback that
gets its own environment — and talks HTTP to it. This venv keeps only hindsight-client and
hindsight-embed, both declared in pyproject.toml, so every mode installs with the plugin and
nothing has to be fetched at runtime.
That is not a size optimisation, it is the only shape that installs. hindsight-all pulls the whole
hindsight-api-slim tree, which cannot resolve against Hermes' pinned extras: api-slim needs
protobuf>=7.35.1 while mem0ai==2.0.10 and modal==1.5.5 cap it below 7.0, and
opentelemetry-semantic-conventions>=0.65b0 while mistralai==2.4.8 caps it below 0.61. Relaxing
one pin only uncovers the next. It is also 482 MB on macOS arm64 and 3.2 GB on Linux x86_64 (the
CUDA wheels torch pulls there) that cloud-mode users would pay for nothing.
_new_embedded_client therefore composes what the old hindsight.HindsightEmbedded wrapper composed
internally — hindsight_embed.get_embed_manager() plus hindsight_client.Hindsight — instead of
importing it. Existing embedded users keep everything: the profile decides the daemon, so the
database (~/.pg0/instances/hindsight-embed-<profile>/) and the profile env
(~/.hindsight/profiles/<profile>.env) are the same files, read the same way. No migration step, no
re-setup.
The plugin no longer calls tools.lazy_deps.install_specs from anywhere. On package-manager Hermes
that is a retired shim which handed the process to the updater and exited instead of installing, so
every hermes invocation became a ~40s "update" that drained hermes-gateway and still left the
import missing (NousResearch/hermes-agent#126494, fixed upstream in af26acab73 to raise
ImportError). There is nothing left for it to install.
Coming from the built-in provider
Hindsight used to ship inside Hermes as plugins/memory/hindsight/. Nous Research removed that copy
on 2026-09-23 and the provider now installs from the catalog instead. You do not need to do
anything — and your memories are not affected.
hermes update, and agent startup for Desktop users who never run it, calls Hermes'
memory_provider_migration: it sees memory.provider: hindsight configured, finds no provider on
disk, looks the name up in the plugin catalog and installs it at the reviewed commit pin. You'll see:
✓ Memory provider 'hindsight' moved out of core — installed its plugin from the catalog
(your memory.hindsight settings and data are unchanged).
Your data never lived in the Hermes tree: memories are in your Hindsight bank — Hindsight Cloud, or
for local_embedded the profile directory ~/.hindsight/profiles/<profile> and its embedded
PostgreSQL instance. Moving the provider code does not touch any of it, and your
~/.hermes/hindsight/config.json is read exactly as before.
If the migration can't run — offline, or the catalog fetch fails — Hermes prints the manual one-liner rather than starting silently without memory:
hermes plugins install hindsight
Updating
Nothing updates the plugin on its own. Whichever mode you choose below, the code only moves
when you run a command. In particular hermes update does not move it: it reinstalls the
plugin's Python dependencies and leaves the checkout where it is. If you used the built-in
provider, that is the one habit worth unlearning — memory improvements no longer arrive as a side
effect of updating Hermes.
Hermes re-fetches the published catalog at most once every 6 hours, so a freshly released version can take that long to even appear as available.
Follow the official pin (default)
What you get from hermes plugins install hindsight: the commit Nous reviewed and pinned in their
catalog.
hermes plugins update hindsight # move to the catalog's current pin
hermes plugins list flags the plugin update_available once your installed commit differs from
the catalog's. Re-running hermes plugins install hindsight does not update it — it refuses
with "already exists"; plugins update is the command that re-pins.
Pin a specific release
For a version you choose and freeze, install with an explicit commit:
hermes plugins install vectorize-io/hindsight/hindsight-integrations/hermes \
--force --ref <40-character-commit-sha>
Replace the whole placeholder, angle brackets included: < and > are redirection operators in
most shells, so leaving them in makes the command fail to parse. And if you copy both lines, keep
the trailing \ at the end of the first one or join them into a single line, since a \ followed
by anything other than a newline is also a parse error.
--ref takes a full 40-character commit SHA and rejects tag names, so take the SHA from the
release notes of the release you want rather
than typing v1.1.0. The copy button beside a commit on
the plugin's history
gives you the full SHA; the abbreviated one shown on screen is too short.
A --ref install is marked pinned, and hermes plugins update hindsight deliberately refuses to
move it — install again with a new --ref when you want a different version.
Track the latest development code
For fixes before they reach the catalog. Install from the source path rather than the catalog name:
hermes plugins install vectorize-io/hindsight/hindsight-integrations/hermes
hermes plugins update hindsight # now a git pull of our main branch
Unreviewed by definition — you get whatever is on main at the moment you run it.
The catalog entry lives in Nous' repo at
plugin-catalog/hindsight.yaml,
which is what records the current pin.
Requirements
- Cloud: API key from ui.hindsight.vectorize.io
- Local Embedded: API key for a supported LLM provider (OpenAI, Anthropic, Gemini, Groq, OpenRouter, MiniMax, Ollama, or any OpenAI-compatible endpoint). Embeddings and reranking run locally — no additional API keys needed.
- Local External: A running Hindsight instance (Docker or self-hosted) reachable over HTTP.
Setup
hermes memory setup # select "hindsight"
The setup wizard installs nothing (dependencies come with the plugin), walks you through configuration, and offers to seed the bank with a starter memory template (a curated set of dispositions/instructions for common agent roles) — you can skip it, and it warns before overwriting an already-configured bank.
Or manually (cloud mode with defaults):
hermes config set memory.provider hindsight
echo "HINDSIGHT_API_KEY=your-key" >> ~/.hermes/.env
Cloud
Connects to the Hindsight Cloud API. Requires an API key from ui.hindsight.vectorize.io.
Local Embedded
Hermes spins up a local Hindsight daemon with built-in PostgreSQL. Requires an LLM API key for memory extraction and synthesis. The daemon starts automatically in the background on first use and stops after 5 minutes of inactivity.
Supports any OpenAI-compatible LLM endpoint (llama.cpp, vLLM, LM Studio, etc.) — pick openai_compatible as the provider and enter the base URL.
Daemon startup logs: ~/.hermes/logs/hindsight-embed.log
Daemon runtime logs: ~/.hindsight/profiles/<profile>.log
To open the Hindsight web UI (local embedded mode only):
hindsight-embed -p hermes ui start
Local External
Points the plugin at an existing Hindsight instance you're already running (Docker, self-hosted, etc.). No daemon management — just a URL and an optional API key.
Config
Config file: ~/.hermes/hindsight/config.json
Connection
| Key | Default | Description |
|---|---|---|
mode |
cloud |
cloud, local_embedded, or local_external |
api_url |
https://api.hindsight.vectorize.io |
API URL (cloud and local_external modes) |
Memory Bank
| Key | Default | Description |
|---|---|---|
bank_id |
hermes |
Memory bank name (static fallback used when bank_id_template is unset or resolves empty) |
bank_id_template |
— | Optional template to derive the bank name dynamically. Placeholders: {profile}, {workspace}, {platform}, {user}, {session}. Example: hermes-{profile} isolates memory per active Hermes profile. Empty placeholders collapse cleanly (e.g. hermes-{user} with no user becomes hermes). |
bank_mission |
— | Reflect mission (identity/framing for reflect reasoning). Applied via Banks API. |
bank_retain_mission |
— | Retain mission (steers what gets extracted). Applied via Banks API. |
Recall
| Key | Default | Description |
|---|---|---|
recall_budget |
mid |
Recall thoroughness: low / mid / high |
recall_prefetch_method |
recall |
Auto-recall method: recall (raw facts) or reflect (LLM synthesis) |
recall_max_tokens |
4096 |
Maximum tokens for recall results |
recall_max_input_chars |
800 |
Maximum input query length for auto-recall |
recall_prompt_preamble |
— | Custom preamble for recalled memories in context |
recall_tags |
— | Tags to filter when searching memories |
recall_tags_match |
any |
Tag matching mode: any / all / any_strict / all_strict |
recall_types |
observation |
Fact types surfaced by recall (both auto-recall and the hindsight_recall tool). Comma-separated string or JSON list. Default narrowed to observation only (see "Behavior change" below). Set to observation,world,experience to also include raw facts. |
auto_recall |
true |
Automatically recall memories before each turn |
recall_sync |
false |
Recall synchronously against the current message each turn (higher relevance, adds recall latency). Default off: recall runs in the background and is injected on the next turn. |
recall_indicator |
true |
Show a 👁️ Hindsight — recalled N memories status line when auto-recall injects memory. Turn off for customer-facing agents. |
Behavior change —
recall_typesdefaults toobservationonly.Previously recall returned all three fact types. It now returns only observations.
Per Hindsight's docs, observations are the consolidated knowledge layer Hindsight builds on top of raw facts: deduplicated beliefs grounded in evidence, refined as new facts arrive, with proof counts and freshness signals. Raw
world/experiencefacts are the individual supporting evidence that feeds them. For per-turn context injection, observations are denser per token and avoid feeding the model multiple raw facts that one observation already summarizes.Restore the broad recall with
"recall_types": "observation,world,experience"(string or JSON list) in~/.hermes/hindsight/config.json. This applies to both auto-recall and thehindsight_recalltool — both read the samerecall_typessetting (the tool schema has no per-calltypesargument), so narrowing the default narrows both paths.
Retain
| Key | Default | Description |
|---|---|---|
auto_retain |
true |
Automatically retain conversation turns |
retain_async |
true |
Process retain asynchronously on the Hindsight server |
retain_every_n_turns |
1 |
Retain every N turns (1 = every turn) |
retain_context |
conversation between Hermes Agent and the User |
Context label for retained memories |
retain_tags |
— | Default tags applied to retained memories; merged with per-call tool tags |
retain_source |
— | Opt-in metadata.source attached to retained memories (identifies the storing client, e.g. hermes). Empty by default — no attribution tag ships unless you set it. |
retain_indicator |
true |
Show a 👁️ Hindsight — saving to memory… status line when a turn is saved. Turn off for customer-facing agents. |
retain_user_prefix |
User |
Label used before user turns in auto-retained transcripts |
retain_assistant_prefix |
Assistant |
Label used before assistant turns in auto-retained transcripts |
Integration
| Key | Default | Description |
|---|---|---|
memory_mode |
hybrid |
How memories are integrated into the agent |
memory_mode:
hybrid— automatic context injection + tools available to the LLMcontext— automatic injection only, no tools exposedtools— tools only, no automatic injection
Local Embedded LLM
| Key | Default | Description |
|---|---|---|
llm_provider |
openai |
openai, anthropic, gemini, groq, openrouter, minimax, ollama, lmstudio, openai_compatible |
llm_model |
per-provider | Model name (e.g. gpt-4o-mini, qwen/qwen3.5-9b) |
llm_base_url |
— | Endpoint URL for openai_compatible (e.g. http://192.168.1.10:8080/v1) |
The LLM API key is stored in ~/.hermes/.env as HINDSIGHT_LLM_API_KEY.
The embedded daemon is a subprocess that cannot see the per-turn secret
scope, so it reads the key from ~/.hindsight/profiles/<profile>.env
(materialized owner-only at setup and on config change). Key resolution
order is explicit config → secret scope → the on-disk profile env, and the
rewrite path is fail-closed: a build with no key never clobbers a profile
file that already holds one.
Tools
Available in hybrid and tools memory modes:
| Tool | Description |
|---|---|
hindsight_retain |
Store information with auto entity extraction; supports optional per-call tags |
hindsight_recall |
Multi-strategy search (semantic + entity graph) |
hindsight_reflect |
Cross-memory synthesis (LLM-powered) |
Environment Variables
| Variable | Description |
|---|---|
HINDSIGHT_API_KEY |
API key for Hindsight Cloud |
HINDSIGHT_LLM_API_KEY |
LLM API key for local mode |
HINDSIGHT_API_LLM_BASE_URL |
LLM Base URL for local mode (e.g. OpenRouter) |
HINDSIGHT_API_URL |
Override API endpoint |
HINDSIGHT_BANK_ID |
Override bank name |
HINDSIGHT_BUDGET |
Override recall budget |
HINDSIGHT_MODE |
Override mode (cloud, local_embedded, local_external) |
Client Version
Requires hindsight-client >= 0.10.1 and, for local_embedded, hindsight-embed >= 0.10.1. A version below
the floor only logs a warning; hermes plugins update hindsight moves the environment.
The floor is 0.10.1 rather than the 0.6.1 this plugin needs at the API level because
hindsight-embed 0.10.0 breaks local_embedded outright: its daemon probe cleared the calling
thread's event loop, so the next client call failed with Timeout context manager should be used inside a task. If you installed between 2026-09-14 and 2026-09-21, run hermes update (or
hermes plugins update hindsight) to move off it.
Hermes Gateway (Telegram, Discord, Slack)
The provider works across every gateway platform. Hermes builds a fresh agent per message, and the provider is re-initialized with it, so auto-recall runs for each turn regardless of platform.
Two settings are worth turning off for customer-facing bots: recall_indicator and
retain_indicator, which otherwise print a 👁️ Hindsight status line into the user's channel.
Disabling Hermes' built-in memory
Hermes has its own memory store backed by local markdown (MEMORY.md, plus a slimmer USER.md
profile). With both active the model may prefer the built-in one, so turn the flat-file stores off:
hermes config set memory.memory_enabled false
hermes config set memory.user_profile_enabled false # optional: the USER.md profile
Setting both to false removes the built-in memory tool from the agent entirely. Re-enable later
by setting the same flags back to true.
Troubleshooting
Tools don't appear in /tools — the provider skips tool registration when it isn't configured.
Check hermes memory status reports hindsight as the active provider and Status: available. In
memory_mode: context the tools are hidden on purpose.
Status: not available in local_embedded — this plugin's own packages
(hindsight-client, hindsight-embed) are missing from the environment, which happens when a venv
rebuild dropped the plugin member. Run hermes pm repair and restart Hermes to rebuild them. The Hindsight server is not needed in that venv — it runs as a separate
process, and first use downloads it if no hindsight-api binary is present yet.
Timeout context manager should be used inside a task — hindsight-embed 0.10.0. Run
hermes plugins update hindsight to move to the 0.10.1 floor.
Local daemon not starting — check the logs:
cat ~/.hermes/logs/hindsight-embed.log # startup
cat ~/.hindsight/profiles/<profile>.log # daemon runtime
Recall returns nothing — memories need at least one retain cycle, and extraction is an LLM call. Store a fact, then ask about it on a later turn.
Development
Releasing
./scripts/release-integration.sh hermes patch # or minor / major / an explicit semver
That bumps the version in both pyproject.toml and plugin.yaml (Hermes reads the latter —
it is the version hermes plugins list and the catalog card show), writes the changelog entry,
regenerates the docs skill, commits, and pushes the tag integrations/hermes/vX.Y.Z.
Then open a follow-up PR against NousResearch/hermes-agent bumping sha and version
together in plugin-catalog/hindsight.yaml. Until that lands, installs stay on the old commit —
the tag alone reaches nobody.
Put the released commit SHA in the release notes. Hermes' --ref takes a 40-character SHA and
rejects tag names (_EXACT_COMMIT_RE), so a user pinning to a specific release needs the SHA, not
v1.1.0.
First release only: the release creates changelog/integrations/hermes, and
check-integrations.mjs then requires the doc page to link it. The page is generated, so add the
link to this README (as the other integrations do, absolute so it also works on GitHub):
[View Changelog →](https://hindsight.vectorize.io/changelog/integrations/hermes). It cannot go in
earlier — the docs build runs onBrokenLinks: 'throw' and the page does not exist until the
release commit.
This README is the single source for the docs page. After editing it, regenerate:
node hindsight-docs/scripts/sync-hermes-doc.mjs
The docs build runs the same script with --check, so a stale page fails the build.
uv sync
uv run pytest tests -v
Hermes Agent is not on PyPI, so tests/conftest.py stubs the Hermes core interfaces the
plugin imports (MemoryProvider, the secret scope, cfg_get, ...) and loads this directory
as a package, the way Hermes' plugin loader does. A recording fake client stands in for the
Hindsight SDK so the tests assert what the provider actually sends.
Things to know when changing this plugin:
config_schema.pyimports fromplugins.memory.config_schemaon purpose: Hermes core loads that file directly and its dashboard expects core'sProviderConfigSchematype, so it must not be vendored.- The setup wizard imports private helpers from
hermes_cli.memory_setup(_curses_select,_prompt, ...). Those are Hermes internals, not a public API — expect to own a copy or drop the wizard hook if they move. pyproject.tomlis the only dependency authority; bump it when a newer client is needed.
