Skip to content

feat(moa): add reference model toggles - #59753

Closed
oppenheimor wants to merge 1 commit into
NousResearch:mainfrom
oppenheimor:feat/moa-reference-toggle-59744
Closed

feat(moa): add reference model toggles#59753
oppenheimor wants to merge 1 commit into
NousResearch:mainfrom
oppenheimor:feat/moa-reference-toggle-59744

Conversation

@oppenheimor

@oppenheimor oppenheimor commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds per-reference enable/disable support for MoA reference models.

Each MoA reference model now keeps an enabled flag, defaulting to true for existing configs. Disabled references stay in the preset, but are skipped during MoA inference so they do not make API calls or contribute to the aggregator context.

Related Issue

feat #59707

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added per-reference enabled normalization for MoA presets.
  • Skips disabled references in both persistent MoA provider runs and one-shot MoA context aggregation.
  • Added MoA reference toggles to the desktop and dashboard MoA settings UI.
  • Preserves reference enabled state when changing provider/model selections.
  • Added backend/runtime coverage for default-enabled references and disabled-reference skipping.
  • Added desktop settings coverage for saving disabled MoA references.

How to Test

  1. Run MoA backend tests:

    source .venv/bin/activate
    pytest tests/hermes_cli/test_moa_config.py tests/run_agent/test_moa_loop_mode.py tests/cli/test_moa_command.py
  2. Run dashboard typecheck:

    npm --workspace web run typecheck
  3. Manually verify in the dashboard:

    hermes dashboard

    Open Models -> Configure MoA presets, toggle a reference model off, save, and confirm the disabled reference stays in the preset but is skipped during MoA runs.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this feature
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation — N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact — N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Screenshots / Logs

Manually verified through hermes dashboard.

Image Image

@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/desktop Electron desktop app (apps/desktop/*) comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P3 Low — cosmetic, nice to have labels Jul 6, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: implements the per-reference MoA enable/disable feature requested in #59707 (kept open as the spec thread). Distinct from #59743, which adds the per-preset enabled toggle to the desktop UI (#59723) -- this PR is per-reference-model granularity and touches the full stack (agent/moa_loop.py, moa_config, desktop + dashboard). Note: the body says 'Fixes #59744', but #59744 is about hiding unconfigured providers in the model picker and appears unrelated to this change.

@oppenheimor

Copy link
Copy Markdown
Contributor Author

Thanks for catching that. I updated the PR body to reference #59707 instead of #59744, and used “Related to” since #59707 is being kept open as the spec thread. This PR is scoped to per-reference-model enable/disable behavior.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing the per-reference MoA toggle requested in #59707. The feature premise is still valid on current main: hermes_cli/moa_config.py:92-110 drops per-reference enabled, and both execution paths fan out every slot (agent/moa_loop.py:683-690, 906-908).

Problems

  • This branch predates current per-slot reasoning support. Current hermes_cli/moa_config.py:107-109 preserves reasoning_effort (commit 3dca75b45c2edf38089ef07c22023afe357aebc1); merge the enabled handling into that normalizer rather than replacing it.
  • The runtime test covers persistent MoAChatCompletions.create(), but the PR also changes one-shot aggregation. Add a disabled-reference test directly through aggregate_moa_context() (agent/conversation_loop.py:877-893).
  • Add an accessible name to the dashboard switch; nearby dashboard toggle controls provide aria-label (web/src/components/ToolsetConfigDrawer.tsx:252-256).

Suggested changes

  • Salvage against current MoA slot semantics and retain reasoning_effort, reference_max_tokens, and fanout behavior.
  • Cover both persistent and one-shot reference fan-out paths.

Automated hermes-sweeper review.

Comment thread hermes_cli/moa_config.py
@@ -87,12 +106,15 @@ def _clean_slot(slot: Any) -> dict[str, str] | None:
# an invalid slot is dropped, falling back to the preset's defaults.
if provider.lower() == "moa":
return None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current main's _clean_slot preserves reasoning_effort (3dca75b45c2edf38089ef07c22023afe357aebc1, now hermes_cli/moa_config.py:107-109). When salvaging, compose enabled normalization with that behavior rather than replacing it, or normalization will discard existing per-slot reasoning settings.

Comment thread agent/moa_loop.py
@@ -594,6 +594,7 @@ def aggregate_moa_context(
provider default applies — matching single-model agent behavior. Presets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a direct aggregate_moa_context() test for this filter. The new runtime test covers persistent MoAChatCompletions.create(), but one-shot /moa reaches this separate path through agent/conversation_loop.py:877-893.

className={cn(
"flex items-center gap-2 border border-border/50 bg-muted/20 px-3 py-2",
slot.enabled === false && "opacity-60"
)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a stateful accessible name such as Disable reference ${index + 1} / Enable reference ${index + 1}. This switch has no associated label; existing dashboard switches provide aria-label.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
teknium1 added a commit that referenced this pull request Jul 23, 2026
…abled flag

The per-reference-model enabled toggle (#59753 salvage) intentionally adds
'enabled' to normalized slot dicts. The two endpoint tests asserted the
exact key set {provider, model} — convert them to subset + round-trip
contracts so optional slot keys (enabled, reasoning_effort, max_tokens)
don't break them again.
teknium1 added a commit that referenced this pull request Jul 24, 2026
Follow-up for salvaged PR #59753 rebased over the per-slot
reasoning_effort feature: _clean_slot now round-trips reasoning_effort
AND enabled together; add a normalize→normalize regression test, update
the validate/normalize agreement contract for the canonical enabled
default, restore the desktop per-slot toggle test on the current
autosave editor, and map oppenheimor's contributor email.
teknium1 added a commit that referenced this pull request Jul 24, 2026
…abled flag

The per-reference-model enabled toggle (#59753 salvage) intentionally adds
'enabled' to normalized slot dicts. The two endpoint tests asserted the
exact key set {provider, model} — convert them to subset + round-trip
contracts so optional slot keys (enabled, reasoning_effort, max_tokens)
don't break them again.
teknium1 added a commit that referenced this pull request Jul 24, 2026
Follow-up for salvaged PR #59753 rebased over the per-slot
reasoning_effort feature: _clean_slot now round-trips reasoning_effort
AND enabled together; add a normalize→normalize regression test, update
the validate/normalize agreement contract for the canonical enabled
default, restore the desktop per-slot toggle test on the current
autosave editor, and map oppenheimor's contributor email.
teknium1 added a commit that referenced this pull request Jul 24, 2026
…abled flag

The per-reference-model enabled toggle (#59753 salvage) intentionally adds
'enabled' to normalized slot dicts. The two endpoint tests asserted the
exact key set {provider, model} — convert them to subset + round-trip
contracts so optional slot keys (enabled, reasoning_effort, max_tokens)
don't break them again.
teknium1 added a commit that referenced this pull request Jul 24, 2026
Follow-up for salvaged PR #59753 rebased over the per-slot
reasoning_effort feature: _clean_slot now round-trips reasoning_effort
AND enabled together; add a normalize→normalize regression test, update
the validate/normalize agreement contract for the canonical enabled
default, restore the desktop per-slot toggle test on the current
autosave editor, and map oppenheimor's contributor email.
teknium1 added a commit that referenced this pull request Jul 24, 2026
…abled flag

The per-reference-model enabled toggle (#59753 salvage) intentionally adds
'enabled' to normalized slot dicts. The two endpoint tests asserted the
exact key set {provider, model} — convert them to subset + round-trip
contracts so optional slot keys (enabled, reasoning_effort, max_tokens)
don't break them again.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via cluster PR #70283 (commit 385a065) — your commit cherry-picked with authorship preserved, rebased over the per-slot reasoning_effort feature that landed after you opened this; _clean_slot now round-trips reasoning_effort, max_tokens, AND enabled together with a round-trip regression test. Implements #59707. Thanks!

@teknium1 teknium1 closed this Jul 24, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
Follow-up for salvaged PR NousResearch#59753 rebased over the per-slot
reasoning_effort feature: _clean_slot now round-trips reasoning_effort
AND enabled together; add a normalize→normalize regression test, update
the validate/normalize agreement contract for the canonical enabled
default, restore the desktop per-slot toggle test on the current
autosave editor, and map oppenheimor's contributor email.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…abled flag

The per-reference-model enabled toggle (NousResearch#59753 salvage) intentionally adds
'enabled' to normalized slot dicts. The two endpoint tests asserted the
exact key set {provider, model} — convert them to subset + round-trip
contracts so optional slot keys (enabled, reasoning_effort, max_tokens)
don't break them again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants