fix(workflow): Keep regular-tool FRs on mixed task turns - #6586
Open
a2105z wants to merge 2 commits into
Open
Conversation
When a chat coordinator emits a regular tool call and a task-delegation call in the same model turn, the wrapper broke out of run_async before draining the regular-tool function response. That left unbalanced FC/FR history and caused Gemini to reject later turns. Fixes google#6581
Author
|
Hi @DeanChensj — thanks for taking a look at this (and for all the prior work on the chat/task wrapper; I leaned on that area while debugging). I put up a fix for #6581: on mixed turns (regular tool FC + task FC in the same model response), the wrapper was breaking out of Happy to adjust the approach if you'd prefer a different drain/boundary condition — just let me know what you'd like changed. Appreciate any feedback when you have a moment. |
This was referenced Aug 4, 2026
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.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
Problem:
When a chat-mode coordinator emits both a regular tool function call and a task-delegation function call in the same model turn,
_llm_agent_wrapper.pybroke out ofrun_asyncimmediately after handling the task FC. That closed the generator before the pending regular-tool function-response event was read.Effects:
400 INVALID_ARGUMENT: Please ensure that the number of function response parts is equal to the number of function call parts.Solution:
Before breaking on task FCs, if the turn also contains eager (non-deferred / non-long-running) tool calls, drain pending non-model events from the current LLM step so regular-tool FRs are yielded and persisted. Then dispatch task FCs and synthesize task FRs as before, and re-enter
run_async.Testing Plan
Unit Tests:
New / updated tests:
tests/unittests/workflow/test_llm_agent_wrapper_mixed_turn.py_event_has_eager_tool_callstrue for regular+task, false for task-only_drain_pending_tool_response_eventsyields FR then stopstests/unittests/workflow/test_task_api_e2e.pytest_chat_root_mixed_regular_tool_and_task_keeps_regular_frtest_chat_root_mixed_turn_with_two_regular_tools_and_taskpytest results (local):
Manual / repro verification:
mainwith the issue's stub-LLM mixed-turn script:set_todo_listFR was missing and the tool did not execute (FAIL).FR:set_todo_list, and the tool executes.finish_taskconfirms:Pre-commit:
Checklist
Additional context
Files changed:
src/google/adk/workflow/_llm_agent_wrapper.py— drain eager-tool FRs before breaking on task delegationtests/unittests/workflow/test_task_api_e2e.py— mixed-turn e2e coveragetests/unittests/workflow/test_llm_agent_wrapper_mixed_turn.py— helper unit testsExact commands run
pytest tests/unittests/workflow/test_llm_agent_wrapper_mixed_turn.py \ tests/unittests/workflow/test_task_api_e2e.py -v # 14 passed, 1 xfailed pytest tests/unittests/workflow/ \ tests/unittests/agents/test_llm_agent_interruptions.py \ tests/unittests/agents/test_llm_agent_single_turn_subagents.py -q # 694 passed, 11 skipped, 12 xfailed pre-commit run --files \ src/google/adk/workflow/_llm_agent_wrapper.py \ tests/unittests/workflow/test_task_api_e2e.py \ tests/unittests/workflow/test_llm_agent_wrapper_mixed_turn.py # all hooks passed