Make replaying reasoning content opt-out - #6986
Open
chengwudi1 wants to merge 1 commit into
Open
chengwudi1 wants to merge 1 commit into
chengwudi1 wants to merge 1 commit into
Conversation
reasoning_content is echoed back on an assistant message so that
OpenAI-compatible reasoning endpoints which require it keep working:
DeepSeek's thinking mode returns HTTP 400 when an assistant turn that
carried reasoning arrives without it. Other endpoints return the
property but reject it on the way back, so Groq answers a follow-up
request built from such a history with
400: 'messages.6' : for 'role:assistant' ...
property 'reasoning_content' is unsupported
Both cannot be satisfied at once, so the replay becomes configurable:
OpenAiChatOptions.replayReasoningContent defaults to null, which keeps
sending the property whenever it is present, and a value of false
stops it. The property is also exposed as
spring.ai.openai.chat.replay-reasoning-content.
Closes spring-projects#6968
Signed-off-by: chengwudi1 <chengwudi1@users.noreply.github.com>
chengwudi1
force-pushed
the
fix-replay-reasoning-content
branch
from
September 14, 2026 04:18
37cff71 to
c9db89f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6968
Problem
reasoning_contentis echoed back on assistant messages so thatOpenAI-compatible reasoning endpoints which require it keep working.
DeepSeek's thinking mode answers HTTP 400 when an assistant turn that
carried reasoning arrives without it (#6296), which is why the replay was
added in the first place.
Endpoints in the opposite position return the property but reject it on
the way back. Groq answers a follow-up request built from such a history
with:
The first model invocation succeeds; it is the second one — after
ToolCallingAdvisorhas run the tool and rebuilt the request from theconversation history — that fails. Since the two requirements are
mutually exclusive, no unconditional behavior can satisfy both.
Change
The replay becomes configurable rather than unconditional:
OpenAiChatOptions.replayReasoningContentdefaults tonull, whichkeeps today's behavior: the property is sent whenever it is present.
Setting it to
falsestops the replay. The assistant turn itself isstill sent as before — only the
reasoning_contentproperty is dropped.spring.ai.openai.chat.replay-reasoning-content.Nothing changes for OpenAI itself (the property is only added when the
assistant message carries reasoning content) and nothing changes for
DeepSeek (the default stays on).
Tests
OpenAiChatModelTests.reasoningContentNotReplayedWhenOptedOut— buildsa request from an assistant message carrying reasoning with the opt-out
set, asserts the property is absent, and asserts the assistant content is
still sent. It fails without the guard in
createRequest(verified byremoving the guard locally: the property reappears).
OpenAiChatOptionsbuilder coverage: bothmutate()andcombineWith(...)carry the new option.OpenAiChatPropertiesTests.chatReplayReasoningContentTest— the propertybinds, reaches
toOptions(), andchatReplayReasoningContentDefaultsToReplayingpins that it stays unsetby default.
Verification
checkstyle, javaformat and enforcer are clean.
(Both commands are run from the repository root. The build cache is
disabled because it otherwise skips the surefire execution and the build
reports success without running any test.)
Documentation
One row added to the OpenAI chat property table in
spring-ai-docs/.../api/chat/openai-chat.adoc.