fix(deepseek): preserve reasoning_content in thinking mode for tool calls#1020
fix(deepseek): preserve reasoning_content in thinking mode for tool calls#1020tlotli wants to merge 1 commit into
Conversation
…alls DeepSeek's thinking mode requires reasoning_content to be passed back in all subsequent requests when tool calls are involved. Without this, the API returns 400: 'The reasoning_content in the thinking mode must be passed back to the API.' Two fixes: - Text.php: Extract reasoning_content from raw response and include it in AssistantMessage.additionalContent for both tool call steps and the final response step. - MessageMap.php: Merge additionalContent into the API payload so reasoning_content is sent back to the API in multi-turn conversations. Fixes multi-turn conversations with tools in deepseek-v4-flash.
|
Hit this exact bug independently while migrating our diary agent (Calorize, ~200 paid users) to direct DeepSeek API in thinking mode. Confirmed deepseek-v4-flash (thinking) 400s on the second iteration of any multi-step tool flow without this fix. Been running a local patch with the same approach (extract reasoning_content into additionalContent, merge it back in MessageMap) for several days — works as expected, no regressions. Would love to see this merged so we can drop the override. Separately: DeepSeek\Handlers\Text::addStep() and Stream::extractUsage() also drop prompt_cache_hit_tokens and completion_tokens_details.reasoning_tokens from the usage payload. That's a different concern from this PR — I'll open a focused PR for it, non-overlapping with this change. |
Summary
reasoning_contentto be passed back in all subsequent requests when tool calls are involved. Without this, the API returns400: The reasoning_content in the thinking mode must be passed back to the API.deepseek-v4-flash(and other DeepSeek thinking-mode models).Problem
When using DeepSeek models in thinking mode with tools, Prism discards the
reasoning_contentfrom the API response:Text.phphandler createsAssistantMessagewith emptyadditionalContent— thereasoning_contentfrom the raw response is lostMessageMap.phpdoes not mergeadditionalContentinto the API payload — even ifreasoning_contentwas in the message object, it was never sent back to the APIWhen Prism recursively calls
handle()for tool-use continuation, the request includes anAssistantMessagewithoutreasoning_content→ DeepSeek returns 400.Changes
src/Providers/DeepSeek/Handlers/Text.phpreasoning_contentfrom raw response (choices.0.message.reasoning_content)AssistantMessage.additionalContentfor both:addStep()(line 128)src/Providers/DeepSeek/Maps/MessageMap.php$message->additionalContentinto the API payload viaarray_merge()(line 102-106)reasoning_contentis sent back to the API in multi-turn conversationsTesting
Verified with 4-turn conversation using tools:
References