hermes - ✅(Solved) Fix regression: #15749 breaks reasoning field promotion for DeepSeek/Kimi tool-call messages [2 pull requests, 2 comments, 2 participants]

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…
GitHub stats
NousResearch/hermes-agent#15812Fetched 2026-04-26 05:24:52
View on GitHub
Comments
2
Participants
2
Timeline
14
Reactions
0
Author
Participants
Timeline (top)
labeled ×5subscribed ×3commented ×2cross-referenced ×2

PR #15749 (merged) introduced a regression where assistant messages with both and a valid field get their reasoning content overwritten with an empty string when using DeepSeek or Kimi thinking mode.

Root Cause

In , #15749 reordered the logic so that the check (step 2) runs before the field promotion (step 3). This means:

  1. A message has and
  2. Step 2 sees + DeepSeek provider → injects → returns early
  3. Step 3 (promote to ) is never reached
  4. The valid reasoning content is lost

Fix Action

Fixed

PR fix notes

PR #15830: fix(reasoning): promote reasoning field before empty-pad for DeepSeek/Kimi (#15812)

Description (problem / solution / changelog)

Summary

  • _copy_reasoning_content_for_api had a step-ordering bug introduced by PR #15749: the tool-call empty-string injection (old step 2) ran before the reasoning field promotion (old step 3)
  • A tool-call message with a valid reasoning field but no reasoning_content would hit the empty-string path, get reasoning_content="" injected, and return early — the reasoning value was silently discarded
  • Fix: move the reasoningreasoning_content promotion to step 2, before the empty-string fallbacks

The bug

run_agent.py_copy_reasoning_content_for_api (pre-fix):

# Step 1: explicit reasoning_content → preserve ✓
# Step 2: tool_calls + DeepSeek/Kimi → inject ""  ← fires here
#         RETURNS EARLY
# Step 3: reasoning field → promote               ← never reached

A message like {"role": "assistant", "reasoning": "thought trace", "tool_calls": [...]} on a DeepSeek session would return reasoning_content="" instead of reasoning_content="thought trace".

The fix

Reorder steps 2 and 3 so reasoning promotion runs first:

# Step 1: explicit reasoning_content → preserve
# Step 2: reasoning field present → promote to reasoning_content  ← moved up
# Step 3: tool_calls + DeepSeek/Kimi + no reasoning → inject ""
# Step 4: all other DeepSeek/Kimi + no reasoning → inject ""
# Step 5: non-string cleanup

Empty-string injection now only fires when neither reasoning_content nor reasoning is present — the poisoned-history case it was designed for.

Test plan

  • Before: test_deepseek_reasoning_field_promotedAssertionError: assert '' == 'thought trace'
  • After: all 21 tests in test_deepseek_reasoning_content_echo.py pass
  • Regression guard: reverted run_agent.pytest_deepseek_reasoning_field_promoted failed with '' != 'thought trace'; restored → 21 passing
  • Broader suite: tests/run_agent/ — 1048 passed, 1 pre-existing baseline failure (test_inf_stays_string_for_integer_only reproduces on clean origin/main)

Related

  • Fixes #15812
  • Regression introduced by #15749
  • Related: #15748 (same code path)

🤖 Generated with Claude Code

Changed files

  • run_agent.py (modified, +14/-12)

PR #15883: fix(run_agent): prevent reasoning_content regression in DeepSeek/Kimi tool-call replay (#15812)

Description (problem / solution / changelog)

Problem

PR #15478 fixed missing reasoning_content for DeepSeek API calls, but introduced a regression in the logic order of _copy_reasoning_content_for_api.

Regression Detail

When a message contains:

  • role: assistant
  • tool_calls (non-empty)
  • reasoning: "some genuine reasoning" (from a prior provider that uses the internal reasoning key)
  • No reasoning_content

The old (buggy) order was:

  1. Preserve explicit reasoning_content → skip (not present)
  2. DeepSeek/Kimi tool-call check → inject ""returnreasoning never promoted
  3. Promote reasoning field → never reached

Result: genuine reasoning content is lost, replaced by empty string.

Fix

Swap steps 2 and 3 so promotion happens before the empty-string fallback:

1. Preserve explicit reasoning_content
2. Promote 'reasoning' field (MOVED UP) ← fix
3. DeepSeek/Kimi tool-call empty-string fallback (MOVED DOWN)
4. Non-thinking provider cleanup

Verification

pytest tests/run_agent/test_deepseek_reasoning_content_echo.py -v: 21/21 passed

Key regression test: test_deepseek_reasoning_field_promoted → PASSED

References

  • Fixes #15812
  • Relates #15749, #15478

Checklist

  • Bug fix (non-breaking change)
  • Tests pass (21/21)
  • Only run_agent.py modified (single-file change)
  • Comments updated to explain ordering rationale

Changed files

  • run_agent.py (modified, +11/-8)
RAW_BUFFERClick to expand / collapse

Summary

PR #15749 (merged) introduced a regression where assistant messages with both and a valid field get their reasoning content overwritten with an empty string when using DeepSeek or Kimi thinking mode.

Root Cause

In , #15749 reordered the logic so that the check (step 2) runs before the field promotion (step 3). This means:

  1. A message has and
  2. Step 2 sees + DeepSeek provider → injects → returns early
  3. Step 3 (promote to ) is never reached
  4. The valid reasoning content is lost

Expected Behavior

The field should be promoted to before any empty-string fallback is applied. The empty-string injection should only happen when there is no explicit AND no field to promote.

Reproduction

Proposed Fix

Reorder the steps in :

  1. Preserve explicit
  2. Promote field → (healthy path)
  3. DeepSeek/Kimi fallback: inject for messages lacking both
  4. Clean up non-string

This fix is already included in #15478 (rebased on latest main).

Related

  • #15478 — fixes this regression + extends empty-string padding to all assistant messages (not just tool-call turns)
  • #15250 — original issue about missing reasoning_content causing HTTP 400
  • #15749 — the merged PR that introduced this regression

/cc @alt-glitch @OutThisLife

extent analysis

TL;DR

Reorder the logic in the affected code to promote the reasoning_content field to reasoning before applying the empty-string fallback.

Guidance

  • Review the proposed fix in #15478, which reorders the steps to preserve explicit reasoning and promote reasoning_content to reasoning before applying the DeepSeek/Kimi fallback.
  • Verify that the fix works by testing assistant messages with both reasoning_content and a valid reasoning field using DeepSeek or Kimi thinking mode.
  • Check the related issues (#15250 and #15749) to understand the original problem and the introduced regression.
  • Apply the fix from #15478 to resolve the regression and ensure the correct promotion of reasoning_content to reasoning.

Example

No code snippet is provided as the issue does not contain explicit code, but the proposed fix in #15478 should be reviewed and applied.

Notes

The fix is already included in #15478, which is rebased on the latest main branch. This fix not only resolves the regression but also extends empty-string padding to all assistant messages.

Recommendation

Apply the workaround by merging the fix from #15478, as it addresses the regression and provides additional functionality for empty-string padding.

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