Repository navigation
fix: harden SetModelResponseTool fallback to prevent infinite loops - #5091
Closed
vietnamesekid wants to merge 2 commits into
Closed
vietnamesekid wants to merge 2 commits into
vietnamesekid wants to merge 2 commits into
Conversation
5 tasks done
vietnamesekid
force-pushed
the
fix/harden-set-model-response-fallback
branch
from
April 2, 2026 02:37
a27127b to
67307bf
Compare
Flash models (gemini-2.5-flash, gemini-3-flash) can ignore set_model_response and loop indefinitely when output_schema is used with tools. This adds a layered defense: 1. Type-aware instruction: primitive schemas (str, int) get a stronger prompt since their trivial tool signature is easily ignored by flash models. 2. Deterministic tool_choice guard: on round N-1 (_MAX_TOOL_ROUNDS-1), restrict the model to only call set_model_response via tool_config. 3. Hard cutoff: on round N, terminate the invocation entirely to prevent runaway API costs. 4. Early return after set_model_response: skip unnecessary transfer_to_agent processing in base_llm_flow.py after structured output is successfully produced. Based on analysis by @surfai, @nino-robotfutures-co, and @surajksharma07 on google#5054.
vietnamesekid
force-pushed
the
fix/harden-set-model-response-fallback
branch
from
April 2, 2026 02:39
3e45d49 to
4dde4c1
Compare
Collaborator
|
Hi @vietnamesekid , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Your PR has been received by the team and is currently under review. We will provide feedback as soon as we have an update to share. |
Collaborator
|
Hi @wukath , can you please review this. |
Contributor
Author
|
Any updates on this @rohityan ? |
copybara-service Bot
pushed a commit
that referenced
this pull request
Oct 5, 2026
Merge #5091 Improves the fallback behavior of SetModelResponseTool to avoid infinite loops when models ignore set_model_response and keep calling other tools. Caps consecutive tool rounds per agent turn at 25 by default (configurable via ADK_MAX_TOOL_ROUNDS; <= 0 disables the cap) and emits an error event with error_code="MAX_TOOL_ROUNDS_EXCEEDED" when the cap is reached. PiperOrigin-RevId: 993785655
Collaborator
|
Thank you @vietnamesekid for your contribution! 🎉 Your changes have been successfully imported and merged via Copybara in commit d185ca5. Closing this PR as the changes are now in the main branch. |
copybara-service Bot
pushed a commit
that referenced
this pull request
Oct 6, 2026
The cap forced any such agent to give its final answer after 24 rounds of tool calls in one turn, with no warning, which broke agents that legitimately need longer tool chains. This reverts #5091 in full and restores the previous behavior. Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 994543093
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
This is a follow-up to #5057. It improves the fallback behavior of
SetModelResponseToolto avoid infinite loops, especially when flash models (like gemini-2.5-flash and gemini-3-flash) ignoreset_model_responseand keep calling other tools.The changes come from the investigation and discussion in #5054.
Changes
_output_schema_processor.py): primitive schemas likestrandintare easy for models to ignore, so we now give clearer guidance in these cases.set_model_responseusingtool_config, so we can guarantee structured output._MAX_TOOL_ROUNDS=25), we stop execution completely to avoid runaway loops and unnecessary API usage.base_llm_flow.py): onceset_model_responsesucceeds, we skip extra steps liketransfer_to_agent.Test plan
strschemas across GOOGLE_AI and Vertex AIRelated
set_model_responseerror responses are treated as final output, bypassing ReflectAndRetryToolPlugin retry #4525