From 6b5c7ae38a9b3932cf1af37723d3ae303ef05ebd Mon Sep 17 00:00:00 2001 From: Stephen Witkowski Date: Thu, 22 Jan 2026 16:22:52 -0500 Subject: [PATCH 1/2] fix(cli): fix agent engine deploy imports --- CHANGELOG.md | 8 ++++++-- src/google/adk/cli/cli_deploy.py | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5ed6b1ed4..029758459d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Bug Fixes +* Sanitize Agent Engine temp folder names to avoid invalid module imports. +* Fix Agent Engine template imports for agents in an app/ subdirectory. + ## [1.23.0](https://github.com/google/adk-python/compare/v1.22.1...v1.23.0) (2026-01-22) ### ⚠ BREAKING CHANGES @@ -82,8 +88,6 @@ * Upgrade the sample BigQuery agent model version to `gemini-2.5-flash` ([fd2c0f5](https://github.com/google/adk-python/commit/fd2c0f556b786417a9f6add744827b07e7a06b7d)) * Import `migration_runner` lazily within the migrate command ([905604f](https://github.com/google/adk-python/commit/905604faac82aca8ae0935eebea288f82985e9c5)) - - ## [1.22.1](https://github.com/google/adk-python/compare/v1.22.0...v1.22.1) (2026-01-09) ### Bug Fixes diff --git a/src/google/adk/cli/cli_deploy.py b/src/google/adk/cli/cli_deploy.py index 2787c8d9d4..97d1780dd6 100644 --- a/src/google/adk/cli/cli_deploy.py +++ b/src/google/adk/cli/cli_deploy.py @@ -33,6 +33,12 @@ ) +def _sanitize_temp_folder_name(folder_name: str) -> str: + if not folder_name: + return folder_name + return folder_name.replace('-', '_') + + def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None: """Ensures staged requirements include Agent Engine dependencies.""" if not os.path.exists(requirements_txt_path): @@ -107,7 +113,7 @@ def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None: from google.adk.agents import config_agent_utils root_agent = config_agent_utils.from_config("{agent_folder}/root_agent.yaml") else: - from .agent import {adk_app_object} + from {adk_app_import_module} import {adk_app_object} if {express_mode}: # Whether or not to use Express Mode vertexai.init(api_key=os.environ.get("GOOGLE_API_KEY")) @@ -789,7 +795,8 @@ def to_agent_engine( os.chdir(parent_folder) did_change_cwd = True tmp_app_name = app_name + '_tmp' + datetime.now().strftime('%Y%m%d_%H%M%S') - temp_folder = temp_folder or tmp_app_name + raw_temp_folder = temp_folder or tmp_app_name + temp_folder = _sanitize_temp_folder_name(raw_temp_folder) agent_src_path = os.path.join(parent_folder, temp_folder) click.echo(f'Staging all files in: {agent_src_path}') # remove agent_src_path if it exists @@ -953,6 +960,17 @@ def to_agent_engine( is_config_agent = True adk_app_file = os.path.join(temp_folder, f'{adk_app}.py') + app_subdir_agent = os.path.join(agent_src_path, 'app', 'agent.py') + app_subdir_init = os.path.join(agent_src_path, 'app', '__init__.py') + root_agent_file = os.path.join(agent_src_path, 'agent.py') + if ( + os.path.exists(app_subdir_agent) + and os.path.exists(app_subdir_init) + and not os.path.exists(root_agent_file) + ): + adk_app_import_module = '.app.agent' + else: + adk_app_import_module = '.agent' if adk_app_object == 'root_agent': adk_app_type = 'agent' elif adk_app_object == 'app': @@ -972,6 +990,7 @@ def to_agent_engine( agent_folder=f'./{temp_folder}', adk_app_object=adk_app_object, adk_app_type=adk_app_type, + adk_app_import_module=adk_app_import_module, express_mode=api_key is not None, ) ) From dbd80143eda7ce7adec4bc145bd83de95a7b6f00 Mon Sep 17 00:00:00 2001 From: Stephen Witkowski Date: Thu, 22 Jan 2026 16:27:35 -0500 Subject: [PATCH 2/2] fix(cli): harden temp folder sanitization --- src/google/adk/cli/cli_deploy.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/google/adk/cli/cli_deploy.py b/src/google/adk/cli/cli_deploy.py index 97d1780dd6..25655683cd 100644 --- a/src/google/adk/cli/cli_deploy.py +++ b/src/google/adk/cli/cli_deploy.py @@ -36,7 +36,12 @@ def _sanitize_temp_folder_name(folder_name: str) -> str: if not folder_name: return folder_name - return folder_name.replace('-', '_') + sanitized = ''.join( + char if char.isalnum() or char == '_' else '_' for char in folder_name + ) + if sanitized and sanitized[0].isdigit(): + return '_' + sanitized + return sanitized def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None: