Toolset resolution bugs: composite, alias, platform defaults
NousResearch/hermes-agent · cluster 22601 · gateway
Data as of
Nothing open on GitHub. Fix merged in #22673. Check it covers your case.
The short answer
- Known?
- Yes. 12 related items grouped here, 3 issues already closed.
- Fix event
- A fix was merged to main in PR #22673. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PRs #22673, #60553, #131906. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and PRs address multiple related bugs where composite toolsets (e.g. hermes-cli, hermes-discord), legacy aliases, and platform-native defaults are silently dropped or ignored during toolset resolution. Several entries also cover Discord and Feishu tool wiring and splitting.
Open issues0
Open PRs0
Fixes on record
-
#22673 fix(cli): expand composite toolset when mixed with configurables in platform_toolsets (salvage #22606)
files:
hermes_cli/tools_config.py,tests/hermes_cli/test_tools_config.pyShow the diff
-
hermes_cli/tools_config.py@@ -972,6 +972,38 @@ def _get_platform_tools( ts for ts in toolset_names if ts in configurable_keys and _toolset_allowed_for_platform(ts, platform) } + # Mixed config: composite toolset alongside configurables (e.g. + # ``[hermes-cli, spotify]`` after enabling Spotify via ``hermes + # tools``). Without expansion the composite name is silently dropped, + # leaving sessions with only the configurable opt-ins and no native + # tools. Mirror the else-branch's subset inference, but apply + # _DEFAULT_OFF_TOOLSETS only to the implicit expansion — anything the + # user explicitly listed (e.g. ``spotify``) must survive. + composite_tools = set() + for ts_name in toolset_names: + if ts_name in configurable_keys or ts_name in plugin_ts_keys: + continue + if ts_name not in TOOLSETS: + continue + composite_tools.update(resolve_toolset(ts_name)) + + if composite_tools: + expanded = set() + for ts_key, _, _ in CONFIGURABLE_TOOLSETS: + if not _toolset_allowed_for_platform(ts_key, platform): + continue + ts_tools = set(resolve_toolset(ts_key)) + if ts_tools and ts_tools.issubset(composite_tools): + expanded.add(ts_key) + + default_off = set(_DEFAULT_OFF_TOOLSETS) + if platform in default_off and platform not in _TOOLSET_PLATFORM_RESTRICTIONS: + default_off.remove(platform) + if "homeassistant" in default_off and os.getenv("HASS_TOKEN"): + default_off.remove("homeassistant") + expanded -= default_off + + enabled_toolsets |= expanded else: # No explicit config — fall back to resolving composite toolset names # (e.g. "hermes-cli") to individual tool names and reverse-mapping. -
tests/hermes_cli/test_tools_config.py@@ -119,6 +119,64 @@ def test_get_platform_tools_homeassistant_toolset_off_for_cron_when_hass_token_m assert "homeassistant" not in cron_enabled +def test_get_platform_tools_expands_composite_when_mixed_with_configurable(): + """``[hermes-cli, spotify]`` (composite + configurable) must keep the full + ``hermes-cli`` toolset alongside the explicit Spotify opt-in. The + has_explicit_config branch used to drop ``hermes-cli`` on the floor, + leaving sessions with only ``{spotify, kanban}``.""" + config = {"platform_toolsets": {"cli": ["hermes-cli", "spotify"]}} + + enabled = _get_platform_tools(config, "cli", include_default_mcp_servers=False) + + # Native tools must reappear. + for ts in ("terminal", "file", "web", "browser", "memory", "delegation", + "code_execution", "todo", "session_search", "skills"): + assert ts in enabled, f"{ts} should be enabled when hermes-cli is listed" + # User explicitly opted into Spotify — must survive _DEFAULT_OFF_TOOLSETS subtraction. + assert "spotify" in enabled + + +def test_get_platform_tools_composite_only_unchanged(): + """Composite-only config (no configurable in list) must still take the + else-branch path and produce the full toolset — guards against the new + code accidentally hijacking the composite-only case.""" + composite_only = _get_platform_tools( + {"platform_toolsets": {"cli": ["hermes-cli"]}}, + "cli", + include_default_mcp_servers=False, + ) + default = _get_platform_tools({}, "cli", include_default_mcp_servers=False) + + assert composite_only == default + + +def test_get_platform_tools_configurable_only_no_expansion(): + """Configurable-only list (no composite) must not pull in unrelated + toolsets — guards against the expansion firing when ``composite_tools`` + is empty.""" + config = {"platform_toolsets": {"cli": ["terminal", "file"]}} + + enabled = _get_platform_tools(config, "cli", include_default_mcp_servers=False) + + assert "terminal" in enabled + assert "file" in enabled + # Web shouldn't sneak in via the new expansion path. + assert "web" not in enabled + + +def test_get_platform_tools_mixed_does_not_resurrect_default_off(): + """Expansion must subtract _DEFAULT_OFF_TOOLSETS from the implicit + pull-in. Without this, ``hermes-cli`` expansion would re-enable + ``moa`` / ``rl`` / ``homeassistant`` for users who never opted in.""" + config = {"platform_toolsets": {"cli": ["hermes-cli", "terminal"]}} + + enabled = _get_platform_tools(config, "cli", include_default_mcp_servers=False) + + assert "terminal" in enabled + assert "moa" not in enabled + assert "rl" not in enabled + + def test_get_platform_tools_preserves_explicit_empty_selection(): config = {"platform_toolsets": {"cli": []}}
-
-
#60553 fix(tools): honor explicit platform_toolsets config for platform-native default-off toolsets
files:
hermes_cli/tools_config.py,tests/hermes_cli/test_tools_config.py -
#131906 fix(tools): expand legacy "hermes" toolset alias to prevent silent tool loss [risk 0.30]
files:
hermes_cli/tools_config.py,tests/hermes_cli/test_tools_config.py
6 PRs closed without merging
From the close comments: done elsewhere 2 · superseded by another PR 2 · merged via another change 1 · other 1
-
#22606 fix(cli): expand composite toolset when mixed with configurables in platform_toolsets · merged via another change →
#22673 -
#22608 fix(tools): expand composite platform toolsets alongside explicit configurable keys · superseded by another PR →
#22673,#22606 -
#22641 fix(tools): expand composite toolsets in has_explicit_config branch · superseded by another PR →
#22673,#22606 -
#35536 fix(tools): honor explicit composite toolsets for platform-restricted defaults · done elsewhere →
8a726e9,#35527 - #38532 fix(tools): honor explicit composite toolsets for platform-restricted defaults · other
Show 1 more
-
#41587 fix(tools): expand legacy "hermes" toolset alias to prevent silent tool loss · done elsewhere →
#131906
Closed issues · 3
- Closed#22601_get_platform_tools silently drops composite toolset (e.g. hermes-cli) when saved list mixes composite + configurable — entire native toolset disappears
- Closed#35527[Bug]: discord/discord_admin tools silently missing when platform_toolsets uses hermes-discord composite
- Closed#41579fix: _get_platform_tools() should resolve legacy toolset aliases (hermes → hermes-cli)
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.15: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the Lab