hermes - 💡(How to fix) Fix Feature Request: Strip reasoning/<think> blocks from TTS preprocessing

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Neither of the two TTS text-preparation functions strips reasoning/<think> blocks:

  1. prepare_tts_text (gateway/platforms/base.py:2264) — strips markdown formatting, truncates to 4000 chars. No reasoning filter.
  2. _strip_markdown_for_tts (tools/tts_tool.py:2252) — strips code blocks, links, bold, italic, headers, lists. No reasoning filter.

The <think> regex does exist in the codebase at tools/tts_tool.py:2340, but it is only used in stream_tts_to_speaker() (the ElevenLabs streaming path) — not in the general TTS pipeline.

Code Example

# tools/tts_tool.py
_THINK_BLOCK = re.compile(r"<think[\s>].*?</think>", flags=re.DOTALL)

def _strip_markdown_for_tts(text: str) -> str:
    text = _THINK_BLOCK.sub("", text)  # strip reasoning before anything else
    # ... existing markdown stripping ...
RAW_BUFFERClick to expand / collapse

Problem

When /reasoning show is enabled, the model's reasoning/thinking content is included in the final assistant message. TTS (text-to-speech) receives this full text and reads the reasoning aloud, which is undesirable — users want to see reasoning but not hear it spoken.

Current behavior

/reasoning settingTTS reads
hideOnly the response body ✅
showReasoning blocks plus response body 😵

Root Cause

Neither of the two TTS text-preparation functions strips reasoning/<think> blocks:

  1. prepare_tts_text (gateway/platforms/base.py:2264) — strips markdown formatting, truncates to 4000 chars. No reasoning filter.
  2. _strip_markdown_for_tts (tools/tts_tool.py:2252) — strips code blocks, links, bold, italic, headers, lists. No reasoning filter.

The <think> regex does exist in the codebase at tools/tts_tool.py:2340, but it is only used in stream_tts_to_speaker() (the ElevenLabs streaming path) — not in the general TTS pipeline.

Proposed Solution

Add <think>...</think> block stripping to _strip_markdown_for_tts() so it applies to all TTS providers uniformly:

# tools/tts_tool.py
_THINK_BLOCK = re.compile(r"<think[\s>].*?</think>", flags=re.DOTALL)

def _strip_markdown_for_tts(text: str) -> str:
    text = _THINK_BLOCK.sub("", text)  # strip reasoning before anything else
    # ... existing markdown stripping ...

This would:

  • Apply to all TTS providers (Edge, OpenAI, ElevenLabs, Mistral, etc.)
  • Not affect the displayed text (reasoning still visible)
  • Only affect the audio output

Environment

  • Hermes Agent (git-installed, up to date)
  • TTS provider: Edge TTS (zh-CN-XiaoxiaoNeural)
  • Platform: Telegram

Additional Context

The same issue applies to non-<think> reasoning formats (e.g., DeepSeek's reasoning_content field, MiniMax thinking blocks). A more comprehensive solution might check for reasoning_content in the API response and exclude it from the TTS feed, but stripping <think> blocks in TTS preprocessing is the simplest first step that covers most cases.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING