Skip to content

feat: Hermes Agent memory provider plugin#107

Merged
rohitg00 merged 2 commits intomainfrom
feat/hermes-integration
Apr 9, 2026
Merged

feat: Hermes Agent memory provider plugin#107
rohitg00 merged 2 commits intomainfrom
feat/hermes-integration

Conversation

@rohitg00
Copy link
Copy Markdown
Owner

@rohitg00 rohitg00 commented Apr 9, 2026

Summary

Adds first-class integration with Hermes Agent (33K stars, Nous Research). Two paths:

Path 1: MCP server (zero code)

# ~/.hermes/config.yaml
mcp_servers:
  agentmemory:
    command: npx
    args: ["agentmemory-mcp"]

Path 2: Memory provider plugin (deeper integration)

cp -r integrations/hermes ~/.hermes/plugins/memory/agentmemory

The plugin implements the full Hermes MemoryProvider ABC:

  • prefetch() injects relevant memories before each LLM call
  • sync_turn() captures conversation turns (non-blocking, daemon thread)
  • on_session_end() marks sessions for summarization
  • on_pre_compress() re-injects context before compaction
  • on_memory_write() mirrors MEMORY.md writes to agentmemory
  • system_prompt_block() injects project profile at session start
  • 3 tools exposed: memory_recall, memory_save, memory_search

Pure 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 metadata
  • integrations/hermes/README.md - Setup guide with both paths
  • README.md - Added Hermes to the agent setup table

Test plan

  • All 646 tests pass
  • Build succeeds
  • Manual: install plugin in Hermes, verify prefetch returns memories
  • Manual: verify sync_turn captures conversation in agentmemory viewer

Summary by CodeRabbit

  • New Features

    • Hermes Agent integration adding persistent cross-session memory, retrieval/search, and real-time viewer
    • Exposes memory recall, save, and search tools for agent workflows
  • Documentation

    • Comprehensive setup instructions offering two installation/configuration paths
    • Documents environment variables, configuration options, lifecycle behavior, and integration benefits

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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5bead83-2754-4542-a01f-02f4eb5190a0

📥 Commits

Reviewing files that changed from the base of the PR and between 112e6f4 and 9173b09.

📒 Files selected for processing (1)
  • integrations/hermes/__init__.py

📝 Walkthrough

Walkthrough

Adds a Hermes Agent integration for agentmemory: documentation and plugin manifest plus a new AgentMemoryProvider that communicates with an external agentmemory HTTP server, registers tool schemas, hooks into Hermes lifecycle callbacks, and performs async observations and memory writes.

Changes

Cohort / File(s) Summary
Documentation & Top-level README
README.md, integrations/hermes/README.md
Added Hermes integration instructions to the top-level "Other agents" table and a detailed integration README describing setup options (MCP server via ~/.hermes/config.yaml or plugin install), env vars (AGENTMEMORY_URL, AGENTMEMORY_SECRET), lifecycle callbacks, tool schemas, and viewer endpoint.
Plugin Manifest & Provider Implementation
integrations/hermes/plugin.yaml, integrations/hermes/__init__.py
Added plugin.yaml (metadata, hooks: on_session_end, on_pre_compress, on_memory_write) and a new AgentMemoryProvider module implementing Hermes MemoryProvider behavior: availability checks, session/start & session/end, context retrieval, smart-search prefetch, tool schemas (memory_recall, memory_save, memory_search), HTTP helpers with optional Bearer auth, async/firing background requests, sync_turn observations, and background memory writes.

Sequence Diagram(s)

mermaid
sequenceDiagram
rect rgba(200,200,255,0.5)
participant Hermes as Hermes Agent
end
rect rgba(200,255,200,0.5)
participant Plugin as AgentMemoryProvider (plugin)
end
rect rgba(255,200,200,0.5)
participant Server as AgentMemory HTTP Server
end

Hermes->>Plugin: initialize(session_id)
Plugin->>Server: POST /session/start (session_id)
Hermes->>Plugin: on_pre_compress(messages)
Plugin->>Server: POST /smart-search (query)
Server-->>Plugin: search results
Plugin-->>Hermes: prepend retrieved context
Hermes->>Plugin: handle_tool_call("memory_search", args)
Plugin->>Server: POST /search
Server-->>Plugin: results
Plugin-->>Hermes: tool response
Hermes->>Plugin: sync_turn(user, assistant)
Plugin->>Server: POST /observe (truncated convo) (async)
Hermes->>Plugin: on_session_end(messages)
Plugin->>Server: POST /session/end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: Hermes Agent memory provider plugin #107 — Adds the same Hermes integration files (integrations/hermes/__init__.py, plugin.yaml, integrations/hermes/README.md) and updates top-level README; likely a duplicate or closely related submission.

Poem

🐰 I hop through sessions bright and merry,
I tuck small memories in a buried carry,
Callbacks hum and searches spring,
Threads whisper what the agents bring,
A rabbit cheers: persistent memory, very merry!

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Hermes Agent memory provider plugin' accurately and clearly summarizes the main change: adding a Hermes Agent integration with a memory provider plugin. It is concise, specific, and directly reflects the primary addition across all modified files.

✏️ 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 feat/hermes-integration

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.

Copy link
Copy Markdown

@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: 2

🧹 Nitpick comments (1)
integrations/hermes/__init__.py (1)

90-100: _secret instance variable is stored but unused.

self._secret is assigned on line 94 but the _api function reads AGENTMEMORY_SECRET directly from the environment on each call. Consider either removing the unused instance variable or passing it to _api for 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

📥 Commits

Reviewing files that changed from the base of the PR and between 699549d and 112e6f4.

📒 Files selected for processing (4)
  • README.md
  • integrations/hermes/README.md
  • integrations/hermes/__init__.py
  • integrations/hermes/plugin.yaml

Comment thread integrations/hermes/__init__.py Outdated
Comment thread integrations/hermes/__init__.py Outdated
- 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
@rohitg00 rohitg00 merged commit e88de77 into main Apr 9, 2026
2 checks passed
@rohitg00 rohitg00 deleted the feat/hermes-integration branch April 9, 2026 12:44
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.

1 participant