Agent EngineデプロイでModuleNotFoundError解決できず無事KOされた
概要
Google Agent Development Kit (ADK)で作成したエージェントをVertex AI Agent Engineにデプロイする際、ModuleNotFoundError: No module named 'agents'エラーが発生し、複数のアプローチを試したが解決できなかった。
環境
- Python: 3.13
- google-adk: 1.17.0
- google-cloud-aiplatform: 1.126.1
- cloudpickle: 3.1.1
プロジェクト構造
ai-agent/
├── agents/
│ ├── __init__.py
│ └── transcribe_single_table_workflow/
│ ├── __init__.py
│ ├── agent.py
│ └── standalone_agent.py
├── deployment/
│ └── deploy.py
└── .env
発生したエラー
Vertex AI Agent Engine環境で以下のエラーが発生:
ModuleNotFoundError: No module named 'agents'
エラー発生箇所:
File "/code/app/api/factory/utils.py", line 179, in get_local_object
return cloudpickle.loads(f.read())
試したアプローチと結果
1. agents/init.py を作成
試したこと:
-
agents/__init__.pyを作成してPythonパッケージとして認識させる
結果: ❌ 失敗
- ローカルでは
import agentsが成功 - Vertex AI環境では依然として
ModuleNotFoundError
2. extra_packagesにagents/ディレクトリを指定
試したこと:
extra_packages = [str(project_root / 'agents')]
結果: ❌ 失敗
-
agents/ディレクトリがPYTHONPATHに追加される - しかし
agents.transcribe_single_table_workflow.agentというパスは解決できない - Vertex AI環境では
agentsがトップレベルモジュールになるため
3. extra_packagesにプロジェクトルート全体を指定
試したこと:
extra_packages = [str(project_root)] # ai-agent/
結果: ❌ タイムアウト
-
.venvディレクトリ(446MB)が含まれてアップロードがタイムアウト
4. 一時ディレクトリにagents/のみをコピー
試したこと:
temp_dir = Path(tempfile.mkdtemp(prefix="agent_deploy_"))
shutil.copytree(source_agents_dir, temp_dir / "agents")
extra_packages = [str(temp_dir)]
結果: ❌ 失敗
-
.venvは除外できたがモジュールパスの問題は解決せず
5. standalone_agent.pyを作成してフラット化
試したこと:
- すべてのコードを単一ファイル
standalone_agent.pyに統合 - 一時ディレクトリに
agent.pyとしてコピー -
agentモジュールとしてインポート
temp_dir = Path(tempfile.mkdtemp(prefix="agent_deploy_"))
shutil.copy(source_standalone_agent, temp_dir / "agent.py")
sys.path.insert(0, str(temp_dir))
import agent as agent_module
結果: ❌ 失敗
- cloudpickleが依然として元のモジュール参照を保持
6. extra_packagesに特定のagentディレクトリを指定
試したこと:
extra_packages = [str(project_root / 'agents' / 'transcribe_single_table_workflow')]
結果: ❌ 失敗
-
transcribe_single_table_workflowがトップレベルになる -
agents.transcribe_single_table_workflow.agentは解決できない
問題の根本原因
cloudpickleのシリアライゼーション
デプロイスクリプトで以下のようにインポート:
module_name = f"agents.{args.agent}.agent"
agent_module = importlib.import_module(module_name)
root_agent = agent_module.root_agent
cloudpickleがroot_agentオブジェクトをシリアライズする際、モジュール参照としてagents.transcribe_single_table_workflow.agentという絶対パスを保存する。
Vertex AI環境でのデシリアライゼーション
extra_packagesで指定したディレクトリがPYTHONPATHに追加されるが、以下のような構造になる:
ケース1: extra_packages = ['/path/to/agents/transcribe_single_table_workflow']
PYTHONPATH: /vertex/path/transcribe_single_table_workflow
→ import agent は可能
→ import agents.transcribe_single_table_workflow.agent は不可能
ケース2: extra_packages = ['/path/to/agents']
PYTHONPATH: /vertex/path/agents
→ import transcribe_single_table_workflow.agent は可能
→ import agents.transcribe_single_table_workflow.agent は不可能(agentsがトップレベル)
ケース3(理論上の正解): extra_packages = ['/path/to/ai-agent']
PYTHONPATH: /vertex/path/ai-agent
→ import agents.transcribe_single_table_workflow.agent は可能
しかし、ケース3は.venv(446MB)を含むためタイムアウトする。
検証したログ
GCP Cloud Loggingで以下を確認:
resource.type="aiplatform.googleapis.com/ReasoningEngine"
severity>=ERROR
すべてのデプロイ試行で同一のエラー:
ModuleNotFoundError: No module named 'agents'
参考情報
関連するGitHub Issues
Google ADKやVertex AI Agent Engineの既知の問題を確認:
-
GitHub Issue #2044の解決策(
extra_packagesにagents/を含める)を試したが解決せず
妥協案
しょうがないのでフォルダ構造を変えて下記の構造、デプロイをまねたら一旦うまく行った。
まとめ
Vertex AI Agent Engineへのデプロイ時、カスタムモジュール構造を持つプロジェクトではModuleNotFoundErrorが発生する可能性が高い。
- cloudpickleは絶対モジュールパスを保持する
-
extra_packagesはディレクトリをPYTHONPATHに追加するだけ - モジュール構造とPYTHONPATHの不整合が問題の根本原因
- シンプルなフラット構造(すべてを単一ファイルにまとめる)が最も確実
推奨アプローチ(未検証):
- すべての依存コードを単一の
agent.pyファイルに統合 -
extra_packagesを使わず、必要最小限の構成でデプロイ - または、プロジェクトルート全体を軽量化してアップロード
Discussion