Skip to content

[Bug]: Desktop MOA settings silently drop save_traces and trace_dir fields #58819

Description

@ZHEN7299

Bug Description

The Desktop MOA settings panel calls PUT /api/model/moa to save preset changes. The endpoint's Pydantic payload model MoaConfigPayload does not declare save_traces or trace_dir as fields, and set_moa_models does a wholesale overwrite of cfg["moa"]. As a result, any save_traces: true (and trace_dir) value I have set by hand-editing ~/.hermes/config.yaml is silently dropped every time I save anything through the Desktop MOA GUI — without warning, and without any log entry.

This effectively prevents enabling MOA trace persistence through the Desktop UI, and silently disables it for users who already have it working via hand-edited yaml.

Steps to Reproduce

  1. Hand-edit ~/.hermes/config.yaml, add under the moa: block:

    save_traces: true
    trace_dir: ""

  2. Run a MOA session from Desktop. Verify: a trace JSONL file appears at ~/.hermes/moa-traces/<session_id>.jsonl.

  3. Open Desktop -> Settings -> Model -> Mixture of Agents panel.

  4. Change any preset parameter (e.g. add a reference model, change max_tokens).

  5. Click Save.

  6. Re-open ~/.hermes/config.yaml: the save_traces: true line is gone. save_traces and trace_dir are dropped from yaml.

Expected: the two hand-set fields are preserved across saves.
Actual: both fields silently disappear.

Expected Behavior

After saving through the Desktop MOA panel, manually-configured save_traces and trace_dir values remain intact in ~/.hermes/config.yaml. Subsequent MOA runs continue to produce JSONL trace files.

Actual Behavior

After saving through the Desktop MOA panel, save_traces and trace_dir are silently removed from cfg["moa"] in ~/.hermes/config.yaml. Subsequent MOA runs produce NO trace file under ~/.hermes/moa-traces/, with no warning to the user.

To restore trace persistence, the user must hand-edit yaml again - and the same loss recurs on the next save.

Affected Component

Configuration (config.yaml, .env, hermes setup)

Messaging Platform (if gateway-related)

N/A (CLI only)

Debug Report

Local debug report (not uploaded for privacy):

$ hermes debug share --local --lines 300

[output saved locally at /tmp/hermes_debug_report.txt - 10032 lines]

Key extract from the report:
- hermes version: 0.18.0 [a0a3c716] (2026-07-05)
- os: Darwin 25.5.0 arm64
- python: 3.11.15
- main model: 参谋部 (moa provider)
- features.gateway: running (launchd, pid 57182)
- agent.log shows the API path: agent.conversation_loop calls model=参谋部 provider=moa

If maintainers want the full report file, I can rerun with --nous for private Nous-internal upload.

Operating System

macOS 26.5.1 (Darwin 25.5.0 arm64)

Python Version

3.11.15

Hermes Version

0.18.0 (commit a0a3c71, 2026-07-05)

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

Source code review:

  1. hermes_cli/web_server.py - MoaConfigPayload class (around line 4430) defines only:

    • default_preset, active_preset
    • presets (dict of MoaPresetPayload)
    • reference_models, aggregator (legacy flat payload fields)
    • reference_temperature, aggregator_temperature
    • max_tokens, enabled
    • profile
      -> save_traces and trace_dir are NOT declared.
  2. hermes_cli/web_server.py line 4447 - set_moa_models function:
    raw = {
    "default_preset": body.default_preset,
    "active_preset": body.active_preset,
    "presets": {...}, # references + aggregator + temperatures + max_tokens + enabled
    }
    normalized = normalize_moa_config(raw)
    cfg["moa"] = normalized # WHOLE-BLOCK OVERWRITE
    save_config(cfg)

    save_traces / trace_dir are not in raw, so they get dropped.

  3. hermes_cli/moa_config.py _normalize_preset (line 93+) - uses _default_preset() for any preset that doesn't declare save_traces/trace_dir, defaulting both to None/false. The preset structure also doesn't have a save_traces field, so even if MoaPresetPayload is fixed at the top level, nested preset save_traces wouldn't survive.

Suggested patch (mirror PR #58143's approach):

  • Add save_traces: Optional[bool] = None and trace_dir: Optional[str] = None to MoaPresetPayload and MoaConfigPayload.
  • Write both fields into the raw dict in set_moa_models (preset branch + legacy flat branch).
  • Add a regression test that PUTs save_traces: True, trace_dir: "/tmp/x" and asserts both fields round-trip.

Proposed Fix (optional)

ext Mirror PR #58143's fix exactly:

In hermes_cli/web_server.py, extend MoaConfigPayload and MoaPresetPayload: save_traces: Optional[bool] = None trace_dir: Optional[str] = None

In set_moa_models (web_server.py ~line 4470), add save_traces and trace_dir to the raw dict in BOTH the preset branch AND the legacy flat branch.

Add regression test in tests/hermes_cli/test_web_server.py: def test_put_moa_models_preserves_save_traces_and_trace_dir(): # Round-trip a PUT with save_traces=True, trace_dir="/tmp/x" # Assert both fields persist after save_config

Optionally: prefer read-modify-write semantics in set_moa_models (merge with existing cfg["moa"] before write) so future fields aren't silently dropped.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/configConfig system, migrations, profilesbugcomp/dashboardWeb dashboard / control panel UI (dashboard/, landing)type/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions