From 7ad8dd5ed9d252518e1e2b48f3284659b0e5aae3 Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Thu, 12 Mar 2026 13:22:42 -0700 Subject: [PATCH 1/7] Fix #2433: Lazy load modules to improve import time --- src/google/adk/__init__.py | 22 ++++++++-- src/google/adk/agents/__init__.py | 67 +++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/google/adk/__init__.py b/src/google/adk/__init__.py index d48806bacd..f24ada98b1 100644 --- a/src/google/adk/__init__.py +++ b/src/google/adk/__init__.py @@ -13,11 +13,25 @@ # limitations under the License. from __future__ import annotations +from typing import TYPE_CHECKING -from . import version -from .agents.context import Context -from .agents.llm_agent import Agent -from .runners import Runner +if TYPE_CHECKING: + from .agents.context import Context + from .agents.llm_agent import Agent + from .runners import Runner +else: + def __getattr__(name: str): + if name == "Agent": + from .agents.llm_agent import Agent + return Agent + if name == "Context": + from .agents.context import Context + return Context + if name == "Runner": + from .runners import Runner + return Runner + raise AttributeError(f"module {__name__} has no attribute {name}") +from . import version __version__ = version.__version__ __all__ = ["Agent", "Context", "Runner"] diff --git a/src/google/adk/agents/__init__.py b/src/google/adk/agents/__init__.py index fbd1808f3f..9cd47ca42f 100644 --- a/src/google/adk/agents/__init__.py +++ b/src/google/adk/agents/__init__.py @@ -12,18 +12,61 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .base_agent import BaseAgent -from .context import Context -from .invocation_context import InvocationContext -from .live_request_queue import LiveRequest -from .live_request_queue import LiveRequestQueue -from .llm_agent import Agent -from .llm_agent import LlmAgent -from .loop_agent import LoopAgent -from .mcp_instruction_provider import McpInstructionProvider -from .parallel_agent import ParallelAgent -from .run_config import RunConfig -from .sequential_agent import SequentialAgent +from __future__ import annotations +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .base_agent import BaseAgent + from .context import Context + from .invocation_context import InvocationContext + from .live_request_queue import LiveRequest + from .live_request_queue import LiveRequestQueue + from .llm_agent import Agent + from .llm_agent import LlmAgent + from .loop_agent import LoopAgent + from .mcp_instruction_provider import McpInstructionProvider + from .parallel_agent import ParallelAgent + from .run_config import RunConfig + from .sequential_agent import SequentialAgent + +def __getattr__(name: str): + if name == 'BaseAgent': + from .base_agent import BaseAgent + return BaseAgent + if name == 'Context': + from .context import Context + return Context + if name == 'InvocationContext': + from .invocation_context import InvocationContext + return InvocationContext + if name == 'LiveRequest': + from .live_request_queue import LiveRequest + return LiveRequest + if name == 'LiveRequestQueue': + from .live_request_queue import LiveRequestQueue + return LiveRequestQueue + if name == 'Agent': + from .llm_agent import Agent + return Agent + if name == 'LlmAgent': + from .llm_agent import LlmAgent + return LlmAgent + if name == 'LoopAgent': + from .loop_agent import LoopAgent + return LoopAgent + if name == 'McpInstructionProvider': + from .mcp_instruction_provider import McpInstructionProvider + return McpInstructionProvider + if name == 'ParallelAgent': + from .parallel_agent import ParallelAgent + return ParallelAgent + if name == 'RunConfig': + from .run_config import RunConfig + return RunConfig + if name == 'SequentialAgent': + from .sequential_agent import SequentialAgent + return SequentialAgent + raise AttributeError(f"module {__name__} has no attribute {name}") __all__ = [ 'Agent', From f37ea6ffa4b534a585ed104313937efdc9a1352a Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Thu, 12 Mar 2026 14:20:23 -0700 Subject: [PATCH 2/7] Refactor lazy loading to use dictionary-based mapping and fix __getattr__ scope for better maintainability. --- src/google/adk/__init__.py | 20 ++++++----- src/google/adk/agents/__init__.py | 60 ++++++++++++------------------- 2 files changed, 33 insertions(+), 47 deletions(-) diff --git a/src/google/adk/__init__.py b/src/google/adk/__init__.py index f24ada98b1..ef5ee5a03a 100644 --- a/src/google/adk/__init__.py +++ b/src/google/adk/__init__.py @@ -20,16 +20,18 @@ from .agents.llm_agent import Agent from .runners import Runner else: + import importlib + + _LAZY_IMPORTS = { + "Agent": ".agents.llm_agent", + "Context": ".agents.context", + "Runner": ".runners", + } + def __getattr__(name: str): - if name == "Agent": - from .agents.llm_agent import Agent - return Agent - if name == "Context": - from .agents.context import Context - return Context - if name == "Runner": - from .runners import Runner - return Runner + if name in _LAZY_IMPORTS: + module = importlib.import_module(_LAZY_IMPORTS[name], __name__) + return getattr(module, name) raise AttributeError(f"module {__name__} has no attribute {name}") from . import version diff --git a/src/google/adk/agents/__init__.py b/src/google/adk/agents/__init__.py index 9cd47ca42f..e812add152 100644 --- a/src/google/adk/agents/__init__.py +++ b/src/google/adk/agents/__init__.py @@ -28,45 +28,29 @@ from .parallel_agent import ParallelAgent from .run_config import RunConfig from .sequential_agent import SequentialAgent +else: + import importlib -def __getattr__(name: str): - if name == 'BaseAgent': - from .base_agent import BaseAgent - return BaseAgent - if name == 'Context': - from .context import Context - return Context - if name == 'InvocationContext': - from .invocation_context import InvocationContext - return InvocationContext - if name == 'LiveRequest': - from .live_request_queue import LiveRequest - return LiveRequest - if name == 'LiveRequestQueue': - from .live_request_queue import LiveRequestQueue - return LiveRequestQueue - if name == 'Agent': - from .llm_agent import Agent - return Agent - if name == 'LlmAgent': - from .llm_agent import LlmAgent - return LlmAgent - if name == 'LoopAgent': - from .loop_agent import LoopAgent - return LoopAgent - if name == 'McpInstructionProvider': - from .mcp_instruction_provider import McpInstructionProvider - return McpInstructionProvider - if name == 'ParallelAgent': - from .parallel_agent import ParallelAgent - return ParallelAgent - if name == 'RunConfig': - from .run_config import RunConfig - return RunConfig - if name == 'SequentialAgent': - from .sequential_agent import SequentialAgent - return SequentialAgent - raise AttributeError(f"module {__name__} has no attribute {name}") + _LAZY_IMPORTS = { + "BaseAgent": ".base_agent", + "Context": ".context", + "InvocationContext": ".invocation_context", + "LiveRequest": ".live_request_queue", + "LiveRequestQueue": ".live_request_queue", + "Agent": ".llm_agent", + "LlmAgent": ".llm_agent", + "LoopAgent": ".loop_agent", + "McpInstructionProvider": ".mcp_instruction_provider", + "ParallelAgent": ".parallel_agent", + "RunConfig": ".run_config", + "SequentialAgent": ".sequential_agent", + } + + def __getattr__(name: str): + if name in _LAZY_IMPORTS: + module = importlib.import_module(_LAZY_IMPORTS[name], __name__) + return getattr(module, name) + raise AttributeError(f"module {__name__} has no attribute {name}") __all__ = [ 'Agent', From 0b4c9b47159459eb182477ab9048a69ceac3831c Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Wed, 25 Mar 2026 11:10:20 -0700 Subject: [PATCH 3/7] Fix sorting in _LAZY_IMPORTS and __all__ in src/google/adk/agents/__init__.py --- src/google/adk/agents/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/google/adk/agents/__init__.py b/src/google/adk/agents/__init__.py index e812add152..98eae32391 100644 --- a/src/google/adk/agents/__init__.py +++ b/src/google/adk/agents/__init__.py @@ -32,12 +32,12 @@ import importlib _LAZY_IMPORTS = { + "Agent": ".llm_agent", "BaseAgent": ".base_agent", "Context": ".context", "InvocationContext": ".invocation_context", "LiveRequest": ".live_request_queue", "LiveRequestQueue": ".live_request_queue", - "Agent": ".llm_agent", "LlmAgent": ".llm_agent", "LoopAgent": ".loop_agent", "McpInstructionProvider": ".mcp_instruction_provider", @@ -56,13 +56,13 @@ def __getattr__(name: str): 'Agent', 'BaseAgent', 'Context', + 'InvocationContext', + 'LiveRequest', + 'LiveRequestQueue', 'LlmAgent', 'LoopAgent', 'McpInstructionProvider', 'ParallelAgent', - 'SequentialAgent', - 'InvocationContext', - 'LiveRequest', - 'LiveRequestQueue', 'RunConfig', + 'SequentialAgent', ] From 9d3bbcb101dd5cd32b1fd447b050a4670dd203d0 Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Wed, 25 Mar 2026 12:17:08 -0700 Subject: [PATCH 4/7] Fix formatting issues: Standardize quotes to double quotes in __all__ list. --- src/google/adk/agents/__init__.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/google/adk/agents/__init__.py b/src/google/adk/agents/__init__.py index 98eae32391..f8a27fa490 100644 --- a/src/google/adk/agents/__init__.py +++ b/src/google/adk/agents/__init__.py @@ -53,16 +53,16 @@ def __getattr__(name: str): raise AttributeError(f"module {__name__} has no attribute {name}") __all__ = [ - 'Agent', - 'BaseAgent', - 'Context', - 'InvocationContext', - 'LiveRequest', - 'LiveRequestQueue', - 'LlmAgent', - 'LoopAgent', - 'McpInstructionProvider', - 'ParallelAgent', - 'RunConfig', - 'SequentialAgent', + "Agent", + "BaseAgent", + "Context", + "InvocationContext", + "LiveRequest", + "LiveRequestQueue", + "LlmAgent", + "LoopAgent", + "McpInstructionProvider", + "ParallelAgent", + "RunConfig", + "SequentialAgent", ] From 9f8304827b1f80bee016140e1e79e846c4b51702 Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Thu, 16 Apr 2026 09:08:26 -0700 Subject: [PATCH 5/7] Add test case to verify lazy loading of Agent module --- tests/unittests/test_lazy_loading.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/unittests/test_lazy_loading.py diff --git a/tests/unittests/test_lazy_loading.py b/tests/unittests/test_lazy_loading.py new file mode 100644 index 0000000000..2134de890b --- /dev/null +++ b/tests/unittests/test_lazy_loading.py @@ -0,0 +1,28 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import unittest +import google.adk + +class TestLazyLoading(unittest.TestCase): + def test_agent_not_loaded(self): + # Before accessing Agent, it shouldn't be in sys.modules + self.assertNotIn("google.adk.agents.llm_agent", sys.modules) + + # Accessing Agent + _ = google.adk.Agent + + # Now it should be loaded + self.assertIn("google.adk.agents.llm_agent", sys.modules) From 17f1d0a2a4d620c1fff26f5d1b26ecedfe0a3917 Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Fri, 17 Apr 2026 03:40:05 -0700 Subject: [PATCH 6/7] Fix indentation to 2 spaces to comply with pyproject.toml configuration --- src/google/adk/__init__.py | 28 +++++----- src/google/adk/agents/__init__.py | 88 +++++++++++++++---------------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/google/adk/__init__.py b/src/google/adk/__init__.py index ef5ee5a03a..7c741589c9 100644 --- a/src/google/adk/__init__.py +++ b/src/google/adk/__init__.py @@ -16,23 +16,23 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from .agents.context import Context - from .agents.llm_agent import Agent - from .runners import Runner + from .agents.context import Context + from .agents.llm_agent import Agent + from .runners import Runner else: - import importlib + import importlib - _LAZY_IMPORTS = { - "Agent": ".agents.llm_agent", - "Context": ".agents.context", - "Runner": ".runners", - } + _LAZY_IMPORTS = { + "Agent": ".agents.llm_agent", + "Context": ".agents.context", + "Runner": ".runners", + } - def __getattr__(name: str): - if name in _LAZY_IMPORTS: - module = importlib.import_module(_LAZY_IMPORTS[name], __name__) - return getattr(module, name) - raise AttributeError(f"module {__name__} has no attribute {name}") + def __getattr__(name: str): + if name in _LAZY_IMPORTS: + module = importlib.import_module(_LAZY_IMPORTS[name], __name__) + return getattr(module, name) + raise AttributeError(f"module {__name__} has no attribute {name}") from . import version __version__ = version.__version__ diff --git a/src/google/adk/agents/__init__.py b/src/google/adk/agents/__init__.py index f8a27fa490..7d361731c8 100644 --- a/src/google/adk/agents/__init__.py +++ b/src/google/adk/agents/__init__.py @@ -16,53 +16,53 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from .base_agent import BaseAgent - from .context import Context - from .invocation_context import InvocationContext - from .live_request_queue import LiveRequest - from .live_request_queue import LiveRequestQueue - from .llm_agent import Agent - from .llm_agent import LlmAgent - from .loop_agent import LoopAgent - from .mcp_instruction_provider import McpInstructionProvider - from .parallel_agent import ParallelAgent - from .run_config import RunConfig - from .sequential_agent import SequentialAgent + from .base_agent import BaseAgent + from .context import Context + from .invocation_context import InvocationContext + from .live_request_queue import LiveRequest + from .live_request_queue import LiveRequestQueue + from .llm_agent import Agent + from .llm_agent import LlmAgent + from .loop_agent import LoopAgent + from .mcp_instruction_provider import McpInstructionProvider + from .parallel_agent import ParallelAgent + from .run_config import RunConfig + from .sequential_agent import SequentialAgent else: - import importlib + import importlib - _LAZY_IMPORTS = { - "Agent": ".llm_agent", - "BaseAgent": ".base_agent", - "Context": ".context", - "InvocationContext": ".invocation_context", - "LiveRequest": ".live_request_queue", - "LiveRequestQueue": ".live_request_queue", - "LlmAgent": ".llm_agent", - "LoopAgent": ".loop_agent", - "McpInstructionProvider": ".mcp_instruction_provider", - "ParallelAgent": ".parallel_agent", - "RunConfig": ".run_config", - "SequentialAgent": ".sequential_agent", - } + _LAZY_IMPORTS = { + "Agent": ".llm_agent", + "BaseAgent": ".base_agent", + "Context": ".context", + "InvocationContext": ".invocation_context", + "LiveRequest": ".live_request_queue", + "LiveRequestQueue": ".live_request_queue", + "LlmAgent": ".llm_agent", + "LoopAgent": ".loop_agent", + "McpInstructionProvider": ".mcp_instruction_provider", + "ParallelAgent": ".parallel_agent", + "RunConfig": ".run_config", + "SequentialAgent": ".sequential_agent", + } - def __getattr__(name: str): - if name in _LAZY_IMPORTS: - module = importlib.import_module(_LAZY_IMPORTS[name], __name__) - return getattr(module, name) - raise AttributeError(f"module {__name__} has no attribute {name}") + def __getattr__(name: str): + if name in _LAZY_IMPORTS: + module = importlib.import_module(_LAZY_IMPORTS[name], __name__) + return getattr(module, name) + raise AttributeError(f"module {__name__} has no attribute {name}") __all__ = [ - "Agent", - "BaseAgent", - "Context", - "InvocationContext", - "LiveRequest", - "LiveRequestQueue", - "LlmAgent", - "LoopAgent", - "McpInstructionProvider", - "ParallelAgent", - "RunConfig", - "SequentialAgent", + "Agent", + "BaseAgent", + "Context", + "InvocationContext", + "LiveRequest", + "LiveRequestQueue", + "LlmAgent", + "LoopAgent", + "McpInstructionProvider", + "ParallelAgent", + "RunConfig", + "SequentialAgent", ] From 824597b429d79a5eda94ef369306fc3d68be2ff9 Mon Sep 17 00:00:00 2001 From: 9chait9 <9chait9@gmail.com> Date: Fri, 17 Apr 2026 03:56:16 -0700 Subject: [PATCH 7/7] Fix indentation to 2 spaces to comply with pyproject.toml configuration