{"repo":"NousResearch/hermes-agent","public_id":"27877","display_label":"Toggle to enable/disable automatic title generation","summary":"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.","subsystem":"agent","counts":{"members":10,"open_issues":1,"open_issues_distinct":1,"open_prs":0,"closed_issues":3,"merged_prs":2,"attempt_prs":4},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":113955,"merged_at":"2026-09-17T15:45:09+00:00"},"resolution":{"state":"unresolved","by":null},"freshness":{"state":"verified","last_verified_at":"2026-09-17T15:45:09+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.15733333333333335},"fix_edges":[{"issue_number":27877,"pr_number":113955,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-09-17T15:45:09+00:00"},{"issue_number":41744,"pr_number":66049,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-07-17T05:24:46+00:00"},{"issue_number":85194,"pr_number":113955,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-09-17T15:45:09+00:00"}],"members":[{"kind":"issue","number":27877,"title":"Feature: add `enabled` toggle for auxiliary tasks (title_generation, etc.)","url":null,"state":"closed"},{"kind":"issue","number":29456,"title":"[Feature]: Ability to toggle title generation","url":null,"state":"open"},{"kind":"issue","number":41744,"title":"auxiliary.title.enabled config is ignored — title generation runs regardless","url":null,"state":"closed"},{"kind":"issue","number":54577,"title":"bug(title_generation): `enabled: false` config is ignored, title generation always runs","url":null,"state":"closed"},{"kind":"pr","number":27977,"title":"feat(auxiliary): add enabled toggle for individual auxiliary tasks (#27877)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"e20c3c1c29a37806ac7c06c7d743433657839667","number":0},{"kind":"pr","value":"#113955","number":113955}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":41760,"title":"fix(auxiliary): respect auxiliary.title_generation.enabled config","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#66049","number":66049},{"kind":"pr","value":"#37349","number":37349}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":41951,"title":"fix(title_gen): honor auxiliary.title_generation.enabled config setting (#41744)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#41760","number":41760},{"kind":"pr","value":"#41744","number":41744},{"kind":"pr","value":"#37349","number":37349}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":42098,"title":"fix(agent): honor auxiliary.title_generation.enabled to disable auto titles","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#66049","number":66049},{"kind":"pr","value":"#37349","number":37349}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":66049,"title":"fix(title): honor auxiliary.title_generation.enabled to disable auto titles (salvage #37349)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["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":[{"file":"agent/title_generator.py","hunks":["@@ -48,6 +48,23 @@ def _title_language() -> str:\n         return \"\"\n \n \n+def _auto_title_enabled() -> bool:\n+    \"\"\"Return whether automatic session title generation is enabled.\"\"\"\n+    try:\n+        # Lazy imports, matching _title_language(): title_generator is imported\n+        # from agent code paths where a module-level hermes_cli import risks\n+        # circularity, and the read-only loader avoids config-migration writes.\n+        from hermes_cli.config import load_config_readonly\n+        from utils import is_truthy_value\n+\n+        config = load_config_readonly()\n+        title_config = (config.get(\"auxiliary\") or {}).get(\"title_generation\") or {}\n+        return is_truthy_value(title_config.get(\"enabled\"), default=True)\n+    except Exception:\n+        logger.debug(\"Failed to read title_generation.enabled\", exc_info=True)\n+        return True\n+\n+\n def generate_title(\n     user_message: str,\n     assistant_response: str,","@@ -66,6 +83,10 @@ def generate_title(\n     ``AIAgent._emit_auxiliary_failure`` so the user sees a warning instead\n     of silently accumulating untitled sessions.\n     \"\"\"\n+    if not _auto_title_enabled():\n+        logger.debug(\"Auto-title skipped: auxiliary.title_generation.enabled=false\")\n+        return None\n+\n     # Truncate long messages to keep the request small\n     user_snippet = user_message[:500] if user_message else \"\"\n     assistant_snippet = assistant_response[:500] if assistant_response else \"\"","@@ -254,6 +275,12 @@ def maybe_auto_title(\n     if user_msg_count > 2:\n         return\n \n+    # Config read comes after the cheap first-exchange guard so the file\n+    # isn't touched on every subsequent turn of a long session.\n+    if not _auto_title_enabled():\n+        logger.debug(\"Auto-title skipped: auxiliary.title_generation.enabled=false\")\n+        return\n+\n     thread = threading.Thread(\n         target=auto_title_session,\n         args=(session_db, session_id, user_message, assistant_response),"]},{"file":"cli-config.yaml.example","hunks":["@@ -526,6 +526,14 @@ prompt_caching:\n #     model: \"\"\n #     timeout: 30\n #\n+#   # Automatic session title generation after the first exchange\n+#   title_generation:\n+#     enabled: true          # set false to disable auto-title generation\n+#     provider: \"auto\"\n+#     model: \"\"\n+#     timeout: 30\n+#     language: \"\"           # empty = match the user's language; or e.g. \"English\"\n+#\n #   # Session search — summarizes matching past sessions\n #   session_search:\n #     provider: \"auto\""]},{"file":"hermes_cli/config.py","hunks":["@@ -1643,6 +1643,7 @@ def _ensure_hermes_home_managed(home: Path):\n             \"reasoning_effort\": \"\",  # per-task thinking level: none|minimal|low|medium|high|xhigh|max|ultra (empty = provider default)\n         },\n         \"title_generation\": {\n+            \"enabled\": True,\n             \"provider\": \"auto\",\n             \"model\": \"\",\n             \"base_url\": \"\","]},{"file":"scripts/release.py","hunks":["@@ -363,6 +363,7 @@\n     \"290859878+synapsesx@users.noreply.github.com\": \"synapsesx\",\n     \"157689911+itsflownium@users.noreply.github.com\": \"itsflownium\",\n     \"dirtyren@users.noreply.github.com\": \"dirtyren\",\n+    \"[redacted:email]\": \"s96919\",\n     \"[redacted:email]\": \"doxe0x\",\n     \"[redacted:email]\": \"Code-suphub\",\n     \"78542984+Code-suphub@users.noreply.github.com\": \"Code-suphub\","]},{"file":"tests/agent/test_title_generator.py","hunks":["@@ -210,6 +210,18 @@ def mock_call_llm(**kwargs):\n         user_content = captured_kwargs[\"messages\"][1][\"content\"]\n         assert len(user_content) < 1100  # 500 + 500 + formatting\n \n+    def test_skips_when_title_generation_disabled(self):\n+        \"\"\"auxiliary.title_generation.enabled=false disables automatic titles.\"\"\"\n+        config = {\"auxiliary\": {\"title_generation\": {\"enabled\": False}}}\n+\n+        with (\n+            patch(\"hermes_cli.config.load_config_readonly\", return_value=config),\n+            patch(\"agent.title_generator.call_llm\") as mock_call_llm,\n+        ):\n+            assert generate_title(\"question\", \"answer\") is None\n+\n+        mock_call_llm.assert_not_called()\n+\n \n class TestAutoTitleSession:\n     \"\"\"Tests for auto_title_session() — the sync worker function.\"\"\"","@@ -347,6 +359,23 @@ def test_fires_on_first_exchange(self):\n                 title_callback=None,\n             )\n \n+    def test_skips_when_title_generation_disabled(self):\n+        \"\"\"Disabled title generation should not even start the background worker.\"\"\"\n+        db = MagicMock()\n+        history = [\n+            {\"role\": \"user\", \"content\": \"hello\"},\n+            {\"role\": \"assistant\", \"content\": \"hi there\"},\n+        ]\n+        config = {\"auxiliary\": {\"title_generation\": {\"enabled\": False}}}\n+\n+        with (\n+            patch(\"hermes_cli.config.load_config_readonly\", return_value=config),\n+            patch(\"agent.title_generator.auto_title_session\") as mock_auto,\n+        ):\n+            maybe_auto_title(db, \"sess-1\", \"hello\", \"hi there\", history)\n+\n+        mock_auto.assert_not_called()\n+\n     def test_forwards_failure_callback_to_worker(self):\n         \"\"\"maybe_auto_title must forward failure_callback into the thread.\"\"\"\n         db = MagicMock()"]},{"file":"tests/hermes_cli/test_aux_config.py","hunks":["@@ -36,6 +36,7 @@ def test_title_generation_present_in_default_config():\n     \"\"\"\n     assert \"title_generation\" in DEFAULT_CONFIG[\"auxiliary\"]\n     tg = DEFAULT_CONFIG[\"auxiliary\"][\"title_generation\"]\n+    assert tg[\"enabled\"] is True\n     assert tg[\"provider\"] == \"auto\"\n     assert tg[\"model\"] == \"\"\n     assert tg[\"timeout\"] > 0"]},{"file":"website/docs/user-guide/configuration.md","hunks":["@@ -958,6 +958,10 @@ $ hermes model\n \n 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.\n \n+If you do not want Hermes to auto-generate titles after the first exchange, set\n+`auxiliary.title_generation.enabled: false`. Manual titles still work through\n+`/title` and `hermes sessions rename`.\n+\n ### Video Tutorial\n \n <div style={{position: 'relative', width: '100%', aspectRatio: '16 / 9', marginBottom: '1.5rem'}}>","@@ -1070,6 +1074,7 @@ auxiliary:\n   # Auto-generated session titles. Empty language follows the conversation;\n   # set e.g. \"English\" or \"Japanese\" to pin titles to one language.\n   title_generation:\n+    enabled: true              # set false to disable auto-title generation\n     provider: \"auto\"\n     model: \"\"\n     base_url: \"\"\n"]}]},{"kind":"pr","number":113955,"title":"fix(aux): session titles keep the instant derived title while the model upgrade is switched off (#85194, salvage #85401)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["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"]}],"trust":{"default_tier":"verified","includes_suggested":false}}