10000 refactor: refine agent_loader to load the most common folder structur… · CentML/adk-python@623957c · GitHub
[go: up one dir, main page]

Skip to content

Commit 623957c

Browse files
seanzhougooglecopybara-github
authored andcommitted
refactor: refine agent_loader to load the most common folder structure first and don't including unnecessary case
PiperOrigin-RevId: 764545194
1 parent 6157db7 commit 623957c

File tree

1 file changed

+27
-30
lines changed

1 file changed

+27
-30
lines changed

src/google/adk/cli/utils/agent_loader.py

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import importlib
1818
import logging
1919
import sys
20+
from typing import Optional
2021

2122
from . import envs
2223
from ...agents.base_agent import BaseAgent
@@ -27,40 +28,40 @@
2728
class AgentLoader:
2829
"""Centralized agent loading with proper isolation, caching, and .env loading.
2930
Support loading agents from below folder/file structures:
30-
a) agents_dir/agent_name.py (with root_agent or agent.root_agent in it)
31-
b) agents_dir/agent_name_folder/__init__.py (with root_agent or agent.root_agent in the package)
32-
c) agents_dir/agent_name_folder/agent.py (where agent.py has root_agent)
31+
a) {agent_name}.agent as a module name:
32+
agents_dir/{agent_name}/agent.py (with root_agent defined in the module)
33+
b) {agent_name} as a module name
34+
agents_dir/{agent_name}.py (with root_agent defined in the module)
35+
c) {agent_name} as a package name
36+
agents_dir/{agent_name}/__init__.py (with root_agent in the package)
37+
3338
"""
3439

3540
def __init__(self, agents_dir: str):
3641
self.agents_dir = agents_dir.rstrip("/")
3742
self._original_sys_path = None
3843
self._agent_cache: dict[str, BaseAgent] = {}
3944

40-
def _load_from_module_or_package(self, agent_name: str) -> BaseAgent:
41-
# Load for case: Import "<agent_name>" (as a package or module)
45+
def _load_from_module_or_package(
46+
self, agent_name: str
47+
) -> Optional[BaseAgent]:
48+
# Load for case: Import "{agent_name}" (as a package or module)
4249
# Covers structures:
43-
# a) agents_dir/agent_name.py (with root_agent or agent.root_agent in it)
44-
# b) agents_dir/agent_name_folder/__init__.py (with root_agent or agent.root_agent in the package)
50+
# a) agents_dir/{agent_name}.py (with root_agent in the module)
51+
# b) agents_dir/{agent_name}/__init__.py (with root_agent in the package)
4552
try:
4653
module_candidate = importlib.import_module(agent_name)
47-
# Check for "root_agent" directly in "<agent_name>" module/package
54+
# Check for "root_agent" directly in "{agent_name}" module/package
4855
if hasattr(module_candidate, "root_agent"):
4956
logger.debug("Found root_agent directly in %s", agent_name)
50-
return module_candidate.root_agent
51-
# Check for "<agent_name>.agent.root_agent" structure (e.g. agent_name is a package,
52-
# and it has an 'agent' submodule/attribute which in turn has 'root_agent')
53-
if hasattr(module_candidate, "agent") and hasattr(
54-
module_candidate.agent, "root_agent"
55-
):
56-
logger.debug("Found root_agent in %s.agent attribute", agent_name)
57-
if isinstance(module_candidate.agent, BaseAgent):
58-
return module_candidate.agent.root_agent
57+
if isinstance(module_candidate.root_agent, BaseAgent):
58+
return module_candidate.root_agent
5959
else:
6060
logger.warning(
6161
"Root agent found is not an instance of BaseAgent. But a type %s",
62-
type(module_candidate.agent),
62+
type(module_candidate.root_agent),
6363
)
64+
6465
except ModuleNotFoundError:
6566
logger.debug("Module %s itself not found.", agent_name)
6667
# Re-raise as ValueError to be caught by the final error message construction
@@ -72,13 +73,13 @@ def _load_from_module_or_package(self, agent_name: str) -> BaseAgent:
7273

7374
return None
7475

75-
def _load_from_submodule(self, agent_name: str) -> BaseAgent:
76-
# Load for case: Import "<agent_name>.agent" and look for "root_agent"
77-
# Covers structure: agents_dir/agent_name_folder/agent.py (where agent.py has root_agent)
76+
def _load_from_submodule(self, agent_name: str) -> Optional[BaseAgent]:
77+
# Load for case: Import "{agent_name}.agent" and look for "root_agent"
78+
# Covers structure: agents_dir/{agent_name}/agent.py (with root_agent defined in the module)
7879
try:
7980
module_candidate = importlib.import_module(f"{agent_name}.agent")
8081
if hasattr(module_candidate, "root_agent"):
81-
logger.debug("Found root_agent in %s.agent", agent_name)
82+
logger.info("Found root_agent in %s.agent", agent_name)
8283
if isinstance(module_candidate.root_agent, BaseAgent):
8384
return module_candidate.root_agent
8485
else:
@@ -106,32 +107,28 @@ def _perform_load(self, agent_name: str) -> BaseAgent:
106107
)
107108
envs.load_dotenv_for_agent(agent_name, str(self.agents_dir))
108109

109-
root_agent = self._load_from_module_or_package(agent_name)
110-
if root_agent:
110+
if root_agent := self._load_from_submodule(agent_name):
111111
return root_agent
112112

113-
root_agent = self._load_from_submodule(agent_name)
114-
if root_agent:
113+
if root_agent := self._load_from_module_or_package(agent_name):
115114
return root_agent
116115

117116
# If no root_agent was found by any pattern
118117
raise ValueError(
119118
f"No root_agent found for '{agent_name}'. Searched in"
120-
f" '{agent_name}.agent.root_agent', '{agent_name}.root_agent', and"
121-
f" via an 'agent' attribute within the '{agent_name}' module/package."
119+
f" '{agent_name}.agent.root_agent', '{agent_name}.root_agent'."
122120
f" Ensure '{self.agents_dir}/{agent_name}' is structured correctly,"
123121
" an .env file can be loaded if present, and a root_agent is"
124122
" exposed."
125123
)
126124

127125
def load_agent(self, agent_name: str) -> BaseAgent:
128-
"""Load an agent module (with caching & .env) and return its root_agent (asynchronously)."""
126+
"""Load an agent module (with caching & .env) and return its root_agent."""
129127
if agent_name in self._agent_cache:
130128
logger.debug("Returning cached agent for %s (async)", agent_name)
131129
return self._agent_cache[agent_name]
132130

133131
logger.debug("Loading agent %s - not in cache.", agent_name)
134-
# Assumes this method is called when the context manager (`with self:`) is active
135132
agent = self._perform_load(agent_name)
136133
self._agent_cache[agent_name] = agent
137134
return agent

0 commit comments

Comments
 (0)
0