hermes - 💡(How to fix) Fix Platform plugin discovery drops platforms/ namespace from keys

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

print((p.get('key'), p.get('name'), p.get('enabled'), p.get('error')))

Root Cause

In PluginManager.discover_and_load(), bundled top-level plugins are scanned with platforms skipped, then platform plugins are scanned separately:

bundled = self._scan_directory(
    repo_plugins,
    source="bundled",
    skip_names={"memory", "context_engine", "platforms", "model-providers"},
)
...
bundled_platforms = self._scan_directory(
    repo_plugins / "platforms", source="bundled"
)

Because the second scan starts at plugins/platforms with an empty prefix, _parse_manifest() computes:

key = f"{prefix}/{plugin_dir.name}" if prefix else name

For platform manifests whose name is e.g. teams-platform, the key becomes teams-platform instead of platforms/teams.

Fix Action

Fix / Workaround

I verified this minimal local patch produces the expected platforms/* keys.

  • Reproduced on a clean detached worktree at HEAD: platform keys are *-platform.
  • Applied the minimal local patch above: platform keys become platforms/*.
  • Ran relevant plugin tests locally after the patch:

Code Example

bundled = self._scan_directory(
    repo_plugins,
    source="bundled",
    skip_names={"memory", "context_engine", "platforms", "model-providers"},
)
...
bundled_platforms = self._scan_directory(
    repo_plugins / "platforms", source="bundled"
)

---

key = f"{prefix}/{plugin_dir.name}" if prefix else name

---

HERMES_HOME=$(mktemp -d) python - <<'PY'
from hermes_cli.plugins import get_plugin_manager, discover_plugins
pm = get_plugin_manager()
discover_plugins(force=True)
for p in sorted(pm.list_plugins(), key=lambda x: x.get('key','')):
    if p.get('kind') == 'platform':
        print((p.get('key'), p.get('name'), p.get('enabled'), p.get('error')))
PY

---

('google_chat-platform', 'google_chat-platform', True, None)
('irc-platform', 'irc-platform', True, None)
('line-platform', 'line-platform', True, None)
('simplex-platform', 'simplex-platform', True, None)
('teams-platform', 'teams-platform', True, None)

---

('platforms/google_chat', 'google_chat-platform', True, None)
('platforms/irc', 'irc-platform', True, None)
('platforms/line', 'line-platform', True, None)
('platforms/simplex', 'simplex-platform', True, None)
('platforms/teams', 'teams-platform', True, None)

---

bundled_platforms = self._scan_directory_level(
    repo_plugins / "platforms",
    source="bundled",
    skip_names=None,
    prefix="platforms",
    depth=0,
)

---

python -m pytest tests/hermes_cli/test_plugins.py tests/hermes_cli/test_plugins_cmd.py -q -o 'addopts='
137 passed in 6.39s
RAW_BUFFERClick to expand / collapse

Bug Description

Bundled gateway platform plugins under plugins/platforms/<name>/ are discovered with keys like teams-platform instead of the path-derived key platforms/teams.

This is inconsistent with the plugin manager's key model for namespaced plugins (image_gen/openai, web/tavily, etc.) and breaks config/UI code that uses canonical plugin keys for plugins.enabled / plugins.disabled.

Root Cause

In PluginManager.discover_and_load(), bundled top-level plugins are scanned with platforms skipped, then platform plugins are scanned separately:

bundled = self._scan_directory(
    repo_plugins,
    source="bundled",
    skip_names={"memory", "context_engine", "platforms", "model-providers"},
)
...
bundled_platforms = self._scan_directory(
    repo_plugins / "platforms", source="bundled"
)

Because the second scan starts at plugins/platforms with an empty prefix, _parse_manifest() computes:

key = f"{prefix}/{plugin_dir.name}" if prefix else name

For platform manifests whose name is e.g. teams-platform, the key becomes teams-platform instead of platforms/teams.

Steps to Reproduce

Run plugin discovery from a clean HERMES_HOME on current HEAD:

HERMES_HOME=$(mktemp -d) python - <<'PY'
from hermes_cli.plugins import get_plugin_manager, discover_plugins
pm = get_plugin_manager()
discover_plugins(force=True)
for p in sorted(pm.list_plugins(), key=lambda x: x.get('key','')):
    if p.get('kind') == 'platform':
        print((p.get('key'), p.get('name'), p.get('enabled'), p.get('error')))
PY

Actual Behavior

('google_chat-platform', 'google_chat-platform', True, None)
('irc-platform', 'irc-platform', True, None)
('line-platform', 'line-platform', True, None)
('simplex-platform', 'simplex-platform', True, None)
('teams-platform', 'teams-platform', True, None)

Expected Behavior

Platform plugin keys should include the platforms/ namespace, while the display/manifest name can remain whatever the manifest declares:

('platforms/google_chat', 'google_chat-platform', True, None)
('platforms/irc', 'irc-platform', True, None)
('platforms/line', 'line-platform', True, None)
('platforms/simplex', 'simplex-platform', True, None)
('platforms/teams', 'teams-platform', True, None)

Impact

  • plugins.disabled / plugins.enabled entries using canonical keys like platforms/teams do not affect the discovered platform plugin if discovery reports teams-platform.
  • Downstream tooling that displays plugin state by key can show platform plugins as neutral/not blocked even when config intended to disable them.
  • The bug is specific to plugins/platforms/* because other category plugins are scanned with a category prefix and already get keys like web/tavily or image_gen/openai.

Candidate Fix

Scan bundled platform plugins with _scan_directory_level() and prefix="platforms" instead of _scan_directory() from inside the platforms directory:

bundled_platforms = self._scan_directory_level(
    repo_plugins / "platforms",
    source="bundled",
    skip_names=None,
    prefix="platforms",
    depth=0,
)

I verified this minimal local patch produces the expected platforms/* keys.

Verification Performed

  • Reproduced on a clean detached worktree at HEAD: platform keys are *-platform.
  • Applied the minimal local patch above: platform keys become platforms/*.
  • Ran relevant plugin tests locally after the patch:
python -m pytest tests/hermes_cli/test_plugins.py tests/hermes_cli/test_plugins_cmd.py -q -o 'addopts='
137 passed in 6.39s

Environment

  • Repo: NousResearch/hermes-agent
  • Component: plugin discovery / bundled gateway platform plugins

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

hermes - 💡(How to fix) Fix Platform plugin discovery drops platforms/ namespace from keys