feat: Hermes Agent memory provider plugin#107
Conversation
Two integration paths: 1. MCP server (zero code) - add to ~/.hermes/config.yaml 2. Memory provider plugin (deeper) - hooks into Hermes agent loop Plugin implements the full MemoryProvider ABC: - prefetch() injects relevant memories before each LLM call - sync_turn() captures conversation turns in background (non-blocking) - on_session_end() marks sessions for summarization - on_pre_compress() re-injects context before compaction - on_memory_write() mirrors MEMORY.md writes - system_prompt_block() injects project profile - 3 tools: memory_recall, memory_save, memory_search Uses only stdlib (urllib, json, threading). No new dependencies.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a Hermes Agent integration for agentmemory: documentation and plugin manifest plus a new Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
integrations/hermes/__init__.py (1)
90-100:_secretinstance variable is stored but unused.
self._secretis assigned on line 94 but the_apifunction readsAGENTMEMORY_SECRETdirectly from the environment on each call. Consider either removing the unused instance variable or passing it to_apifor consistency.♻️ Option: Remove unused variable
def initialize(self, session_id: str, **kwargs: Any) -> None: self._base = os.environ.get("AGENTMEMORY_URL", DEFAULT_BASE_URL) self._session_id = session_id self._project = kwargs.get("cwd", os.getcwd()) - self._secret = os.environ.get("AGENTMEMORY_SECRET", "") _api(self._base, "session/start", {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@integrations/hermes/__init__.py` around lines 90 - 100, The instance variable self._secret is assigned in initialize but never used because _api reads AGENTMEMORY_SECRET from env; update initialize to pass the stored secret into _api (e.g., include it in the payload or as an explicit parameter) so the _secret field is actually used, or remove the assignment if you prefer the env-only approach; locate the initialize method and the _api(...) call and either pass self._secret to that call or delete the self._secret assignment to eliminate the unused variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@integrations/hermes/__init__.py`:
- Around line 261-267: The on_pre_compress method currently calls
_api(self._base, "context", {...}) and ignores the returned context; either
re-inject the fetched context into the messages or document the no-op intent.
Fix by using the returned result.get("context") to modify messages (e.g.,
prepend/merge into the messages list or update message metadata) inside
on_pre_compress, or if the call is only meant to warm a cache, add a clear
comment explaining that behavior and leave it as a no-op; locate this change in
the on_pre_compress function and reference the _api call that fetches "context"
so reviewers can see where to apply the injection or add the explanatory
comment.
- Around line 54-67: The _api function (and is_available) must validate the
AGENTMEMORY_URL scheme before calling urlopen to prevent SSRF: parse the base
URL using urllib.parse.urlparse, ensure parsed.scheme is exactly "http" or
"https" (otherwise return None or raise a ValueError), and only then build the
full URL and call urlopen (preserve existing headers/timeout/TIMEOUT logic);
update the is_available function to perform the same scheme check on
AGENTMEMORY_URL before attempting any network call.
---
Nitpick comments:
In `@integrations/hermes/__init__.py`:
- Around line 90-100: The instance variable self._secret is assigned in
initialize but never used because _api reads AGENTMEMORY_SECRET from env; update
initialize to pass the stored secret into _api (e.g., include it in the payload
or as an explicit parameter) so the _secret field is actually used, or remove
the assignment if you prefer the env-only approach; locate the initialize method
and the _api(...) call and either pass self._secret to that call or delete the
self._secret assignment to eliminate the unused variable.
🪄 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: 226d7ee6-7500-4f5a-9343-99762dbec8e3
📒 Files selected for processing (4)
README.mdintegrations/hermes/README.mdintegrations/hermes/__init__.pyintegrations/hermes/plugin.yaml
- SSRF prevention: validate URL scheme (http/https only) before urlopen - on_pre_compress: inject fetched context into messages list (was no-op) - Remove unused self._secret; _api reads from env directly
Summary
Adds first-class integration with Hermes Agent (33K stars, Nous Research). Two paths:
Path 1: MCP server (zero code)
Path 2: Memory provider plugin (deeper integration)
cp -r integrations/hermes ~/.hermes/plugins/memory/agentmemoryThe plugin implements the full Hermes
MemoryProviderABC:prefetch()injects relevant memories before each LLM callsync_turn()captures conversation turns (non-blocking, daemon thread)on_session_end()marks sessions for summarizationon_pre_compress()re-injects context before compactionon_memory_write()mirrors MEMORY.md writes to agentmemorysystem_prompt_block()injects project profile at session startmemory_recall,memory_save,memory_searchPure stdlib Python (urllib, json, threading). Zero dependencies beyond Hermes itself.
Files added
integrations/hermes/__init__.py- MemoryProvider implementation (~250 lines)integrations/hermes/plugin.yaml- Plugin metadataintegrations/hermes/README.md- Setup guide with both pathsREADME.md- Added Hermes to the agent setup tableTest plan
Summary by CodeRabbit
New Features
Documentation