hermes - 💡(How to fix) Fix engram memory plugin causes silent 30-min gateway hang on Engram 0.3.0 CLOUD_MODE — and reveals missing env-driven config baseline across bundled memory plugins

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

Gateway log: no error, just retry timing

(a) Surface plugin failures at WARN. Independently of the env-config fix, the silent 30-min retry is its own UX cliff and overlaps with the observability gap of #27474. Logging the upstream HTTP status once at WARN level on the first memory-provider failure of a session would let operators attribute a freeze to the memory plugin without tcpdump or backend-side logs. Happy to scope a separate issue.

Root Cause

Root cause is a two-line gap in plugins/memory/engram/__init__.py: the URL is hardcoded and no auth header is emitted. Patch is ready and fully backwards compatible.

Fix Action

Fix / Workaround

Root cause is a two-line gap in plugins/memory/engram/__init__.py: the URL is hardcoded and no auth header is emitted. Patch is ready and fully backwards compatible.

Proposed patch — minimal, backwards compatible

Patch ready locally and validated against both default-localhost and remote-authenticated setups. Will open a PR if maintainers confirm the approach (env names, single-header X-API-Key vs also accepting Authorization: Bearer, etc.).

Code Example

# 1. Run Engram Core 0.3.0 with CLOUD_MODE=true (the documented secure default)
# 2. Configure any Hermes profile with memory.provider: engram in config.yaml
# 3. Send any message that triggers memory read/write (most do — session search runs every turn)

# Backend log:   POST /v1/search HTTP/1.1 401 Unauthorized
# Gateway log:   no error, just retry timing
# User sees:     ⏳ Still working... iteration 1/90, waiting for stream response
#                (~30 minutes per message before timeout)

---

ENGRAM_BASE = "http://localhost:8100"

# in _api_request():
req.add_header("X-Namespace", ns)
with urllib.request.urlopen(req, timeout=timeout) as r:
    ...

---

ENGRAM_BASE = os.environ.get("ENGRAM_BASE", "http://localhost:8100")
ENGRAM_API_KEY = os.environ.get("ENGRAM_API_KEY", "")

# in _api_request() and _list_memories():
req.add_header("X-Namespace", ns)
if ENGRAM_API_KEY:
    req.add_header("X-API-Key", ENGRAM_API_KEY)
with urllib.request.urlopen(req, timeout=timeout) as r:
    ...
RAW_BUFFERClick to expand / collapse

TL;DR

Enabling Engram Core 0.3.0's recommended CLOUD_MODE posture turns the bundled engram memory plugin into a silent failure: every memory op returns 401 Unauthorized, the gateway retries for ~30 minutes per message, and no log surfaces the cause. To the end-user, Hermes looks frozen.

Root cause is a two-line gap in plugins/memory/engram/__init__.py: the URL is hardcoded and no auth header is emitted. Patch is ready and fully backwards compatible.

Investigating also surfaces a wider pattern worth surfacing for triage: engram is the only bundled memory plugin that doesn't read endpoint + credentials from env vars. The other four (mem0, supermemory, honcho, hindsight) all do — so this isn't a new convention to introduce, it's an existing one that engram has drifted away from.

Triage context: the user-visible behavior (gateway hangs ~30 min on the default secure posture of Engram 0.3.0, with no actionable log) is closer to the bug pattern of #27226 / #27474 than to a feature gap — flagged here in case the current type/feature + P3 labels (auto-applied at open time) deserve a second look.

Reproduction

# 1. Run Engram Core 0.3.0 with CLOUD_MODE=true (the documented secure default)
# 2. Configure any Hermes profile with memory.provider: engram in config.yaml
# 3. Send any message that triggers memory read/write (most do — session search runs every turn)

# Backend log:   POST /v1/search HTTP/1.1 401 Unauthorized
# Gateway log:   no error, just retry timing
# User sees:     ⏳ Still working... iteration 1/90, waiting for stream response
#                (~30 minutes per message before timeout)

/v1/health returns 200 without auth, so basic probes pass. The failure is invisible unless the operator tails the Engram-side logs directly.

Related open issues — this fits an existing cluster

Three sibling issues opened the same day (2026-05-17), all under tool/memory + comp/plugins, point at the same broader pattern of memory-plugin config/observability gaps:

  • #27314 — Honcho memory provider: support runtime peer alias/prefix mapping for multi-user gateways. Same class of concern: a memory plugin can't be configured for multi-tenant / multi-user deployments without source forks.
  • #27226 — Supermemory default/My Space config can create a literal default container. Plugin treats hardcoded sentinels incorrectly, silently splits user memory. Labeled type/bug P2.
  • #27474 — hindsight embedded daemon profile mismatch causes false 'not available' status. Memory plugin silent observability failure — status reports wrong without explaining why. Labeled type/bug P3.

The engram silent-401 + 30-min hang is the same family of failure: a bundled memory plugin whose configuration model can't keep up with how the upstream service evolves (or with non-default deployment shapes), surfacing as silent UX cliffs at the gateway. Treating these as a cluster (rather than as four isolated tickets) might be worth a maintainer-side decision.

Who is affected by the engram instance specifically

Three concrete classes of user are blocked or about to be:

1. Anyone upgrading Engram Core to 0.3.0 with auth enabled. This is the documented Engram recommendation and the default in fresh installs. After upgrade, every Hermes profile using memory.provider: engram enters the 30-min retry loop on every message.

2. Anyone running Engram on a non-localhost host. A reasonable production split (gateway and memory backend on different VMs / containers) is impossible today without forking the plugin into $HERMES_HOME/plugins/ — the URL is hardcoded to http://localhost:8100.

3. Anyone running multiple Hermes profiles against different memory tenants (dev/staging/prod, multi-org, isolating an experimental profile from production memory). Today this requires duplicating the plugin source per profile — the exact pain that #27314 reports for Honcho.

Why the fix is more than a one-line tweak — engram is an outlier in this repo

A quick grep of plugins/memory/*/__init__.py:

PluginEndpoint via envCredential via env
mem0MEM0_BASE_URLMEM0_API_KEY
supermemorySUPERMEMORY_BASE_URLSUPERMEMORY_API_KEY
honchoHONCHO_BASE_URLHONCHO_API_KEY
hindsightHINDSIGHT_BASE_URLHINDSIGHT_API_KEY
engram❌ hardcoded http://localhost:8100❌ no auth header emitted at all

Four of five bundled memory plugins already follow 12-factor — env-driven endpoint + credential is the de facto convention. Engram is the only one without that safety net, which is exactly why it broke silently when its upstream service evolved its auth posture. Bringing engram back into the convention closes the immediate bug and removes the seam where this class of failure can re-emerge for the next plugin.

Current plugin code (plugins/memory/engram/__init__.py)

ENGRAM_BASE = "http://localhost:8100"

# in _api_request():
req.add_header("X-Namespace", ns)
with urllib.request.urlopen(req, timeout=timeout) as r:
    ...

Proposed patch — minimal, backwards compatible

ENGRAM_BASE = os.environ.get("ENGRAM_BASE", "http://localhost:8100")
ENGRAM_API_KEY = os.environ.get("ENGRAM_API_KEY", "")

# in _api_request() and _list_memories():
req.add_header("X-Namespace", ns)
if ENGRAM_API_KEY:
    req.add_header("X-API-Key", ENGRAM_API_KEY)
with urllib.request.urlopen(req, timeout=timeout) as r:
    ...

Defaults preserve the exact current behavior (localhost:8100, no auth header) — zero impact on existing installs. Aligns engram with how mem0/supermemory/honcho/hindsight are already configured.

Suggested follow-up scopes (optional, separate issues)

(a) Surface plugin failures at WARN. Independently of the env-config fix, the silent 30-min retry is its own UX cliff and overlaps with the observability gap of #27474. Logging the upstream HTTP status once at WARN level on the first memory-provider failure of a session would let operators attribute a freeze to the memory plugin without tcpdump or backend-side logs. Happy to scope a separate issue.

(b) Make the env-driven contract explicit. If maintainers want, a short docs section ("expected env names for bundled memory plugins") — or a tiny base-class helper exposing endpoint_from_env(name, default) / auth_header_from_env(name) — would give future plugins an obvious template and prevent another silent drift. Touches the same surface as #27314 (per-plugin runtime knobs).

Versions tested

  • Engram Core 0.3.0 (CLOUD_MODE=true, X-API-Key auth)
  • Hermes Agent recent main

PR

Patch ready locally and validated against both default-localhost and remote-authenticated setups. Will open a PR if maintainers confirm the approach (env names, single-header X-API-Key vs also accepting Authorization: Bearer, etc.).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING