{"repo":"NousResearch/hermes-agent","public_id":"4285","display_label":"Orphaned think/reasoning tags appearing in user-facing responses","summary":"The members concern orphaned think or reasoning tags, specifically closing </think> tags, appearing in user-facing responses. One is a bug report and two are identically titled pull requests proposing to strip such tags; the titles alone do not show whether any change was merged or works.","subsystem":"agent","counts":{"members":3,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":4311,"merged_at":"2026-03-31T18:42:45+00:00"},"resolution":{"state":"resolved","by":"pr-4311"},"freshness":{"state":"stale","last_verified_at":"2026-03-31T18:42:45+00:00","is_stale":true},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.6666666666666666},"fix_edges":[{"issue_number":4285,"pr_number":4311,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-03-31T18:42:45+00:00"}],"members":[{"kind":"issue","number":4285,"title":"[Bug]: Orphaned </think> closing tags leak into user-facing responses","url":null,"state":"closed"},{"kind":"pr","number":4286,"title":"fix: strip orphaned think/reasoning tags from user-facing responses","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#4311","number":4311}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":4311,"title":"fix: strip orphaned think/reasoning tags from user-facing responses","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["run_agent.py","tests/test_run_agent.py"],"fix_hunks":[{"file":"run_agent.py","hunks":["@@ -1389,6 +1389,7 @@ def _strip_think_blocks(self, content: str) -> str:\n         content = re.sub(r'<thinking>.*?</thinking>', '', content, flags=re.DOTALL | re.IGNORECASE)\n         content = re.sub(r'<reasoning>.*?</reasoning>', '', content, flags=re.DOTALL)\n         content = re.sub(r'<REASONING_SCRATCHPAD>.*?</REASONING_SCRATCHPAD>', '', content, flags=re.DOTALL)\n+        content = re.sub(r'</?(?:think|thinking|reasoning|REASONING_SCRATCHPAD)>\\s*', '', content, flags=re.IGNORECASE)\n         return content\n \n     def _looks_like_codex_intermediate_ack("]},{"file":"tests/test_run_agent.py","hunks":["@@ -230,6 +230,27 @@ def test_multiline_block_removed(self, agent):\n         assert \"line1\" not in result\n         assert \"visible\" in result\n \n+    def test_orphaned_closing_think_tag(self, agent):\n+        result = agent._strip_think_blocks(\"some reasoning</think>actual answer\")\n+        assert \"</think>\" not in result\n+        assert \"actual answer\" in result\n+\n+    def test_orphaned_closing_thinking_tag(self, agent):\n+        result = agent._strip_think_blocks(\"reasoning</thinking>answer\")\n+        assert \"</thinking>\" not in result\n+        assert \"answer\" in result\n+\n+    def test_orphaned_opening_think_tag(self, agent):\n+        result = agent._strip_think_blocks(\"<think>orphaned reasoning without close\")\n+        assert \"<think>\" not in result\n+\n+    def test_mixed_orphaned_and_paired_tags(self, agent):\n+        text = \"stray</think><think>paired reasoning</think> visible\"\n+        result = agent._strip_think_blocks(text)\n+        assert \"</think>\" not in result\n+        assert \"<think>\" not in result\n+        assert \"visible\" in result\n+\n \n class TestExtractReasoning:\n     def test_reasoning_field(self, agent):\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}