File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2222from pydantic import BaseModel
2323from pydantic import ConfigDict
2424from pydantic import Field
25+ from pydantic import PrivateAttr
2526
2627from ..agents .context_cache_config import ContextCacheConfig
2728from ..tools .base_tool import BaseTool
@@ -100,6 +101,15 @@ class LlmRequest(BaseModel):
100101 the full history.
101102 """
102103
104+ _is_managed_agent : bool = PrivateAttr (default = False )
105+ """Internal flag: whether this request was built by a ManagedAgent.
106+
107+ This is an internal implementation detail (not part of the serialized request
108+ schema). It is set by ``ManagedAgent`` and read only through the
109+ ``_is_managed_agent`` helper in ``model_name_utils`` so built-in tools resolve
110+ server-side without a Gemini model.
111+ """
112+
103113 def append_instructions (
104114 self , instructions : Union [list [str ], types .Content ]
105115 ) -> list [types .Content ]:
Original file line number Diff line number Diff line change 1919from google .genai import types
2020from typing_extensions import override
2121
22+ from ..utils .model_name_utils import _is_managed_agent
2223from ..utils .model_name_utils import is_gemini_1_model
2324from ..utils .model_name_utils import is_gemini_model
2425from ..utils .model_name_utils import is_gemini_model_id_check_disabled
@@ -79,7 +80,11 @@ async def process_llm_request(
7980 llm_request .config .tools .append (
8081 types .Tool (google_search_retrieval = types .GoogleSearchRetrieval ())
8182 )
82- elif is_gemini_model (llm_request .model ) or model_check_disabled :
83+ elif (
84+ is_gemini_model (llm_request .model )
85+ or model_check_disabled
86+ or _is_managed_agent (llm_request )
87+ ):
8388 llm_request .config .tools .append (
8489 types .Tool (google_search = types .GoogleSearch ())
8590 )
Original file line number Diff line number Diff line change 1919from google .genai import types
2020from typing_extensions import override
2121
22+ from ..utils .model_name_utils import _is_managed_agent
2223from ..utils .model_name_utils import is_gemini_1_model
2324from ..utils .model_name_utils import is_gemini_eap_or_2_or_above
2425from ..utils .model_name_utils import is_gemini_model_id_check_disabled
@@ -52,7 +53,11 @@ async def process_llm_request(
5253 llm_request .config .tools = llm_request .config .tools or []
5354 if is_gemini_1_model (llm_request .model ):
5455 raise ValueError ('Url context tool cannot be used in Gemini 1.x.' )
55- elif is_gemini_eap_or_2_or_above (llm_request .model ) or model_check_disabled :
56+ elif (
57+ is_gemini_eap_or_2_or_above (llm_request .model )
58+ or model_check_disabled
59+ or _is_managed_agent (llm_request )
60+ ):
5661 llm_request .config .tools .append (
5762 types .Tool (url_context = types .UrlContext ())
5863 )
Original file line number Diff line number Diff line change 1818
1919import re
2020from typing import Optional
21+ from typing import TYPE_CHECKING
2122
2223from packaging .version import InvalidVersion
2324from packaging .version import Version
2425
2526from .env_utils import is_env_enabled
2627
28+ if TYPE_CHECKING :
29+ from ..models .llm_request import LlmRequest
30+
2731_DISABLE_GEMINI_MODEL_ID_CHECK_ENV_VAR = 'ADK_DISABLE_GEMINI_MODEL_ID_CHECK'
2832
2933
@@ -36,6 +40,11 @@ def is_gemini_model_id_check_disabled() -> bool:
3640 return is_env_enabled (_DISABLE_GEMINI_MODEL_ID_CHECK_ENV_VAR )
3741
3842
43+ def _is_managed_agent (llm_request : LlmRequest ) -> bool :
44+ """Whether the request was built by a ManagedAgent."""
45+ return llm_request ._is_managed_agent
46+
47+
3948def extract_model_name (model_string : str ) -> str :
4049 """Extract the actual model name from either simple or path-based format.
4150
Original file line number Diff line number Diff line change @@ -834,3 +834,16 @@ def test_append_instructions_with_only_text_parts():
834834
835835 # Should return empty list since no non-text parts
836836 assert user_contents == []
837+
838+
839+ def test_is_managed_agent_defaults_false ():
840+ """_is_managed_agent defaults to False for ordinary requests."""
841+ request = LlmRequest ()
842+ assert request ._is_managed_agent is False
843+
844+
845+ def test_is_managed_agent_can_be_set_true ():
846+ """_is_managed_agent is an internal flag set after construction."""
847+ request = LlmRequest ()
848+ request ._is_managed_agent = True
849+ assert request ._is_managed_agent is True
Original file line number Diff line number Diff line change @@ -516,3 +516,23 @@ async def test_process_llm_request_custom_model_behavior(
516516 assert llm_request .model == expected_model
517517 assert llm_request .config .tools is not None
518518 assert len (llm_request .config .tools ) == 1
519+
520+ @pytest .mark .asyncio
521+ async def test_process_llm_request_managed_agent_no_model (self ):
522+ """Managed-agent requests resolve google_search even with no model."""
523+ tool = GoogleSearchTool ()
524+ tool_context = await _create_tool_context ()
525+
526+ llm_request = LlmRequest (
527+ model = None ,
528+ config = types .GenerateContentConfig (),
529+ )
530+ llm_request ._is_managed_agent = True
531+
532+ await tool .process_llm_request (
533+ tool_context = tool_context , llm_request = llm_request
534+ )
535+
536+ assert llm_request .config .tools is not None
537+ assert len (llm_request .config .tools ) == 1
538+ assert llm_request .config .tools [0 ].google_search is not None
Original file line number Diff line number Diff line change @@ -322,3 +322,23 @@ async def test_process_llm_request_edge_cases(self):
322322 await tool .process_llm_request (
323323 tool_context = tool_context , llm_request = llm_request
324324 )
325+
326+ @pytest .mark .asyncio
327+ async def test_process_llm_request_managed_agent_no_model (self ):
328+ """Managed-agent requests resolve url_context even with no model."""
329+ tool = UrlContextTool ()
330+ tool_context = await _create_tool_context ()
331+
332+ llm_request = LlmRequest (
333+ model = None ,
334+ config = types .GenerateContentConfig (),
335+ )
336+ llm_request ._is_managed_agent = True
337+
338+ await tool .process_llm_request (
339+ tool_context = tool_context , llm_request = llm_request
340+ )
341+
342+ assert llm_request .config .tools is not None
343+ assert len (llm_request .config .tools ) == 1
344+ assert llm_request .config .tools [0 ].url_context is not None
Original file line number Diff line number Diff line change 1414
1515"""Tests for model name utility functions."""
1616
17+ from google .adk .models .llm_request import LlmRequest
18+ from google .adk .utils .model_name_utils import _is_managed_agent
1719from google .adk .utils .model_name_utils import extract_model_name
1820from google .adk .utils .model_name_utils import is_gemini_1_model
1921from google .adk .utils .model_name_utils import is_gemini_3_1_flash_live
@@ -429,3 +431,15 @@ def test_is_gemini_3_5_live_translate_edge_cases(self):
429431 """Test edge cases."""
430432 assert is_gemini_3_5_live_translate (None ) is False
431433 assert is_gemini_3_5_live_translate ('' ) is False
434+
435+
436+ class TestIsManagedAgent :
437+ """Tests for the _is_managed_agent predicate."""
438+
439+ def test_true_when_flag_set (self ):
440+ request = LlmRequest ()
441+ request ._is_managed_agent = True
442+ assert _is_managed_agent (request ) is True
443+
444+ def test_false_by_default (self ):
445+ assert _is_managed_agent (LlmRequest ()) is False
You can’t perform that action at this time.
0 commit comments