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. It used to ship inside Hermes as plugins/memory/hindsight/; Nous Research moved every memory provider out of the core tree and handed this one over, so it now lives here and is maintained by the Hindsight team. This directory is the live source, and the Hermes catalog entry points here.
Install
hermes plugins install vectorize-io/hindsight/hindsight-integrations/hermes
hermes memory setup # select "hindsight"
Dependencies in pyproject.toml are installed into the Hermes venv automatically and survive hermes update.
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. Setup also installs
the mode-dependent extras (local_embedded needs hindsight-all, not just the client), so
plugins install on its own leaves the provider reporting "not available" in embedded mode.
While Hermes still bundles plugins/memory/hindsight/, the bundled copy wins — provider lookup
is bundled → ~/.hermes/plugins/ → project → entry point, first hit wins, so installing this plugin
alongside the bundled one is inert. When Hermes drops the bundled copy, hermes update migrates
existing users automatically via hermes_cli/memory_provider_migration.py, which resolves the
provider name against the Hermes plugin catalog. Submitting that entry is our job per the
handoff notes, which makes plugin-catalog-entry.yaml (to be PR'd into NousResearch/hermes-agent
as plugin-catalog/hindsight.yaml) a hard prerequisite of their removal — see the comments in that
file.
local_embedded mode needs hindsight-all, which pyproject.toml deliberately does not declare
(it would push the local-ML stack onto cloud-mode users). The setup wizard installs it, and
embedded.py::_ensure_local_runtime self-installs it on the availability check as a backstop, so
embedded mode no longer depends on the if provider_name == "hindsight" special case in Hermes
core's memory_setup.py — which leaves the tree when the bundled provider does.
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 dependencies automatically via uv, 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.6.1. The plugin auto-upgrades on session start if an older version is detected.
Development
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.