Skip to content

Commit 1402a30

Browse files
RudrenduPaulharanrk
authored andcommitted
fix(cli): support flat-module agents in _determine_agent_language
Merge #5235 `_determine_agent_language()` handled only 3 of the 4 agent structures that `load_agent()` supports. When an agent is a flat module (`agents_dir/my_agent.py`, with no subdirectory), `load_agent()` loads it successfully but `_determine_agent_language()` raised `ValueError`. This adds the missing flat-module branch so language detection is consistent with all four supported load patterns: - `{name}/agent.py` - `{name}/__init__.py` - `{name}/root_agent.yaml` - `{name}.py` (flat module) It also adds `__init__.py` to the recognized agent marker files listed in the `adk web` / `adk api_server` AGENTS_DIR docstrings, and adds a `TestDetermineAgentLanguage` suite covering all four patterns plus the unrecognized-structure error case. Co-authored-by: Haran Rajkumar <haranrk@google.com> PiperOrigin-RevId: 933831825
1 parent d60ac69 commit 1402a30

3 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/google/adk/cli/cli_tools_click.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,8 +1806,8 @@ def cli_web(
18061806
"""Starts a FastAPI server with Web UI for agents.
18071807
18081808
AGENTS_DIR: The directory of agents (where each subdirectory is a single
1809-
agent containing `agent.py` or `root_agent.yaml` files) or a path pointing
1810-
directly to a single agent folder.
1809+
agent containing `agent.py`, `__init__.py`, or `root_agent.yaml`) or a path
1810+
pointing directly to a single agent folder.
18111811
18121812
Example:
18131813
@@ -1947,8 +1947,8 @@ def cli_api_server(
19471947
"""Starts a FastAPI server for agents.
19481948
19491949
AGENTS_DIR: The directory of agents (where each subdirectory is a single
1950-
agent containing `agent.py` or `root_agent.yaml` files) or a path pointing
1951-
directly to a single agent folder.
1950+
agent containing `agent.py`, `__init__.py`, or `root_agent.yaml`) or a path
1951+
pointing directly to a single agent folder.
19521952
19531953
Example:
19541954

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ def _determine_agent_language(
471471
return "python"
472472
elif (base_path / "__init__.py").exists():
473473
return "python"
474+
elif (base_path.parent / f"{agent_name}.py").exists():
475+
return "python"
474476

475477
raise ValueError(f"Could not determine agent type for '{agent_name}'.")
476478

tests/unittests/cli/utils/test_agent_loader.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,3 +1039,56 @@ def test_validate_agent_name_rejects_nonexistent_agent(self):
10391039
# 'subprocess' is a valid identifier but shouldn't be importable as an agent
10401040
with pytest.raises(ValueError, match="Agent not found"):
10411041
loader.load_agent("subprocess")
1042+
1043+
1044+
class TestDetermineAgentLanguage:
1045+
"""Tests for AgentLoader._determine_agent_language covering all 4 load patterns."""
1046+
1047+
def test_flat_module_returns_python(self):
1048+
"""Flat-module agent (agents_dir/agent_name.py) is detected as python."""
1049+
with tempfile.TemporaryDirectory() as temp_dir:
1050+
temp_path = Path(temp_dir)
1051+
(temp_path / "my_agent.py").write_text("root_agent = None\n")
1052+
loader = AgentLoader(temp_dir)
1053+
assert loader._determine_agent_language("my_agent") == "python"
1054+
1055+
def test_agent_py_subdirectory_returns_python(self):
1056+
"""Subdirectory with agent.py is detected as python."""
1057+
with tempfile.TemporaryDirectory() as temp_dir:
1058+
temp_path = Path(temp_dir)
1059+
agent_dir = temp_path / "my_agent"
1060+
agent_dir.mkdir()
1061+
(agent_dir / "agent.py").write_text("root_agent = None\n")
1062+
loader = AgentLoader(temp_dir)
1063+
assert loader._determine_agent_language("my_agent") == "python"
1064+
1065+
def test_init_py_subdirectory_returns_python(self):
1066+
"""Subdirectory with __init__.py is detected as python."""
1067+
with tempfile.TemporaryDirectory() as temp_dir:
1068+
temp_path = Path(temp_dir)
1069+
agent_dir = temp_path / "my_agent"
1070+
agent_dir.mkdir()
1071+
(agent_dir / "__init__.py").write_text("root_agent = None\n")
1072+
loader = AgentLoader(temp_dir)
1073+
assert loader._determine_agent_language("my_agent") == "python"
1074+
1075+
def test_root_agent_yaml_returns_yaml(self):
1076+
"""Subdirectory with root_agent.yaml is detected as yaml."""
1077+
with tempfile.TemporaryDirectory() as temp_dir:
1078+
temp_path = Path(temp_dir)
1079+
agent_dir = temp_path / "my_agent"
1080+
agent_dir.mkdir()
1081+
(agent_dir / "root_agent.yaml").write_text("root_agent: {}\n")
1082+
loader = AgentLoader(temp_dir)
1083+
assert loader._determine_agent_language("my_agent") == "yaml"
1084+
1085+
def test_unrecognized_structure_raises_value_error(self):
1086+
"""A directory with no recognized structure raises ValueError."""
1087+
with tempfile.TemporaryDirectory() as temp_dir:
1088+
temp_path = Path(temp_dir)
1089+
agent_dir = temp_path / "my_agent"
1090+
agent_dir.mkdir()
1091+
(agent_dir / "main.py").write_text("root_agent = None\n")
1092+
loader = AgentLoader(temp_dir)
1093+
with pytest.raises(ValueError, match="Could not determine agent type"):
1094+
loader._determine_agent_language("my_agent")

0 commit comments

Comments
 (0)