{"repo":"NousResearch/hermes-agent","public_id":"149","display_label":"Strip think blocks leaking into user-facing responses","summary":"Multiple fixes addressing a recurring issue where internal <think> blocks were leaking into user-visible output across streaming, storage, API replay, resume, and fallback response paths. The work spans several layers of the system with incremental and defensive filtering approaches.","subsystem":"gateway","counts":{"members":6,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":4},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":174},"resolution":{"state":"resolved","by":"pr-174"},"freshness":{"state":"stale","last_verified_at":"2026-03-01T00:43:47+00:00","is_stale":true},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.3333333333333333},"fix_edges":[{"issue_number":149,"pr_number":174,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":149,"title":"<think> blocks leak into user-facing responses","url":null,"state":"closed"},{"kind":"pr","number":174,"title":"fix: strip <think> blocks from final response to users","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["run_agent.py"],"fix_hunks":[{"file":"run_agent.py","hunks":["@@ -2567,7 +2567,8 @@ def run_conversation(\n                                             tool_names.append(fn.get(\"name\", \"unknown\"))\n                                         msg[\"content\"] = f\"Calling the {', '.join(tool_names)} tool{'s' if len(tool_names) > 1 else ''}...\"\n                                         break\n-                                final_response = fallback\n+                                # Strip <think> blocks from fallback content for user display\n+                                final_response = self._strip_think_blocks(fallback).strip()\n                                 break\n                             \n                             # No fallback -- append the empty message as-is","@@ -2596,6 +2597,9 @@ def run_conversation(\n                     if hasattr(self, '_empty_content_retries'):\n                         self._empty_content_retries = 0\n                     \n+                    # Strip <think> blocks from user-facing response (keep raw in messages for trajectory)\n+                    final_response = self._strip_think_blocks(final_response).strip()\n+                    \n                     final_msg = self._build_assistant_message(assistant_message, finish_reason)\n                     \n                     messages.append(final_msg)\n"]}]},{"kind":"pr","number":196,"title":"Fix: strip <think> blocks from fallback final responses","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#149","number":149}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":205,"title":"fix(agent): strip <think> blocks from final response before displaying to user","url":null,"state":"closed","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":208,"title":"fix(agent): strip <think> blocks from final response before displaying to user","url":null,"state":"closed","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":28631,"title":"fix(stream-consumer): case-insensitive think-block filtering with defence-in-depth scrub","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#27289","number":27289},{"kind":"pr","value":"#27288","number":27288},{"kind":"pr","value":"#27289","number":27289},{"kind":"pr","value":"#27289","number":27289},{"kind":"pr","value":"#27289","number":27289},{"kind":"pr","value":"#27289","number":27289},{"kind":"pr","value":"#27289","number":27289}],"category":"duplicate_of","implication":"duplicate"},"merged":false}],"trust":{"default_tier":"verified","includes_suggested":false}}