Skip to content

fix: surface reasoning/thinking content as response instead of '(empty)' - #58148

Closed
Sahil-SS9 wants to merge 1 commit into
NousResearch:mainfrom
Sahil-SS9:fix/issue-58117-deliver-reasoning-on-empty-response
Closed

Sahil-SS9 wants to merge 1 commit into
NousResearch:mainfrom
Sahil-SS9:fix/issue-58117-deliver-reasoning-on-empty-response

Conversation

@Sahil-SS9

Copy link
Copy Markdown
Contributor

Fixes #58117

Description

When a thinking model (e.g. DeepSeek V4 Flash) returns a response where all
content is inside a reasoning/thinking block — or where content is empty
and only reasoning_content is populated — the agent exhausts its prefill
and empty-response retries and eventually sets final_response = "(empty)".

This causes:

  • Blank responses — the user sees nothing despite the model having
    produced reasoning content
  • Infinite cron heartbeat loops — cron jobs keep firing because the
    response is empty, wasting $30-80+ in API costs

Fix

When retries are exhausted and reasoning/thinking content IS available,
surface it as final_response instead of "(empty)". The reasoning
text (from reasoning_content, reasoning, or reasoning_details
fields) is the model's actual response — it was just delivered through the
thinking channel rather than visible content.

Verification

  • Change is 9 lines in agent/conversation_loop.py
  • No new dependencies
  • Compile-check passes
  • Only the reasoning-exhaustion exit path is affected — successful responses
    with visible content are unchanged

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jul 4, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Duplicate of #50397 — same fix in the reasoning-exhaustion exit path of agent/conversation_loop.py (surface reasoning_text as final_response instead of "(empty)" for reasoning-only models like DeepSeek V4 Flash). #50397 was opened earlier (2026-06-21) and is the more comprehensive version (also bumps thinking-prefill retries 2->3 and sets the persisted assistant message content), so it's canonical. Cross-linking so a maintainer can pick.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean fix: surfaces reasoning/thinking content as response instead of '(empty)'. 1 file, 9 additions, well-scoped. No issues.


Reviewed by Hermes Agent

@Sahil-SS9
Sahil-SS9 force-pushed the fix/issue-58117-deliver-reasoning-on-empty-response branch from 1cd8ff1 to 6864a1e Compare July 8, 2026 10:41
@Sahil-SS9
Sahil-SS9 force-pushed the fix/issue-58117-deliver-reasoning-on-empty-response branch from 6864a1e to 299e905 Compare July 8, 2026 11:05

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused fix. The premise is confirmed on current main: agent/conversation_loop.py:5177-5214 extracts reasoning but still terminates with (empty), and tests/run_agent/test_run_agent.py:4424-4444 reproduces that path.

Problems

  • agent/conversation_loop.py:4895 leaves _turn_exit_reason as empty_response_exhausted. Current agent/turn_finalizer.py:338-366 treats a non-punctuated response of 24 characters or fewer under that reason as a partial fragment and appends the “⚠️ No reply” explainer. Thus a valid short fallback such as Yes would be delivered with a contradictory failure notice. The changed test fixture is 27 characters, so it misses this path.

Suggested changes

  • Mark the reasoning fallback as a visible text completion, or explicitly exempt it from the partial-fragment explainer; add a short reasoning-only regression test.

This is an automated hermes-sweeper review.

# content only via reasoning_content/reasoning_details
# API fields would otherwise show blank to the user
# and cause infinite retry loops (#58117).
final_response = reasoning_text

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also change the terminal reason or exempt this fallback from the completion explainer. On current main, empty_response_exhausted plus a non-punctuated response of 24 characters or fewer makes agent/turn_finalizer.py:338-366 append “⚠️ No reply”; a valid reasoning fallback such as Yes would therefore receive a contradictory failure footer.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
@Sahil-SS9

Copy link
Copy Markdown
Contributor Author

Thanks @tonydwb for the review.

@alt-glitch — noted on the duplicate flag. #50397 was filed first and covers the same reasoning-exhaustion exit path. I checked #50397 and it's still open. Closing this one in favour of the earlier PR.

@Sahil-SS9

Copy link
Copy Markdown
Contributor Author

Closing as duplicate of #50397 (filed earlier, same fix in the reasoning-exhaustion exit path). Thanks to @alt-glitch for flagging the overlap.

@Sahil-SS9 Sahil-SS9 closed this Jul 31, 2026
@Sahil-SS9
Sahil-SS9 deleted the fix/issue-58117-deliver-reasoning-on-empty-response branch August 2, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Thinking blocks cause blank text responses in CLI mode + infinite heartbeat loops

4 participants