Your Memory Provider's Recall Was Being Truncated: Opt-In Spilling and Two Other Silent Failures

You wire an external memory provider into Hermes — Hindsight, Mem0, Honcho, any of them. For a couple of weeks it genuinely remembers you. Then one day you mention the API contract you agreed on last week, and it answers like it never heard of it. You blame the model, or assume the provider lost the write. The real story is more annoying: the recall was fetched, and then Hermes itself replaced it with the first few paragraphs, the last few paragraphs, and a file path.
That behavior changed on October 9, in three merged fixes covering three silent failures around external memory plugins: truncated recall, providers that go missing from hermes memory status, and an install that retries on every single start. Here’s each symptom, its mechanism and what to do about it.
Symptom one: recall gets truncated with no warning
Hermes has a general “spill” mechanism: when a hook’s output crosses a size threshold, the full text is not placed in context. A head-and-tail preview takes its place, with a file path for the rest. For ordinary plugin hooks that default is sensible — one chatty plugin shouldn’t eat your context window.
The catch was that the same mechanism applied to external memory prefetch recall. So a provider that had already applied its own recall budget got trimmed a second time by Hermes: the relevance-ranked middle disappeared from view, and the model saw only the beginning and the end.
The fix makes that an explicit choice (PR #135157):
# ~/.hermes/config.yaml
memory:
prefetch_spill_enabled: false # default: external recall stays intact
The details are worth knowing:
- Default false. External recall reaches the model whole. A safety ceiling still exists: recall above 10×
hooks.output_spill.max_chars(at least 100,000 characters) still spills, so a runaway provider can’t overflow the context window. - Set it true and you get the old behavior back: oversized recall becomes a head/tail preview plus a file path. It reuses the shared
hooks.output_spillthreshold, preview lengths and directory — andhooks.output_spill.enabled: falsestill overrides everything. - Normal plugin-hook spilling is unchanged and stays on by default, independently of this memory setting.
- The setting is snapshotted when the provider registers, so restart Hermes after changing it; an in-flight conversation won’t change behavior mid-turn.
- The official docs put it plainly: when your provider has its own recall budget, prefer that. It knows better than a truncation rule what to keep.
One honest trade-off: keeping full recall makes prompts bigger. If you’re on metered tokens and run a talkative memory service, turning prefetch_spill_enabled back on can save money — as long as you accept that the middle of the recall is less visible.
Symptom two: your provider vanishes from hermes memory status
The second fix (PR #135524) is one changed line plus a docstring line, and it matters more than its size suggests.
To decide whether a plugin folder is a memory provider, Hermes looks for register_memory_provider or MemoryProvider in its __init__.py. That’s a cheap scan with no imports — but it only read the first 8 KB of the file. A perfectly working provider with a long module docstring was skipped: missing from hermes memory status, and hermes memory setup <name> said “not found”.
The catalog plugin excel_line hit exactly this, and the workaround at the time was grim: shorten the docstring so the registration code landed inside the first 8 KB (#135442 / #135473). That workaround is no longer needed. The fast path stays (still a cheap 8 KB text check); only when it finds nothing does it fall back to the existing _defines_memory_provider, which parses the package’s top-level modules without importing them. Providers that already matched pay nothing extra — only folders that miss pay for one AST parse.
If you wrote a plugin that installs but is never detected: stop deleting your docs, and update instead.
Symptom three: the provider reinstalls itself on every start
The third fix (PR #135529) addresses a snowballing retry loop.
A memory provider’s automatic install runs at agent start — hermes chat, a cron run, a gateway agent, a Desktop restart, each counts. Before the fix, a failed install was retried on every one of those starts, and every retry was recorded as a fresh failure. The PR’s telemetry (14 days, deduped) shows what that produced:
| plugin | ok | failed | failing install-days | failed per failing install-day |
|---|---|---|---|---|
| hindsight | 130 | 1048 | 204 | 5.1 |
| mnemosyne | 47 | 288 | 83 | 3.5 |
Hindsight’s daily failures climbed 8 → 47 → 170 → 204 between 09-29 and 10-02, mostly the same handful of failures being counted over and over, on top of a smaller set of genuine network errors (PM’s uv lock, git clone). The conclusion in the PR is blunt: this is a retry loop, not 1,048 distinct faults.
The semantics are now clean: STARTUP_RETRY_SECONDS = 3600.0 in hermes_cli/memory_provider_migration.py — a provider whose automatic install failed is not retried by any process for an hour. When it does come up again, it tells you what to run:
Its automatic install failed less than an hour ago: run `hermes plugins install hindsight`
The same PR fixed a related misdiagnosis: when plugins/<name> already exists as a symlink to somewhere else, a catalog install now says the slot is taken instead of blaming the plugin’s manifest.
How to check your own setup
hermes memory status # which external provider is active, and whether it's installed
hermes memory setup # pick or configure a provider (also mentions a missing install)
hermes memory off # disable the external provider
hermes plugins list # is the plugin present?
A practical triage order for “it forgot something”: confirm the provider is present with hermes memory status, then read memory.provider and prefetch_spill_enabled in config.yaml, then decide whether the model never received the recall (configuration) or the provider never stored it (service). For background on choosing a memory backend, see our semantic-memory walkthrough and the dreaming / memory consolidation feature; the full command surface is in the hermes memory reference.
Release status
All three fixes merged on 2026-10-09, after v0.21.6 shipped on October 8, so they are on origin/main only for now — wait for the next release or run hermes update. For how plugins get reviewed and pinned in the first place, see the plugin catalog guide.
The takeaway
All three are silent failures: no error, no log line, just quietly worse behavior — recall trimmed, a plugin skipped, one failure counted a thousand times. They survived so long because each one lives in a layer users can’t see. If you run an external memory provider, the single most useful thing you can do today is open config.yaml, look at memory.prefetch_spill_enabled, and decide whether you want complete recall or a smaller prompt.