🦧

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/を含める)を試したが解決せず

妥協案

しょうがないのでフォルダ構造を変えて下記の構造、デプロイをまねたら一旦うまく行った。

https://github.com/google/adk-samples/blob/main/python/agents/travel-concierge/deployment/deploy.py

https://qiita.com/nnhkrnk/items/023d91b00075be0b1cbf

まとめ

Vertex AI Agent Engineへのデプロイ時、カスタムモジュール構造を持つプロジェクトではModuleNotFoundErrorが発生する可能性が高い。

  1. cloudpickleは絶対モジュールパスを保持する
  2. extra_packagesはディレクトリをPYTHONPATHに追加するだけ
  3. モジュール構造とPYTHONPATHの不整合が問題の根本原因
  4. シンプルなフラット構造(すべてを単一ファイルにまとめる)が最も確実

推奨アプローチ(未検証):

  • すべての依存コードを単一のagent.pyファイルに統合
  • extra_packagesを使わず、必要最小限の構成でデプロイ
  • または、プロジェクトルート全体を軽量化してアップロード

Discussion