# NousResearch/hermes-agent · MoA disabled presets incorrectly matching/activating

## Open now

- Nothing open on GitHub.

A bug where disabled MoA presets were still being selected or matched during plain chat interactions. Fixes target preset-skipping logic to respect the enabled flag.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #55598. Verify it addresses your case.
- **Recommended:** read PR #55598 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-55598`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #55187: \[Bug\] MoA virtual provider auto-selects on plain chat message; \`enabled: false\` presets still match

## Prior & competing PRs

- **#55598: fix(moa): disabled presets no longer hijack a plain model switch**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `hermes_cli/moa_config.py`, `tests/hermes_cli/test_moa_config.py`
  - fix hunks:
  - `hermes_cli/moa_config.py`

    ```diff
    @@ -158,11 +158,26 @@ def resolve_moa_preset(config: Any, name: str | None = None) -> dict[str, Any]:
     
     
     def exact_moa_preset_name(config: Any, text: str) -> str | None:
    +    """Return the preset name iff ``text`` exactly matches an *enabled* preset.
    +
    +    Used by the no-explicit-provider switch path (PATH B in
    +    ``hermes_cli/model_switch.py``) to recognize a bare ``/model <preset>``
    +    that the user typed without the ``moa:`` prefix. This is an *implicit*
    +    match, so it must honor the per-preset ``enabled`` opt-out: a user who set
    +    ``enabled: false`` to disable a preset must not have a plain model switch
    +    whose name happens to collide with that preset key silently pivot the
    +    session onto the MoA virtual provider (issue #55187). Explicit selection
    +    via ``--provider moa`` / the model picker does not go through here, so a
    +    disabled preset is still reachable when the user explicitly asks for it.
    +    """
         wanted = str(text or "").strip()
         if not wanted:
             return None
         cfg = normalize_moa_config(config)
    -    return wanted if wanted in cfg["presets"] else None
    +    preset = cfg["presets"].get(wanted)
    +    if preset is None or not preset.get("enabled", True):
    +        return None
    +    return wanted
     
     
     def set_active_moa_preset(config: Any, name: str | None) -> dict[str, Any]:
    ```
  - `tests/hermes_cli/test_moa_config.py`

    ```diff
    @@ -120,6 +120,38 @@ def test_exact_preset_matching_is_not_fuzzy():
         assert exact_moa_preset_name(config, "coding please fix this") is None
     
     
    +def test_exact_preset_matching_skips_disabled_presets():
    +    """A disabled preset must not match the implicit bare-name switch path.
    +
    +    Regression for #55187: with ``enabled: false`` presets, a plain model
    +    switch whose name collides with a preset key (e.g. ``default``) silently
    +    pivoted the session onto the MoA virtual provider. The per-preset
    +    ``enabled`` opt-out must gate this implicit match.
    +    """
    +    config = {
    +        "presets": {
    +            "default": {"enabled": False},
    +            "klo": {"enabled": False},
    +        },
    +    }
    +    assert exact_moa_preset_name(config, "default") is None
    +    assert exact_moa_preset_name(config, "klo") is None
    +
    +
    +def test_exact_preset_matching_allows_enabled_presets():
    +    """An explicitly enabled preset still matches the bare-name switch path."""
    +    config = {
    +        "presets": {
    +            "fast": {"enabled": True},
    +            "slow": {"enabled": False},
    +        },
    +    }
    +    assert exact_moa_preset_name(config, "fast") == "fast"
    +    assert exact_moa_preset_name(config, "slow") is None
    +    # Default (no explicit enabled key) is enabled and still matches.
    +    assert exact_moa_preset_name({"presets": {"x": {}}}, "x") == "x"
    +
    +
     def test_active_preset_toggle_validation():
         config = {"default_preset": "coding", "presets": {"coding": {}, "review": {}}}
     
    ```
- **#55193: fix(moa): skip disabled presets in exact_moa_preset_name**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#55598`

## Fix status

- Merged to main in PR #55598 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-30`.
