fix: strip extra_content from tool_calls for strict APIs (Fireworks, Mistral)#38543
Merged
Conversation
…Mistral) Fireworks/Mistral reject HTTP 400 'Extra inputs are not permitted, field: messages[N].tool_calls[M].extra_content' on any session whose history contains prior Gemini tool calls. Gemini 3 thinking models attach extra_content (thought_signature) to tool_calls; it survived to the wire because the sanitize paths only stripped call_id/response_item_id. Strip extra_content from the outgoing wire copy in both sanitize paths (ChatCompletionsTransport.convert_messages + _sanitize_tool_calls_for_strict_api), but gate it on the target model: keep extra_content for Gemini-family targets (the thought_signature MUST be replayed or Gemini 400s), strip it for everyone else — including non-Gemini models that inherit a stale Gemini signature earlier in a mixed-provider session. Native Gemini is unaffected (GeminiNativeClient bypasses these paths). Original stored history is never mutated (only the per-call copy). Fixes #17986.
Contributor
🔎 Lint report:
|
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.
Summary
Fireworks and Mistral no longer 400 on sessions that have prior Gemini tool calls in history.
Root cause: Gemini 3 thinking models attach
extra_content(thought_signature) to tool_calls for replay. Both sanitize paths only strippedcall_id/response_item_id, soextra_contentsurvived to the wire and strict providers rejected the request withExtra inputs are not permitted, field: 'messages[N].tool_calls[M].extra_content'.Salvages @nateGeorge's #18663 onto current main, with the unconditional strip made model-aware so it doesn't regress Gemini-on-aggregator.
Changes
agent/transports/chat_completions.py:convert_messages()stripsextra_contentfrom tool_calls — gated on_model_consumes_thought_signature(model). Model threaded in frombuild_kwargs.run_agent.py:_sanitize_tool_calls_for_strict_api()takes amodelarg; stripsextra_contentunless the target is Gemini-family (defaults to stripping when the model is unknown).agent/conversation_loop.py,agent/chat_completion_helpers.py: passmodel=agent.modelto the sanitizer.Why model-aware (not the original unconditional strip)
extra_contentis required when the destination is Gemini (thinking models 400 without the replayed signature). Stripping it for all non-Codex providers would trade a Fireworks 400 for a Gemini-on-OpenRouter 400. So: keep for Gemini-family targets, strip for everyone else. Native Gemini is unaffected — it usesGeminiNativeClientand bypasses these paths entirely.Validation
165 targeted tests pass (
tests/agent/transports/test_chat_completions.py,tests/run_agent/test_provider_parity.py). E2E verified through_build_api_kwargswith isolated HERMES_HOME for all three cases above.Salvages #18663 — original author @nateGeorge credited via commit authorship.
Fixes #17986.
Infographic