Skip to content

Hermes Agent Python plugin sends raw cwd path as project, not git basename (PR #687 gap) #1135

Description

@Yiipu

Summary

The Hermes Agent Python plugin (__init__.py) sends the raw os.getcwd() path as the project field to the agentmemory backend. It does not normalize the project name to the git repository basename. This causes context fragmentation and cross-project recall failures.

PR #687 introduced resolveProject(cwd) for the JavaScript hooks. That function resolves the project name through AGENTMEMORY_PROJECT_NAME env, then git rev-parse --show-toplevel basename, then cwd basename. The Hermes Python plugin does not implement this logic. It sends the full filesystem path.

Related issues:

Problem Details

The Hermes plugin file is __init__.py inside the agentmemory plugin directory. Line 191:

self._project = kwargs.get("cwd", os.getcwd())

This value propagates to three places:

  1. session/start API call: {"project": self._project, "cwd": self._project} (line 195-199)
  2. system_prompt_block context retrieval: {"project": self._project} (line 223-226)
  3. sync_turn observation: {"project": self._project, "cwd": self._project} (line 347-358)

All three send the raw path. The backend filters context by exact project match. Sessions stored with a raw path never match sessions stored with a git basename.

Steps to Reproduce

  1. Install the agentmemory plugin in Hermes Agent.
  2. Start a Hermes session inside a git repository (for example, /Users/user/projects/my-app).
  3. Generate some observations through tool use.
  4. Query the sessions API:
curl -s http://localhost:3111/agentmemory/sessions | python -m json.tool
  1. Observe that the session has "project": "/Users/user/projects/my-app" (full path). The Claude Code JS hook would store "project": "my-app" (git basename).

Expected Behavior

The Hermes Python plugin should resolve the project name the same way PR #687 does for JavaScript hooks:

  1. Check AGENTMEMORY_PROJECT_NAME env.
  2. Resolve the git toplevel via git rev-parse --show-toplevel and use its basename.
  3. Fall back to the basename of the cwd.

The project field should hold the basename. The cwd field should hold the full path.

Actual Behavior

Both project and cwd hold the full filesystem path from os.getcwd().

Environment

  • agentmemory: 0.9.28
  • Hermes Agent: 0.19.1
  • OS: macOS 15.6
  • Python: 3.11.15

Proposed Fix

Add a _resolve_project(cwd) function to the plugin. It mirrors the JavaScript resolveProject() from PR #687:

import subprocess

def _resolve_project(cwd: str) -> str:
    env_name = os.environ.get("AGENTMEMORY_PROJECT_NAME", "").strip()
    if env_name:
        return env_name
    try:
        result = subprocess.run(
            ["git", "rev-parse", "--show-toplevel"],
            capture_output=True, text=True, timeout=3,
            cwd=cwd,
        )
        if result.returncode == 0 and result.stdout.strip():
            return os.path.basename(result.stdout.strip())
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
        pass
    return os.path.basename(cwd) if cwd else ""

Then update initialize():

def initialize(self, session_id, **kwargs):
    raw_cwd = kwargs.get("cwd", os.getcwd())
    self._cwd = raw_cwd
    self._project = _resolve_project(raw_cwd)
    # ...

And send project=self._project and cwd=self._cwd in all API calls.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions