Skip to content

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
google:mainfrom
ecanlar:fix/agent-tool-input-schema-tool-choice-litellm
Open

fix(agent_tool): wrap input_schema payload in ReAct prompt and propagate tool_choice to LiteLLM#5924
ecanlar wants to merge 2 commits into
google:mainfrom
ecanlar:fix/agent-tool-input-schema-tool-choice-litellm

Conversation

@ecanlar
Copy link
Copy Markdown

@ecanlar ecanlar commented Jun 1, 2026

Summary

Fixes two issues that prevent Claude-family models from entering the ReAct tool-calling loop when used via LiteLLM inside a nested AgentTool:

  1. AgentTool with input_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.
  2. tool_choice not propagatedllm_request.config.tool_config.function_calling_config.mode was not forwarded to LiteLLM's completion_args, so callers could not enforce tool use at the request level.

Changes

src/google/adk/tools/agent_tool.py

Wrap the serialized input_schema JSON 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.py

Read llm_request.config.tool_config.function_calling_config.mode and map it to LiteLLM's tool_choice parameter:

  • ANY"required"
  • NONE"none"
  • AUTO → provider default (unchanged, key omitted from completion_args)

_get_completion_inputs now returns a 5-tuple (messages, tools, response_format, generation_params, tool_choice).

Unit Tests Added

tests/unittests/tools/test_agent_tool.py

  • test_run_async_no_input_schema_passes_request_unchanged: without input_schema, the content passed to the inner runner is args['request'] verbatim.
  • test_run_async_with_input_schema_wraps_in_natural_language: with input_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.py

  • test_get_completion_inputs_tool_choice_none_without_tool_config: tool_choice is None with no tool_config.
  • test_get_completion_inputs_tool_choice_required_for_any_mode: returns "required" for ANY mode.
  • test_get_completion_inputs_tool_choice_none_for_none_mode: returns "none" for NONE mode.
  • test_get_completion_inputs_tool_choice_none_for_auto_mode: returns None for AUTO mode.
  • test_generate_content_async_propagates_tool_choice_required: acompletion receives tool_choice="required" for ANY.
  • test_generate_content_async_propagates_tool_choice_none_mode: acompletion receives tool_choice="none" for NONE.
  • test_generate_content_async_omits_tool_choice_for_auto_mode: tool_choice key absent from completion_args for AUTO.
  • test_generate_content_async_omits_tool_choice_without_tool_config: tool_choice key absent when no tool_config.

Also updated all existing _get_completion_inputs call sites (10 occurrences) to unpack the new 5-tuple.

Pytest Results

tests/unittests/tools/test_agent_tool.py + tests/unittests/models/test_litellm.py
1 failed (pre-existing: test_custom_schema[GOOGLE_AI] — unrelated to this PR),
302 passed, 1 skipped in 2.98s

New tests: 11 passed (3 agent_tool + 8 litellm)

The 1 pre-existing failure (test_custom_schema[GOOGLE_AI]) is a pydantic.ValidationError that reproduces on the base branch before any of these changes and is unrelated to this fix.

Related

…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
@ecanlar ecanlar force-pushed the fix/agent-tool-input-schema-tool-choice-litellm branch from ded18ca to 6168c49 Compare June 1, 2026 09:51
@adk-bot adk-bot added models [Component] Issues related to model support tools [Component] This issue is related to tools labels Jun 1, 2026
@adk-bot
Copy link
Copy Markdown
Collaborator

adk-bot commented Jun 1, 2026

Response from ADK Triaging Agent

Hello @ecanlar, thank you for creating this PR!

We appreciate your contribution to fixing the LiteLLM/Claude AgentTool issue. To help our reviewers process this pull request more efficiently, please ensure it complies with our contribution guidelines.

Currently, the following items are missing:

  1. Unit Tests: The PR modifies behavior in lite_llm.py and agent_tool.py, but does not add or update any unit tests (e.g., under tests/unittests/). Please add unit tests covering the new tool wrapping and tool_choice behavior.
  2. Pytest Results Summary: Please run the tests and include a summary of the passed pytest or tox results in the PR description.
  3. Logs/Screenshots: Please provide console logs or screenshots demonstrating that the inner agent successfully enters the ReAct loop and calls tools after applying the fix.

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

models [Component] Issues related to model support tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: AgentTool with input_schema + LiteLLM/Claude skips inner agent tool calls

2 participants