fix(agent_tool): wrap input_schema payload in ReAct prompt and propagate tool_choice to LiteLLM#5924
Open
ecanlar wants to merge 2 commits into
Open
Conversation
…ol_choice to LiteLLM When AgentTool uses input_schema, the inner agent receives a raw JSON blob that causes Claude models to skip the tool-calling loop (ReAct). Fix by wrapping the payload in a natural-language instruction. Also propagate tool_config.function_calling_config.mode to LiteLLM's tool_choice parameter so callers can enforce tool_choice='required'. Addresses google#773. Fixes: google#5926
ded18ca to
6168c49
Compare
Collaborator
|
Response from ADK Triaging Agent Hello @ecanlar, thank you for creating this PR! We appreciate your contribution to fixing the LiteLLM/Claude Currently, the following items are missing:
Providing this information helps ensure high code quality, prevents future regressions, and makes the review process smoother. Thank you! |
…tool_choice propagation - Update existing _get_completion_inputs call sites to handle new 5-tuple return value (adds tool_choice as 5th element) - Add 3 tests for AgentTool.run_async: verifies message is passed verbatim without input_schema, and is wrapped in a natural-language instruction with input_schema (PR google#5924 fix) - Add 8 tests for LiteLLM tool_choice propagation: covers _get_completion_inputs returning correct tool_choice for ANY/NONE/AUTO modes and None when no tool_config; covers generate_content_async correctly including/omitting tool_choice in completion_args
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
Fixes two issues that prevent Claude-family models from entering the ReAct tool-calling loop when used via LiteLLM inside a nested
AgentTool:AgentToolwithinput_schema— the serialized JSON payload sent as the first message causes Claude to interpret the request as already complete and respond directly without calling any tools.tool_choicenot propagated —llm_request.config.tool_config.function_calling_config.modewas not forwarded to LiteLLM'scompletion_args, so callers could not enforce tool use at the request level.Changes
src/google/adk/tools/agent_tool.pyWrap the serialized
input_schemaJSON in a natural-language instruction that explicitly asks the inner agent to use its available tools before producing a response. This keeps Claude in ReAct mode regardless of the message content format.src/google/adk/models/lite_llm.pyRead
llm_request.config.tool_config.function_calling_config.modeand map it to LiteLLM'stool_choiceparameter:ANY→"required"NONE→"none"AUTO→ provider default (unchanged, key omitted fromcompletion_args)_get_completion_inputsnow returns a 5-tuple(messages, tools, response_format, generation_params, tool_choice).Unit Tests Added
tests/unittests/tools/test_agent_tool.pytest_run_async_no_input_schema_passes_request_unchanged: withoutinput_schema, the content passed to the inner runner isargs['request']verbatim.test_run_async_with_input_schema_wraps_in_natural_language: withinput_schema, the text begins with"Process the following structured request", contains"Request:\n"followed by the JSON payload, and is not a bare JSON blob.test_run_async_with_input_schema_text_not_raw_json: asserts the text does not start with{.tests/unittests/models/test_litellm.pytest_get_completion_inputs_tool_choice_none_without_tool_config:tool_choiceisNonewith notool_config.test_get_completion_inputs_tool_choice_required_for_any_mode: returns"required"forANYmode.test_get_completion_inputs_tool_choice_none_for_none_mode: returns"none"forNONEmode.test_get_completion_inputs_tool_choice_none_for_auto_mode: returnsNoneforAUTOmode.test_generate_content_async_propagates_tool_choice_required:acompletionreceivestool_choice="required"forANY.test_generate_content_async_propagates_tool_choice_none_mode:acompletionreceivestool_choice="none"forNONE.test_generate_content_async_omits_tool_choice_for_auto_mode:tool_choicekey absent fromcompletion_argsforAUTO.test_generate_content_async_omits_tool_choice_without_tool_config:tool_choicekey absent when notool_config.Also updated all existing
_get_completion_inputscall sites (10 occurrences) to unpack the new 5-tuple.Pytest Results
The 1 pre-existing failure (
test_custom_schema[GOOGLE_AI]) is apydantic.ValidationErrorthat reproduces on the base branch before any of these changes and is unrelated to this fix.Related