From e7cece2dc31ef12b8e13b84298e884603b4e2d0f Mon Sep 17 00:00:00 2001 From: flex-myeonghyeon Date: Mon, 13 Apr 2026 14:37:03 +0900 Subject: [PATCH] fix: use toolConfig instead of tool_choice in cached content request body Per Google AI API docs, CachedContent schema uses "toolConfig" not "tool_choice". Also only set the field when tool_choice is not None, matching the pattern used in gemini transformation.py. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../context_caching/vertex_ai_context_caching.py | 6 ++++-- .../test_vertex_ai_context_caching.py | 14 ++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py index 9c38c09562f..d4caca54450 100644 --- a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py +++ b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py @@ -402,7 +402,8 @@ class ContextCachingEndpoints(VertexBase): ) cached_content_request_body["tools"] = tools - cached_content_request_body["tool_choice"] = tool_choice + if tool_choice is not None: + cached_content_request_body["toolConfig"] = tool_choice ## LOGGING logging_obj.pre_call( @@ -550,7 +551,8 @@ class ContextCachingEndpoints(VertexBase): ) cached_content_request_body["tools"] = tools - cached_content_request_body["tool_choice"] = tool_choice + if tool_choice is not None: + cached_content_request_body["toolConfig"] = tool_choice ## LOGGING logging_obj.pre_call( diff --git a/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py b/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py index 63106776b44..f07b81f99ec 100644 --- a/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py +++ b/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py @@ -280,8 +280,7 @@ class TestContextCachingEndpoints: call_args = self.mock_client.post.call_args assert "tools" in call_args.kwargs["json"] assert call_args.kwargs["json"]["tools"] == self.sample_tools - assert "tool_choice" in call_args.kwargs["json"] - assert call_args.kwargs["json"]["tool_choice"] is None + assert "toolConfig" not in call_args.kwargs["json"] @pytest.mark.parametrize( "custom_llm_provider", ["gemini", "vertex_ai", "vertex_ai_beta"] @@ -560,8 +559,7 @@ class TestContextCachingEndpoints: call_args = self.mock_async_client.post.call_args assert "tools" in call_args.kwargs["json"] assert call_args.kwargs["json"]["tools"] == self.sample_tools - assert "tool_choice" in call_args.kwargs["json"] - assert call_args.kwargs["json"]["tool_choice"] is None + assert "toolConfig" not in call_args.kwargs["json"] @pytest.mark.asyncio @pytest.mark.parametrize( @@ -983,9 +981,9 @@ class TestContextCachingEndpoints: model="gemini-1.5-pro", ) - # tool_choice should be in the request body + # tool_choice should be mapped to toolConfig in the request body call_args = self.mock_client.post.call_args - assert call_args.kwargs["json"]["tool_choice"] == tool_choice_value + assert call_args.kwargs["json"]["toolConfig"] == tool_choice_value @pytest.mark.asyncio @pytest.mark.parametrize( @@ -1065,9 +1063,9 @@ class TestContextCachingEndpoints: model="gemini-1.5-pro", ) - # tool_choice should be in the request body + # tool_choice should be mapped to toolConfig in the request body call_args = self.mock_async_client.post.call_args - assert call_args.kwargs["json"]["tool_choice"] == tool_choice_value + assert call_args.kwargs["json"]["toolConfig"] == tool_choice_value class TestCheckCachePagination: