Skip to content

/model switch silently lost when first message after session auto-reset (was_auto_reset flag never consumed) #48031

Description

@rmichelena

Bug Description

/model switch is silently lost when it's the first message after a session auto-reset. The session DB shows the new model, the UI says the new model, but actual API calls go to the previous/default model.

Steps to Reproduce

  1. Have an active session that goes idle long enough to trigger auto-reset (or let it expire by inactivity)
  2. Send /model <new_model> as the first message after the idle period
  3. The /model command succeeds — UI shows "Model switched to X", session DB records the new model
  4. Send a regular message
  5. Actual: The response comes from the old model, not the one you switched to
  6. Check provider logs (e.g. OpenRouter dashboard) — zero calls to the new model

Expected Behavior

After /model switches the model, all subsequent messages in that session should use the new model.

Actual Behavior

The model override stored by /model is wiped on the next regular message because was_auto_reset is a sticky flag that never gets consumed.

Root Cause

In gateway/run.py, _handle_message_with_agent() (line ~8980):

if getattr(session_entry, "was_auto_reset", False):
    self._session_model_overrides.pop(session_key, None)  # ← wipes the override
    self._set_session_reasoning_override(session_key, None)
    if hasattr(self, "_pending_model_notes"):
        self._pending_model_notes.pop(session_key, None)

This cleanup is designed to remove stale overrides from the previous session on auto-reset. But was_auto_reset is never consumed — it stays True for the entire session lifetime (unlike is_fresh_reset, which IS consumed at line ~8998 per issue #6508).

Timeline of the bug:

  1. /model X arrives → get_or_create_session() auto-resets (idle session) → new session with was_auto_reset=True
  2. _handle_model_command() correctly stores override: _session_model_overrides[key] = {model: X, ...}
  3. Next regular message → _handle_message_with_agent()was_auto_reset still Truepops the override
  4. Model resolution falls back to config.yaml default

Two sources of truth diverge:

  • Session DB (SQLite): model = X (updated by _handle_model_command) → dashboard/UI shows X
  • Runtime memory (_session_model_overrides dict): empty → actual API calls use default model

Fix

Two-part patch (both in gateway/run.py):

1. Consume was_auto_reset after use (line ~9000)

After the _is_new_session check, consume the flag so it doesn't fire repeatedly:

if getattr(session_entry, "was_auto_reset", False):
    session_entry.was_auto_reset = False

This mirrors the existing is_fresh_reset consumption pattern (#6508).

2. Clear was_auto_reset in _handle_model_command() (line ~11443)

After /model stores a new override, clear the flag so the next message handler doesn't wipe it:

try:
    _override_sess_entry = self.session_store._entries.get(session_key)
    if _override_sess_entry and getattr(_override_sess_entry, "was_auto_reset", False):
        _override_sess_entry.was_auto_reset = False
except Exception:
    pass

Environment

  • Hermes Agent v0.16.0
  • Platform: Matrix (likely affects all platforms: Telegram, Discord, etc.)
  • Docker container (s6-overlay supervision)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/gatewayGateway runner, session dispatch, deliverytype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions