Skip to content

fix(hermes): seed AGENTMEMORY_URL default at import (closes #520)#643

Merged
rohitg00 merged 1 commit into
mainfrom
fix/hermes-status-520
May 25, 2026
Merged

fix(hermes): seed AGENTMEMORY_URL default at import (closes #520)#643
rohitg00 merged 1 commit into
mainfrom
fix/hermes-status-520

Conversation

@rohitg00
Copy link
Copy Markdown
Owner

@rohitg00 rohitg00 commented May 25, 2026

Summary

Closes #520. Hermes was reporting agentmemory as Missing/not available even when the service was running fine and live Hermes sessions could use it.

Root cause

hermes memory status reads os.environ in the Hermes CLI process. When agentmemory is launched by systemd or any process manager that loads ~/.agentmemory/.env via EnvironmentFile=, those values never reach the interactive shell.

Our plugin already preloads ~/.agentmemory/.env via setdefault at import time, but only catches uncommented key=value lines. Users whose .env has AGENTMEMORY_URL commented out (because it matches the default http://localhost:3111) end up with the var unset, and Hermes reports Missing.

Fix

One line at the end of _preload_agentmemory_dotenv():

os.environ.setdefault("AGENTMEMORY_URL", DEFAULT_BASE_URL)

Guarantees AGENTMEMORY_URL is set to the documented default after import, so hermes memory status reflects the real runtime instead of the absence of a shell env var. Anything explicit from the shell or .env still wins — setdefault is a no-op when the value is already present.

AGENTMEMORY_SECRET stays untouched. It's optional per get_config_schema() ("required": False); Hermes reporting an optional field as Missing is a separate upstream UI question.

Test plan

  • New regression test in test/hermes-plugin.test.ts matches the setdefault line in __init__.py
  • npm test — 1097 / 1097 pass (99 files), no regression
  • Manual: python3 -c "import hermes; print(os.environ['AGENTMEMORY_URL'])" with empty HOME returns http://localhost:3111
  • Manual: python3 -c "AGENTMEMORY_URL=http://10.0.0.5:3111 import hermes; print(os.environ['AGENTMEMORY_URL'])" still returns 10.0.0.5 — explicit env wins

Notes for #520 reporter

The fix also makes is_available() return True for default-localhost setups, since _validate_url("http://localhost:3111") succeeds. The user-suggested Authorization-header patch is a separate path — hermes memory status does its own health check inside Hermes core, not via our plugin. If that health check fails for users with AGENTMEMORY_SECRET set, that's a Hermes-side fix; happy to file an upstream issue if confirmed.

Summary by CodeRabbit

  • Bug Fixes

    • Resolved issue where hermes memory status incorrectly displayed provider as missing.
  • Tests

    • Added test case validating default memory URL configuration.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentmemory Ready Ready Preview, Comment May 25, 2026 10:47am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aecb4f30-b26b-479d-ade4-6fe774a78646

📥 Commits

Reviewing files that changed from the base of the PR and between 7803fa9 and 7279aeb.

📒 Files selected for processing (2)
  • integrations/hermes/__init__.py
  • test/hermes-plugin.test.ts

📝 Walkthrough

Walkthrough

The Hermes plugin now ensures AGENTMEMORY_URL is populated in the process environment at import time by calling os.environ.setdefault() with DEFAULT_BASE_URL. A test verifies this initialization behavior via regex assertion.

Changes

Hermes plugin environment initialization

Layer / File(s) Summary
Hermes URL environment setup
integrations/hermes/__init__.py, test/hermes-plugin.test.ts
_preload_agentmemory_dotenv() ensures AGENTMEMORY_URL is set to DEFAULT_BASE_URL if unset. New test verifies the setdefault call exists at import time.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

A rabbit hops through dotenv lines,
Setting defaults, all is fine,
AGENTMEMORY_URL now shines,
No missing providers in sight, divine!
🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main fix: seeding AGENTMEMORY_URL with a default value at import time to resolve the issue where Hermes incorrectly reported the service as missing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hermes-status-520

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Hermes was reporting agentmemory as Missing/not-available even when the
service was running fine and live sessions could use it. Root cause:
`hermes memory status` reads os.environ in the Hermes CLI process. When
agentmemory is launched by systemd (or any process manager that loads
~/.agentmemory/.env via EnvironmentFile=), those values never reach the
interactive shell. Our plugin already preloads ~/.agentmemory/.env via
setdefault, but only catches uncommented key=value lines. Users whose
.env file has AGENTMEMORY_URL commented out (because it matches the
default http://localhost:3111) end up with the var unset, and Hermes
reports Missing.

Fix: after preload, os.environ.setdefault('AGENTMEMORY_URL',
DEFAULT_BASE_URL). Guarantees the var is set to the documented default
so Hermes status reflects the real runtime. Anything explicit from the
shell or .env still wins (setdefault is no-op when value is present).

AGENTMEMORY_SECRET stays untouched — it's optional per the config
schema.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/hermes-plugin.test.ts (1)

65-70: ⚡ Quick win

Strengthen this regression test to assert import-time execution too.

This currently verifies source text only. Add a second assertion that _preload_agentmemory_dotenv() is invoked at module scope so the “at import time” contract is covered.

Proposed test hardening
   it("preloads AGENTMEMORY_URL default at import time (`#520`)", () => {
     const source = readFileSync("integrations/hermes/__init__.py", "utf8");
     expect(source).toMatch(
       /os\.environ\.setdefault\(\s*["']AGENTMEMORY_URL["']\s*,\s*DEFAULT_BASE_URL\s*\)/,
     );
+    expect(source).toMatch(/^\s*_preload_agentmemory_dotenv\(\)\s*$/m);
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/hermes-plugin.test.ts` around lines 65 - 70, The test currently only
checks source text for setting AGENTMEMORY_URL; add a second assertion that the
helper function _preload_agentmemory_dotenv() is invoked at module scope to
prove import-time execution. Locate integrations/hermes/__init__.py and in
test/hermes-plugin.test.ts add an assertion that the module contains a top-level
call to _preload_agentmemory_dotenv (e.g. a regex match for
/_preload_agentmemory_dotenv\(\s*\)/ or import the module and verify side-effect
behavior), so both the os.environ.setdefault(...) and the actual invocation of
_preload_agentmemory_dotenv are asserted.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integrations/hermes/__init__.py`:
- Around line 93-97: The current use of os.environ.setdefault("AGENTMEMORY_URL",
DEFAULT_BASE_URL) only sets the default when the key is missing but doesn't
handle cases where AGENTMEMORY_URL exists but is empty or a placeholder like
"${AGENTMEMORY_URL}"; update the logic (around os.environ.setdefault usage in
integrations/hermes/__init__.py) to treat empty strings and common placeholder
patterns as unset by: read os.environ.get("AGENTMEMORY_URL"), and if the value
is falsy or matches placeholder patterns (e.g., "${AGENTMEMORY_URL}" or only
whitespace), assign DEFAULT_BASE_URL to os.environ["AGENTMEMORY_URL"] so the
rest of the code uses the documented default.

---

Nitpick comments:
In `@test/hermes-plugin.test.ts`:
- Around line 65-70: The test currently only checks source text for setting
AGENTMEMORY_URL; add a second assertion that the helper function
_preload_agentmemory_dotenv() is invoked at module scope to prove import-time
execution. Locate integrations/hermes/__init__.py and in
test/hermes-plugin.test.ts add an assertion that the module contains a top-level
call to _preload_agentmemory_dotenv (e.g. a regex match for
/_preload_agentmemory_dotenv\(\s*\)/ or import the module and verify side-effect
behavior), so both the os.environ.setdefault(...) and the actual invocation of
_preload_agentmemory_dotenv are asserted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eda5b2b5-8970-4213-8f21-2eca90d1e423

📥 Commits

Reviewing files that changed from the base of the PR and between ca08975 and 7803fa9.

📒 Files selected for processing (4)
  • README.md
  • docs/recipes/pairings.md
  • integrations/hermes/__init__.py
  • test/hermes-plugin.test.ts

Comment on lines +93 to +97
# Guarantee AGENTMEMORY_URL is set so `hermes memory status` never
# reports it as Missing when a user runs agentmemory at the default
# localhost:3111 (or via systemd with the URL line commented out in
# ~/.agentmemory/.env because it matches the default). #520.
os.environ.setdefault("AGENTMEMORY_URL", DEFAULT_BASE_URL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Treat empty/placeholder AGENTMEMORY_URL as unset before defaulting.

setdefault only applies when the key is missing. If AGENTMEMORY_URL is present but empty (or a literal ${AGENTMEMORY_URL}), Hermes can still report unavailable instead of using the documented default.

Proposed fix
-    os.environ.setdefault("AGENTMEMORY_URL", DEFAULT_BASE_URL)
+    raw_url = (os.environ.get("AGENTMEMORY_URL") or "").strip()
+    if not raw_url or (raw_url.startswith("${") and raw_url.endswith("}")):
+        os.environ["AGENTMEMORY_URL"] = DEFAULT_BASE_URL
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Guarantee AGENTMEMORY_URL is set so `hermes memory status` never
# reports it as Missing when a user runs agentmemory at the default
# localhost:3111 (or via systemd with the URL line commented out in
# ~/.agentmemory/.env because it matches the default). #520.
os.environ.setdefault("AGENTMEMORY_URL", DEFAULT_BASE_URL)
# Guarantee AGENTMEMORY_URL is set so `hermes memory status` never
# reports it as Missing when a user runs agentmemory at the default
# localhost:3111 (or via systemd with the URL line commented out in
# ~/.agentmemory/.env because it matches the default). `#520`.
raw_url = (os.environ.get("AGENTMEMORY_URL") or "").strip()
if not raw_url or (raw_url.startswith("${") and raw_url.endswith("}")):
os.environ["AGENTMEMORY_URL"] = DEFAULT_BASE_URL
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/hermes/__init__.py` around lines 93 - 97, The current use of
os.environ.setdefault("AGENTMEMORY_URL", DEFAULT_BASE_URL) only sets the default
when the key is missing but doesn't handle cases where AGENTMEMORY_URL exists
but is empty or a placeholder like "${AGENTMEMORY_URL}"; update the logic
(around os.environ.setdefault usage in integrations/hermes/__init__.py) to treat
empty strings and common placeholder patterns as unset by: read
os.environ.get("AGENTMEMORY_URL"), and if the value is falsy or matches
placeholder patterns (e.g., "${AGENTMEMORY_URL}" or only whitespace), assign
DEFAULT_BASE_URL to os.environ["AGENTMEMORY_URL"] so the rest of the code uses
the documented default.

@rohitg00 rohitg00 merged commit d38a1c6 into main May 25, 2026
6 of 7 checks passed
@rohitg00 rohitg00 deleted the fix/hermes-status-520 branch May 25, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] "hermes memory status" reports agentmemory as unavailable despite active service

1 participant