fix(together_ai): strip internal thinking fields from outbound messages, keep reasoning_content - #38275
Merged
mateo-berri merged 2 commits intoAug 25, 2026
Conversation
…es, pin chat_template_kwargs passthrough
Contributor
Greptile SummaryThe PR sanitizes Together AI assistant-message payloads while preserving reasoning content used for replayed thinking.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| litellm/llms/together_ai/chat/transformation.py | Adds provider-boundary sanitization for internal assistant fields while retaining reasoning_content across synchronous and asynchronous transformations. |
| tests/test_litellm/llms/together_ai/chat/test_together_ai_chat_transformation.py | Adds focused transformation and request-capture coverage for field stripping, reasoning replay, and chat-template passthrough. |
Reviews (2): Last reviewed commit: "test(together_ai): annotate preserved-th..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Contributor
Author
Contributor
Author
|
bugbot run |
Contributor
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8a61b28. Configure here.
mateo-berri
enabled auto-merge
August 25, 2026 23:13
ryan-crabbe-berri
approved these changes
Aug 25, 2026
This was referenced Aug 25, 2026
8 tasks
deepanshululla
pushed a commit
to deepanshululla/litellm
that referenced
this pull request
Aug 26, 2026
…ges surfaces Adds streaming, async, /v1/responses, and /v1/messages coverage for the Together AI overhaul (BerriAI#38233, BerriAI#38248, BerriAI#38230, BerriAI#38265, BerriAI#38275), plus the legacy api.together.xyz host and TOGETHER_AI_API_BASE through litellm.completion. Each new test fails under a one-line mutation of the merged code.
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.
TLDR
Problem this solves:
thinking_blocksandprovider_specific_fieldschat_template_kwargspassthrough or preserved-thinking replayHow it solves it:
reasoning_content: Together consumes it for preserved thinkingUser Flow
Before: a developer chats with Together's GLM-5.2 in preserved-thinking mode through the proxy, and the request forwarded to Together carries litellm-internal junk fields
chat_template_kwargs: {"clear_thinking": false}thinking_blockson the assistant message (plusprovider_specific_fieldswhen an OpenAI-SDK client replays a LiteLLM response verbatim), undocumented fields Together happens to ignore todayAfter: the same chat works and the request Together receives is clean
chat_template_kwargs: {"clear_thinking": false}reasoning_contentstill reaches Togethercontentandreasoning_content, no litellm-internal fieldsRelevant issues
Linear ticket
Resolves LIT-5967
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Both legs booted a live proxy with 2 uvicorn workers (no DB) hitting the real Together API, with
qwen-hybrid = together_ai/Qwen/Qwen3.5-9Bandglm-52 = together_ai/zai-org/GLM-5.2. Same five cases per leg; only the checked-out commit differs. The one commit since the proven tip, 8a61b28, only annotates test helpers, so it cannot change behavior and the proof standsBefore (merge base e4ff44f, port 39605)
Case 1: /v1/chat/completions kwargs passthrough (non-streaming)
With kwargs: content
"391", message keys['content','role'], noreasoning_content. Control (same body minuschat_template_kwargs): content"391"withreasoning_contentpresent. Passthrough already worked hereCase 2: same, streaming
With kwargs: 0 delta chunks carrying
reasoning_content, answer"401"(thinking-off model artifact). Control: 359 reasoning deltas, answer"391"Case 3: /v1/responses kwargs passthrough
With kwargs: output item types
['message']. Control:['reasoning','message']Case 4: /v1/messages preserved thinking (GLM-5.2)
Turn 1 thinking picked secret 42, text
"6". Turn 2 replied"42": the replayed thinking reached the model. But the proxy debug log's "POST Request Sent from LiteLLM" to https://api.together.ai/v1/chat/completions shows the outbound assistant message keys as['content','reasoning_content','role','thinking_blocks']:thinking_blocksleakedCase 5: /v1/chat/completions verbatim-history replay (GLM-5.2)
Turn 1 (same secret prompt) answered
"11"with reasoning settling on 47. Turn 2 replayed the assistant message withreasoning_content,thinking_blocks, andprovider_specific_fieldsexactly as a LiteLLM response carries them, plus"chat_template_kwargs":{"clear_thinking":false}:Reply
"47", the correct secret. Outbound assistant message keys:['content','provider_specific_fields','reasoning_content','role','thinking_blocks']withprovider_specific_fields: {'thinking_blocks': []}: all three litellm-internal keys leaked to TogetherAfter (tip 1ba66b1, port 37398)
Case 1: /v1/chat/completions kwargs passthrough (non-streaming)
Same command on port 37398. With kwargs: content
"391", keys['content','role']. Control:"391"withreasoning_content. UnchangedCase 2: same, streaming
With kwargs: 0 reasoning deltas, content
"391". Control: 346 reasoning deltas. UnchangedCase 3: /v1/responses kwargs passthrough
With kwargs: output item types
['message'], text"391". Control:['reasoning','message']. UnchangedCase 4: /v1/messages preserved thinking (GLM-5.2)
Turn 1 thinking picked 42, text
"6". Turn 2 (same verbatim replay +{"clear_thinking": false}) replied"42", and the outbound body now shows the assistant message asthinking_blocksabsent,provider_specific_fieldsabsent,reasoning_contentpresent and still consumed (the recall proves it)Case 5: /v1/chat/completions verbatim-history replay (GLM-5.2)
Turn 1 picked 73, answered
"10". Turn 2 with all three internal fields replayed replied"73", and the outbound assistant message carries onlyrole,content, andreasoning_contentalongside'chat_template_kwargs': {'clear_thinking': False}in the bodyClosing notes from the legs:
provider_specific_fields; this PR leaves that path equally cleanType
🐛 Bug Fix
✅ Test
Caveats (if any)
Low
chat_template_kwargskeys server-sideFinal Attestation
The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR
1ba66b1 passes /live-pr-risk