fix: cache canonical tools to avoid multiple calls when streaming

Merge https://github.com/google/adk-python/pull/3299
Fixes https://github.com/google/adk-python/issues/3237

Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3299 from hcadioli:fix/cache-tools de02bd3e4533c3741edf05788a5e8b2d3d38bae4
PiperOrigin-RevId: 829499299
This commit is contained in:
Henrique Cadioli
2025-11-07 10:51:32 -08:00
committed by Copybara-Service
parent 9761fc6bbb
commit 8f3c3bfda5
3 changed files with 81 additions and 1 deletions
@@ -32,6 +32,7 @@ from ..memory.base_memory_service import BaseMemoryService
from ..plugins.plugin_manager import PluginManager
from ..sessions.base_session_service import BaseSessionService
from ..sessions.session import Session
from ..tools.base_tool import BaseTool
from .active_streaming_tool import ActiveStreamingTool
from .base_agent import BaseAgent
from .base_agent import BaseAgentState
@@ -202,6 +203,9 @@ class InvocationContext(BaseModel):
plugin_manager: PluginManager = Field(default_factory=PluginManager)
"""The manager for keeping track of plugins in this invocation."""
canonical_tools_cache: Optional[list[BaseTool]] = None
"""The cache of canonical tools for this invocation."""
_invocation_cost_manager: _InvocationCostManager = PrivateAttr(
default_factory=_InvocationCostManager
)
@@ -855,7 +855,10 @@ class BaseLlmFlow(ABC):
response: Optional[LlmResponse] = None,
) -> Optional[LlmResponse]:
readonly_context = ReadonlyContext(invocation_context)
tools = await agent.canonical_tools(readonly_context)
if (tools := invocation_context.canonical_tools_cache) is None:
tools = await agent.canonical_tools(readonly_context)
invocation_context.canonical_tools_cache = tools
if not any(tool.name == 'google_search_agent' for tool in tools):
return response
ground_metadata = invocation_context.session.state.get(