refactor: Replace check of instance for LlmAgent with hasAttribute check

Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 868370272
This commit is contained in:
Xiang (Sean) Zhou
2026-02-10 16:26:49 -08:00
committed by Copybara-Service
parent 0abf4cd2c7
commit 7110336788
8 changed files with 30 additions and 45 deletions
+1 -7
View File
@@ -15,7 +15,6 @@
from __future__ import annotations
from typing import AsyncGenerator
from typing import TYPE_CHECKING
from typing_extensions import override
@@ -30,9 +29,6 @@ from .auth_handler import AuthHandler
from .auth_tool import AuthConfig
from .auth_tool import AuthToolArguments
if TYPE_CHECKING:
from ..agents.llm_agent import LlmAgent
# Prefix used by toolset auth credential IDs.
# Auth requests with this prefix are for toolset authentication (before tool
# listing) and don't require resuming a function call.
@@ -46,10 +42,8 @@ class _AuthLlmRequestProcessor(BaseLlmRequestProcessor):
async def run_async(
self, invocation_context: InvocationContext, llm_request: LlmRequest
) -> AsyncGenerator[Event, None]:
from ..agents.llm_agent import LlmAgent
agent = invocation_context.agent
if not isinstance(agent, LlmAgent):
if not hasattr(agent, 'canonical_tools'):
return
events = invocation_context.session.events
if not events:
@@ -120,9 +120,7 @@ class _CodeExecutionRequestProcessor(BaseLlmRequestProcessor):
async def run_async(
self, invocation_context: InvocationContext, llm_request: LlmRequest
) -> AsyncGenerator[Event, None]:
from ...agents.llm_agent import LlmAgent
if not isinstance(invocation_context.agent, LlmAgent):
if not hasattr(invocation_context.agent, 'code_executor'):
return
if not invocation_context.agent.code_executor:
return
@@ -175,9 +173,7 @@ async def _run_pre_processor(
llm_request: LlmRequest,
) -> AsyncGenerator[Event, None]:
"""Pre-process the user message by adding the user message to the Colab notebook."""
from ...agents.llm_agent import LlmAgent
if not isinstance(invocation_context.agent, LlmAgent):
if not hasattr(invocation_context.agent, 'code_executor'):
return
agent = invocation_context.agent
@@ -109,11 +109,10 @@ response_processor = _NlPlanningResponse()
def _get_planner(
invocation_context: InvocationContext,
) -> Optional[BasePlanner]:
from ...agents.llm_agent import Agent
from ...planners.base_planner import BasePlanner
agent = invocation_context.agent
if not isinstance(agent, Agent):
if not hasattr(agent, 'planner'):
return None
if not agent.planner:
return None
@@ -40,9 +40,7 @@ class _AgentTransferLlmRequestProcessor(BaseLlmRequestProcessor):
async def run_async(
self, invocation_context: InvocationContext, llm_request: LlmRequest
) -> AsyncGenerator[Event, None]:
from ...agents.llm_agent import LlmAgent
if not isinstance(invocation_context.agent, LlmAgent):
if not hasattr(invocation_context.agent, 'disallow_transfer_to_parent'):
return
transfer_targets = _get_transfer_targets(invocation_context.agent)
@@ -141,12 +139,12 @@ If neither you nor the other agents are best for the question, transfer to your
def _get_transfer_targets(agent: LlmAgent) -> list[BaseAgent]:
from ...agents.llm_agent import LlmAgent
result = []
result.extend(agent.sub_agents)
if not agent.parent_agent or not isinstance(agent.parent_agent, LlmAgent):
if not agent.parent_agent or not hasattr(
agent.parent_agent, 'disallow_transfer_to_parent'
):
return result
if not agent.disallow_transfer_to_parent:
+13 -15
View File
@@ -520,12 +520,11 @@ class BaseLlmFlow(ABC):
async def _preprocess_async(
self, invocation_context: InvocationContext, llm_request: LlmRequest
) -> AsyncGenerator[Event, None]:
from ...agents.llm_agent import LlmAgent
agent = invocation_context.agent
if not isinstance(agent, LlmAgent):
if not hasattr(agent, 'tools') or not hasattr(agent, 'canonical_model'):
raise TypeError(
f'Expected agent to be an LlmAgent, but got {type(agent)}'
'Expected agent to have tools and canonical_model attributes,'
f' but got {type(agent)}'
)
# Runs processors.
@@ -973,8 +972,6 @@ class BaseLlmFlow(ABC):
llm_request: LlmRequest,
model_response_event: Event,
) -> Optional[LlmResponse]:
from ...agents.llm_agent import LlmAgent
agent = invocation_context.agent
callback_context = CallbackContext(
@@ -1010,8 +1007,6 @@ class BaseLlmFlow(ABC):
llm_response: LlmResponse,
model_response_event: Event,
) -> Optional[LlmResponse]:
from ...agents.llm_agent import LlmAgent
agent = invocation_context.agent
# Add grounding metadata to the response if needed.
@@ -1130,12 +1125,11 @@ class BaseLlmFlow(ABC):
A generator of LlmResponse.
"""
from ...agents.llm_agent import LlmAgent
agent = invocation_context.agent
if not isinstance(agent, LlmAgent):
if not hasattr(agent, 'canonical_on_model_error_callbacks'):
raise TypeError(
f'Expected agent to be an LlmAgent, but got {type(agent)}'
'Expected agent to have canonical_on_model_error_callbacks'
f' attribute, but got {type(agent)}'
)
async def _run_on_model_error_callbacks(
@@ -1190,6 +1184,10 @@ class BaseLlmFlow(ABC):
raise model_error
def __get_llm(self, invocation_context: InvocationContext) -> BaseLlm:
from ...agents.llm_agent import LlmAgent
return cast(LlmAgent, invocation_context.agent).canonical_model
agent = invocation_context.agent
if not hasattr(agent, 'canonical_model'):
raise TypeError(
'Expected agent to have canonical_model attribute,'
f' but got {type(agent)}'
)
return agent.canonical_model
@@ -73,7 +73,6 @@ async def _build_instructions(
llm_request: The LlmRequest to populate with instructions.
"""
from ...agents.base_agent import BaseAgent
from ...agents.llm_agent import LlmAgent
agent = invocation_context.agent
@@ -81,7 +80,10 @@ async def _build_instructions(
# Handle global instructions (DEPRECATED - use GlobalInstructionPlugin instead)
# TODO: Remove this code block when global_instruction field is removed
if isinstance(root_agent, LlmAgent) and root_agent.global_instruction:
if (
hasattr(root_agent, 'global_instruction')
and root_agent.global_instruction
):
raw_si, bypass_state_injection = (
await root_agent.canonical_global_instruction(
ReadonlyContext(invocation_context)
@@ -46,12 +46,11 @@ class InteractionsRequestProcessor(BaseLlmRequestProcessor):
Yields:
Event: No events are yielded by this processor
"""
from ...agents.llm_agent import LlmAgent
from ...models.google_llm import Gemini
agent = invocation_context.agent
# Only process if using Gemini with interactions API
if not isinstance(agent, LlmAgent):
if not hasattr(agent, 'canonical_model'):
return
model = agent.canonical_model
if not isinstance(model, Gemini):
+4 -5
View File
@@ -39,7 +39,6 @@ from .agents.context_cache_config import ContextCacheConfig
from .agents.invocation_context import InvocationContext
from .agents.invocation_context import new_invocation_context_id
from .agents.live_request_queue import LiveRequestQueue
from .agents.llm_agent import LlmAgent
from .agents.run_config import RunConfig
from .apps.app import App
from .apps.app import ResumabilityConfig
@@ -1143,8 +1142,8 @@ class Runner:
"""
agent = agent_to_run
while agent:
if not isinstance(agent, LlmAgent):
# Only LLM-based Agent can provide agent transfer capability.
if not hasattr(agent, 'disallow_transfer_to_parent'):
# Only agents with transfer capability can transfer.
return False
if agent.disallow_transfer_to_parent:
return False
@@ -1393,7 +1392,7 @@ class Runner:
run_config = run_config or RunConfig()
invocation_id = invocation_id or new_invocation_context_id()
if run_config.support_cfc and isinstance(self.agent, LlmAgent):
if run_config.support_cfc and hasattr(self.agent, 'canonical_model'):
model_name = self.agent.canonical_model.model
if not model_name.startswith('gemini-2'):
raise ValueError(
@@ -1487,7 +1486,7 @@ class Runner:
def _collect_toolset(self, agent: BaseAgent) -> set[BaseToolset]:
toolsets = set()
if isinstance(agent, LlmAgent):
if hasattr(agent, 'tools'):
for tool_union in agent.tools:
if isinstance(tool_union, BaseToolset):
toolsets.add(tool_union)