[PR #5579] [CLOSED] fix: preserve reasoning_content through agent loop for DeepSeek thinking models #5487

Closed
opened 2026-06-05 15:21:30 -04:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Mintplex-Labs/anything-llm/pull/5579
Author: @gurodrigues
Created: 5/4/2026
Status: Closed

Base: masterHead: fix/deepseek-reasoning-content-agent-loop


📝 Commits (1)

  • d537ea0 fix: preserve reasoning_content in agent loop for DeepSeek thinking models

📊 Changes

2 files changed (+71 additions, -18 deletions)

View changed files

📝 server/utils/agents/aibitat/index.js (+47 -11)
📝 server/utils/agents/aibitat/providers/helpers/tooled.js (+24 -7)

📄 Description

Summary

This is a follow-up to #5527 which correctly added deepseek-v4-flash and deepseek-v4-pro to the #isThinkingModel list, enabling the injectReasoningContent flag. However, #5527 only addressed the detection of thinking models - the actual reasoning_content passthrough through the agent loop remained broken.

The bug: DeepSeek thinking models require the reasoning_content field from previous assistant responses to be passed back verbatim in subsequent API calls. The agent loop was:

  1. Not capturing reasoning_content from API streaming/non-streaming responses
  2. Not preserving it through tool call metadata (originalFunctionCall)
  3. Not storing it in chat history for multi-turn conversations
  4. Using an empty string "" as reasoning_content for all assistant messages, which DeepSeek rejects when the original response had actual reasoning content

The fix: Captures reasoning_content at each stage of the agent pipeline and threads it through:

  • tooled.js: tooledStream() and tooledComplete() now capture and return reasoningContent from API responses
  • tooled.js: formatMessagesForTools() uses actual reasoningContent from originalFunctionCall metadata, and correctly handles camelCase/snake_case conversion from chat history
  • aibitat/index.js: getOrFormatNodeChatHistory() preserves reasoningContent from stored chat messages
  • aibitat/index.js: handleAsyncExecution()/handleExecution() store reasoningContent in originalFunctionCall on each tool-call iteration
  • aibitat/index.js: reply() stores reasoningContent in the chat message for multi-turn preservation

Scope

This fix only affects DeepSeek thinking models (deepseek-reasoner, deepseek-v4-flash, deepseek-v4-pro). The injectReasoningContent flag is gated behind the #isThinkingModel getter in deepseek.js. No other provider is impacted.

Related

Test plan

  • Run @agent with DeepSeek deepseek-v4-pro model - agent should complete multi-turn tool calls without 400 errors
  • Run @agent with DeepSeek deepseek-v4-flash model - same verification
  • Run @agent with DeepSeek deepseek-reasoner model - same verification
  • Run @agent with a non-DeepSeek provider (e.g., OpenAI) - verify no regression
  • Run @agent with DeepSeek deepseek-chat (non-thinking model) - verify no regression
  • Verify standard (non-agent) chat continues to work with all DeepSeek models

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Mintplex-Labs/anything-llm/pull/5579 **Author:** [@gurodrigues](https://github.com/gurodrigues) **Created:** 5/4/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `fix/deepseek-reasoning-content-agent-loop` --- ### 📝 Commits (1) - [`d537ea0`](https://github.com/Mintplex-Labs/anything-llm/commit/d537ea04ca72003108ad80a682522ff56949a935) fix: preserve reasoning_content in agent loop for DeepSeek thinking models ### 📊 Changes **2 files changed** (+71 additions, -18 deletions) <details> <summary>View changed files</summary> 📝 `server/utils/agents/aibitat/index.js` (+47 -11) 📝 `server/utils/agents/aibitat/providers/helpers/tooled.js` (+24 -7) </details> ### 📄 Description ## Summary This is a follow-up to #5527 which correctly added `deepseek-v4-flash` and `deepseek-v4-pro` to the `#isThinkingModel` list, enabling the `injectReasoningContent` flag. However, #5527 only addressed the detection of thinking models - the actual `reasoning_content` passthrough through the agent loop remained broken. **The bug**: DeepSeek thinking models require the `reasoning_content` field from previous assistant responses to be passed back verbatim in subsequent API calls. The agent loop was: 1. Not capturing `reasoning_content` from API streaming/non-streaming responses 2. Not preserving it through tool call metadata (`originalFunctionCall`) 3. Not storing it in chat history for multi-turn conversations 4. Using an empty string `""` as reasoning_content for all assistant messages, which DeepSeek rejects when the original response had actual reasoning content **The fix**: Captures `reasoning_content` at each stage of the agent pipeline and threads it through: - `tooled.js`: `tooledStream()` and `tooledComplete()` now capture and return `reasoningContent` from API responses - `tooled.js`: `formatMessagesForTools()` uses actual reasoningContent from `originalFunctionCall` metadata, and correctly handles camelCase/snake_case conversion from chat history - `aibitat/index.js`: `getOrFormatNodeChatHistory()` preserves `reasoningContent` from stored chat messages - `aibitat/index.js`: `handleAsyncExecution()`/`handleExecution()` store reasoningContent in `originalFunctionCall` on each tool-call iteration - `aibitat/index.js`: `reply()` stores reasoningContent in the chat message for multi-turn preservation ## Scope This fix **only affects DeepSeek thinking models** (`deepseek-reasoner`, `deepseek-v4-flash`, `deepseek-v4-pro`). The `injectReasoningContent` flag is gated behind the `#isThinkingModel` getter in `deepseek.js`. No other provider is impacted. ## Related - Resolves #5570 - Follow-up to #5527 - Related: #5509, #5525, #5523 ## Test plan - [ ] Run `@agent` with DeepSeek `deepseek-v4-pro` model - agent should complete multi-turn tool calls without 400 errors - [ ] Run `@agent` with DeepSeek `deepseek-v4-flash` model - same verification - [ ] Run `@agent` with DeepSeek `deepseek-reasoner` model - same verification - [ ] Run `@agent` with a non-DeepSeek provider (e.g., OpenAI) - verify no regression - [ ] Run `@agent` with DeepSeek `deepseek-chat` (non-thinking model) - verify no regression - [ ] Verify standard (non-agent) chat continues to work with all DeepSeek models --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-06-05 15:21:30 -04:00
yindo closed this issue 2026-06-05 15:21:31 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Mintplex-Labs/anything-llm#5487