# NousResearch/hermes-agent · Toggle to enable/disable automatic title generation

## Open now

- 1 issue, 0 PRs open on GitHub.
- #29456: \[Feature\]: Ability to toggle title generation

These issues and pull requests concern adding and correctly honoring a configuration setting to enable or disable auxiliary title generation. Multiple bug reports indicate the enabled flag is ignored, with several fix attempts addressing this behavior.

## TL;DR

- 10 member(s): 1 open issue(s), 3 closed issue(s), 0 open PR(s), 2 merged PR(s), 4 PR(s) closed without merging.
- A fix was merged to main in PR #113955. Verify it addresses your case.
- **Recommended:** read PR #113955 (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: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): 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.16`: 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.

## Open related issues

- #29456: \[Feature\]: Ability to toggle title generation

## Closed / duplicate issues

- #27877: Feature: add \`enabled\` toggle for auxiliary tasks (title_generation, etc.)
- #41744: auxiliary.title.enabled config is ignored — title generation runs regardless
- #54577: bug(title_generation): \`enabled: false\` config is ignored, title generation always runs

## Prior & competing PRs

- **#66049: fix(title): honor auxiliary.title_generation.enabled to disable auto titles (salvage #37349)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/title_generator.py`, `cli-config.yaml.example`, `hermes_cli/config.py`, `scripts/release.py`, `tests/agent/test_title_generator.py`, `tests/hermes_cli/test_aux_config.py`, `website/docs/user-guide/configuration.md`
  - fix hunks:
  - `agent/title_generator.py`

    ```diff
    @@ -48,6 +48,23 @@ def _title_language() -> str:
             return ""
     
     
    +def _auto_title_enabled() -> bool:
    +    """Return whether automatic session title generation is enabled."""
    +    try:
    +        # Lazy imports, matching _title_language(): title_generator is imported
    +        # from agent code paths where a module-level hermes_cli import risks
    +        # circularity, and the read-only loader avoids config-migration writes.
    +        from hermes_cli.config import load_config_readonly
    +        from utils import is_truthy_value
    +
    +        config = load_config_readonly()
    +        title_config = (config.get("auxiliary") or {}).get("title_generation") or {}
    +        return is_truthy_value(title_config.get("enabled"), default=True)
    +    except Exception:
    +        logger.debug("Failed to read title_generation.enabled", exc_info=True)
    +        return True
    +
    +
     def generate_title(
         user_message: str,
         assistant_response: str,
    ```

    ```diff
    @@ -66,6 +83,10 @@ def generate_title(
         ``AIAgent._emit_auxiliary_failure`` so the user sees a warning instead
         of silently accumulating untitled sessions.
         """
    +    if not _auto_title_enabled():
    +        logger.debug("Auto-title skipped: auxiliary.title_generation.enabled=false")
    +        return None
    +
         # Truncate long messages to keep the request small
         user_snippet = user_message[:500] if user_message else ""
         assistant_snippet = assistant_response[:500] if assistant_response else ""
    ```

    ```diff
    @@ -254,6 +275,12 @@ def maybe_auto_title(
         if user_msg_count > 2:
             return
     
    +    # Config read comes after the cheap first-exchange guard so the file
    +    # isn't touched on every subsequent turn of a long session.
    +    if not _auto_title_enabled():
    +        logger.debug("Auto-title skipped: auxiliary.title_generation.enabled=false")
    +        return
    +
         thread = threading.Thread(
             target=auto_title_session,
             args=(session_db, session_id, user_message, assistant_response),
    ```
  - `cli-config.yaml.example`

    ```diff
    @@ -526,6 +526,14 @@ prompt_caching:
     #     model: ""
     #     timeout: 30
     #
    +#   # Automatic session title generation after the first exchange
    +#   title_generation:
    +#     enabled: true          # set false to disable auto-title generation
    +#     provider: "auto"
    +#     model: ""
    +#     timeout: 30
    +#     language: ""           # empty = match the user's language; or e.g. "English"
    +#
     #   # Session search — summarizes matching past sessions
     #   session_search:
     #     provider: "auto"
    ```
  - `hermes_cli/config.py`

    ```diff
    @@ -1643,6 +1643,7 @@ def _ensure_hermes_home_managed(home: Path):
                 "reasoning_effort": "",  # per-task thinking level: none|minimal|low|medium|high|xhigh|max|ultra (empty = provider default)
             },
             "title_generation": {
    +            "enabled": True,
                 "provider": "auto",
                 "model": "",
                 "base_url": "",
    ```
  - `scripts/release.py`

    ```diff
    @@ -363,6 +363,7 @@
         "290859878+synapsesx@users.noreply.github.com": "synapsesx",
         "157689911+itsflownium@users.noreply.github.com": "itsflownium",
         "dirtyren@users.noreply.github.com": "dirtyren",
    +    "[redacted:email]": "s96919",
         "[redacted:email]": "doxe0x",
         "[redacted:email]": "Code-suphub",
         "78542984+Code-suphub@users.noreply.github.com": "Code-suphub",
    ```
  - `tests/agent/test_title_generator.py`

    ```diff
    @@ -210,6 +210,18 @@ def mock_call_llm(**kwargs):
             user_content = captured_kwargs["messages"][1]["content"]
             assert len(user_content) < 1100  # 500 + 500 + formatting
     
    +    def test_skips_when_title_generation_disabled(self):
    +        """auxiliary.title_generation.enabled=false disables automatic titles."""
    +        config = {"auxiliary": {"title_generation": {"enabled": False}}}
    +
    +        with (
    +            patch("hermes_cli.config.load_config_readonly", return_value=config),
    +            patch("agent.title_generator.call_llm") as mock_call_llm,
    +        ):
    +            assert generate_title("question", "answer") is None
    +
    +        mock_call_llm.assert_not_called()
    +
     
     class TestAutoTitleSession:
         """Tests for auto_title_session() — the sync worker function."""
    ```

    ```diff
    @@ -347,6 +359,23 @@ def test_fires_on_first_exchange(self):
                     title_callback=None,
                 )
     
    +    def test_skips_when_title_generation_disabled(self):
    +        """Disabled title generation should not even start the background worker."""
    +        db = MagicMock()
    +        history = [
    +            {"role": "user", "content": "hello"},
    +            {"role": "assistant", "content": "hi there"},
    +        ]
    +        config = {"auxiliary": {"title_generation": {"enabled": False}}}
    +
    +        with (
    +            patch("hermes_cli.config.load_config_readonly", return_value=config),
    +            patch("agent.title_generator.auto_title_session") as mock_auto,
    +        ):
    +            maybe_auto_title(db, "sess-1", "hello", "hi there", history)
    +
    +        mock_auto.assert_not_called()
    +
         def test_forwards_failure_callback_to_worker(self):
             """maybe_auto_title must forward failure_callback into the thread."""
             db = MagicMock()
    ```
  - `tests/hermes_cli/test_aux_config.py`

    ```diff
    @@ -36,6 +36,7 @@ def test_title_generation_present_in_default_config():
         """
         assert "title_generation" in DEFAULT_CONFIG["auxiliary"]
         tg = DEFAULT_CONFIG["auxiliary"]["title_generation"]
    +    assert tg["enabled"] is True
         assert tg["provider"] == "auto"
         assert tg["model"] == ""
         assert tg["timeout"] > 0
    ```
  - `website/docs/user-guide/configuration.md`

    ```diff
    @@ -958,6 +958,10 @@ $ hermes model
     
     Select a task, pick a provider (OAuth flows open a browser; API-key providers prompt), pick a model. The change persists to `auxiliary.<task>.*` in `config.yaml`. Same machinery as the main-model picker — no extra syntax to learn.
     
    +If you do not want Hermes to auto-generate titles after the first exchange, set
    +`auxiliary.title_generation.enabled: false`. Manual titles still work through
    +`/title` and `hermes sessions rename`.
    +
     ### Video Tutorial
     
     <div style={{position: 'relative', width: '100%', aspectRatio: '16 / 9', marginBottom: '1.5rem'}}>
    ```

    ```diff
    @@ -1070,6 +1074,7 @@ auxiliary:
       # Auto-generated session titles. Empty language follows the conversation;
       # set e.g. "English" or "Japanese" to pin titles to one language.
       title_generation:
    +    enabled: true              # set false to disable auto-title generation
         provider: "auto"
         model: ""
         base_url: ""
    ```
- **#113955: fix(aux): session titles keep the instant derived title while the model upgrade is switched off (#85194, salvage #85401)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/title_generator.py`, `cli-config.yaml.example`, `contributors/emails/[redacted:email]`, `hermes_cli/config_defaults.py`, `tests/agent/test_title_generator.py`, `website/docs/user-guide/configuration.md`
- **#27977: feat(auxiliary): add enabled toggle for individual auxiliary tasks (#27877)**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `e20c3c1c29a37806ac7c06c7d743433657839667`, `#113955`
- **#41760: fix(auxiliary): respect auxiliary.title_generation.enabled config**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#66049`, `#37349`
- **#41951: fix(title_gen): honor auxiliary.title_generation.enabled config setting (#41744)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#41760`, `#41744`, `#37349`
- **#42098: fix(agent): honor auxiliary.title_generation.enabled to disable auto titles**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#66049`, `#37349`

## Fix status

- Merged to main in PR #113955 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-09-17`.
- Subsystem: `agent`
