@@ -67,6 +67,10 @@ def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None:
6767FROM python:3.11-slim
6868WORKDIR /app
6969
70+ RUN apt-get update && \
71+ apt-get upgrade -y && \
72+ apt-get install -y git
73+
7074# Create a non-root user
7175RUN adduser --disabled-password --gecos "" myuser
7276
@@ -83,7 +87,7 @@ def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None:
8387# Set up environment variables - End
8488
8589# Install ADK - Start
86- RUN pip install google-adk=={adk_version}
90+ # RUN pip install google-adk=={adk_version}
8791# Install ADK - End
8892
8993# Copy agent - Start
@@ -99,33 +103,7 @@ def _ensure_agent_engine_dependency(requirements_txt_path: str) -> None:
99103
100104EXPOSE {port}
101105
102- CMD adk {command} --port={port} {host_option} {service_option} {trace_to_cloud_option} {otel_to_cloud_option} {allow_origins_option} {a2a_option} {trigger_sources_option} "/app/agents"
103- """
104-
105- _AGENT_ENGINE_APP_TEMPLATE : Final [str ] = """
106- import os
107- import vertexai
108- from vertexai.agent_engines import AdkApp
109-
110- if {is_config_agent}:
111- from google.adk.agents import config_agent_utils
112- config_path = os.path.join(os.path.dirname(__file__), "root_agent.yaml")
113- root_agent = config_agent_utils.from_config(config_path)
114- else:
115- from .agent import {adk_app_object}
116-
117- if {express_mode}: # Whether or not to use Express Mode
118- vertexai.init(api_key=os.environ.get("GOOGLE_API_KEY"))
119- else:
120- vertexai.init(
121- project=os.environ.get("GOOGLE_CLOUD_PROJECT"),
122- location=os.environ.get("GOOGLE_CLOUD_LOCATION"),
123- )
124-
125- adk_app = AdkApp(
126- {adk_app_type}={adk_app_object},
127- enable_tracing={trace_to_cloud_option},
128- )
106+ CMD adk {command} --port={port} {host_option} {service_option} {trace_to_cloud_option} {otel_to_cloud_option} {allow_origins_option} {a2a_option} {trigger_sources_option} {gemini_enterprise_option} "/app/agents"
129107"""
130108
131109_AGENT_ENGINE_CLASS_METHODS = [
@@ -830,7 +808,7 @@ def to_agent_engine(
830808 * ,
831809 agent_folder : str ,
832810 temp_folder : Optional [str ] = None ,
833- adk_app : str ,
811+ adk_app : Optional [ str ] = None ,
834812 staging_bucket : Optional [str ] = None ,
835813 trace_to_cloud : Optional [bool ] = None ,
836814 otel_to_cloud : Optional [bool ] = None ,
@@ -846,36 +824,26 @@ def to_agent_engine(
846824 env_file : Optional [str ] = None ,
847825 agent_engine_config_file : Optional [str ] = None ,
848826 skip_agent_import_validation : bool = True ,
827+ trigger_sources : Optional [str ] = None ,
828+ artifact_service_uri : Optional [str ] = None ,
829+ adk_version : Optional [str ] = None ,
849830):
850831 """Deploys an agent to Vertex AI Agent Engine.
851832
852833 `agent_folder` should contain the following files:
853834
854835 - __init__.py
855836 - agent.py
856- - <adk_app>.py (optional, for customization; will be autogenerated otherwise)
857837 - requirements.txt (optional, for additional dependencies)
858838 - .env (optional, for environment variables)
859839 - ... (other required source files)
860840
861- The contents of `adk_app` should look something like:
862-
863- ```
864- from agent import <adk_app_object>
865- from vertexai.agent_engines import AdkApp
866-
867- adk_app = AdkApp(
868- agent=<adk_app_object>, # or `app=<adk_app_object>`
869- )
870- ```
871-
872841 Args:
873842 agent_folder (str): The folder (absolute path) containing the agent source
874843 code.
875844 temp_folder (str): The temp folder for the generated Agent Engine source
876845 files. It will be replaced with the generated files if it already exists.
877- adk_app (str): The name of the file (without .py) containing the AdkApp
878- instance.
846+ adk_app (str): Deprecated. This argument is no longer required or used.
879847 staging_bucket (str): Deprecated. This argument is no longer required or
880848 used.
881849 trace_to_cloud (bool): Whether to enable Cloud Trace.
@@ -884,13 +852,12 @@ def to_agent_engine(
884852 api_key (str): Optional. The API key to use for Express Mode.
885853 If not provided, the API key from the GOOGLE_API_KEY environment variable
886854 will be used. It will only be used if GOOGLE_GENAI_USE_VERTEXAI is true.
887- adk_app_object (str): Optional. The Python object corresponding to the root
888- ADK agent or app. Defaults to `root_agent` if not specified .
855+ adk_app_object (str): Deprecated. This argument is no longer required or
856+ used .
889857 agent_engine_id (str): Optional. The ID of the Agent Engine instance to
890858 update. If not specified, a new Agent Engine instance will be created.
891- absolutize_imports (bool): Optional. Default is True. Whether to absolutize
892- imports. If True, all relative imports will be converted to absolute
893- import statements.
859+ absolutize_imports (bool): Deprecated. This argument is no longer required
860+ or used.
894861 project (str): Optional. Google Cloud project id for the deployed agent. If
895862 not specified, the project from the `GOOGLE_CLOUD_PROJECT` environment
896863 variable will be used. It will be ignored if `api_key` is specified.
@@ -899,31 +866,41 @@ def to_agent_engine(
899866 variable will be used. It will be ignored if `api_key` is specified.
900867 display_name (str): Optional. The display name of the Agent Engine.
901868 description (str): Optional. The description of the Agent Engine.
902- requirements_file (str): Optional. The filepath to the `requirements.txt`
903- file to use. If not specified, the `requirements.txt` file in the
904- `agent_folder` will be used.
869+ requirements_file (str): Deprecated. This argument is no longer required or
870+ used.
905871 env_file (str): Optional. The filepath to the `.env` file for environment
906872 variables. If not specified, the `.env` file in the `agent_folder` will be
907873 used. The values of `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`
908874 will be overridden by `project` and `region` if they are specified.
909875 agent_engine_config_file (str): The filepath to the agent engine config file
910876 to use. If not specified, the `.agent_engine_config.json` file in the
911877 `agent_folder` will be used.
912- skip_agent_import_validation (bool): Optional. Default is True. If True,
913- skip the pre-deployment import validation of `agent.py`. This can be
914- useful when the local environment does not have the same dependencies as
915- the deployment environment.
878+ skip_agent_import_validation (bool): Deprecated. This argument is no longer
879+ required or used.
880+ trigger_sources (str): Optional. Comma-separated list of trigger sources to
881+ enable (e.g., 'pubsub,eventarc'). Registers /trigger/* endpoints for
882+ batch and event-driven agent invocations.
883+ artifact_service_uri (str): Optional. The URI of the artifact service.
884+ adk_version (str): Optional. The ADK version to use in Agent Engine
885+ deployment.
916886 """
917887 app_name = os .path .basename (agent_folder )
918888 display_name = display_name or app_name
919889 parent_folder = os .path .dirname (agent_folder )
920- adk_app_object = adk_app_object or 'root_agent'
921- if adk_app_object not in ['root_agent' , 'app' ]:
922- click .echo (
923- f'Invalid adk_app_object: { adk_app_object } . Please use "root_agent"'
924- ' or "app".'
890+ if adk_app_object :
891+ warnings .warn (
892+ 'WARNING: `--adk_app_object` is deprecated and will be removed in the'
893+ ' future. Please drop it from the list of arguments.' ,
894+ DeprecationWarning ,
895+ stacklevel = 2 ,
896+ )
897+ if adk_app :
898+ warnings .warn (
899+ 'WARNING: `adk_app` is deprecated and will be removed in a future'
900+ ' release. Please drop it from the list of arguments.' ,
901+ DeprecationWarning ,
902+ stacklevel = 2 ,
925903 )
926- return
927904 if staging_bucket :
928905 warnings .warn (
929906 'WARNING: `staging_bucket` is deprecated and will be removed in a'
@@ -943,15 +920,14 @@ def to_agent_engine(
943920 did_change_cwd = True
944921 tmp_app_name = app_name + '_tmp' + datetime .now ().strftime ('%Y%m%d_%H%M%S' )
945922 temp_folder = temp_folder or tmp_app_name
946- agent_src_path = os .path .join (parent_folder , temp_folder )
923+ agent_src_path = os .path .join (parent_folder , temp_folder , 'agents' , app_name )
947924 click .echo (f'Staging all files in: { agent_src_path } ' )
948925 # remove agent_src_path if it exists
949926 if os .path .exists (agent_src_path ):
950927 click .echo ('Removing existing files' )
951928 shutil .rmtree (agent_src_path )
952929
953930 try :
954- click .echo (f'Staging all files in: { agent_src_path } ' )
955931 ignore_patterns = None
956932 ae_ignore_path = os .path .join (agent_folder , '.ae_ignore' )
957933 if os .path .exists (ae_ignore_path ):
@@ -966,6 +942,7 @@ def to_agent_engine(
966942 ignore = ignore_patterns ,
967943 dirs_exist_ok = True ,
968944 )
945+ os .chdir (os .path .join (parent_folder , temp_folder ))
969946 click .echo ('Copying agent source code complete.' )
970947
971948 project = _resolve_project (project )
@@ -1002,30 +979,13 @@ def to_agent_engine(
1002979 )
1003980 agent_config ['description' ] = description
1004981
1005- requirements_txt_path = os .path .join (agent_src_path , 'requirements.txt' )
1006982 if requirements_file :
1007- if os .path .exists (requirements_txt_path ):
1008- click .echo (
1009- f'Overwriting { requirements_txt_path } with { requirements_file } '
1010- )
1011- shutil .copyfile (requirements_file , requirements_txt_path )
1012- elif 'requirements_file' in agent_config :
1013- if os .path .exists (requirements_txt_path ):
1014- click .echo (
1015- f'Overwriting { requirements_txt_path } with'
1016- f' { agent_config ["requirements_file" ]} '
1017- )
1018- shutil .copyfile (agent_config ['requirements_file' ], requirements_txt_path )
1019- else :
1020- # Attempt to read requirements from requirements.txt in the dir (if any).
1021- if not os .path .exists (requirements_txt_path ):
1022- click .echo (f'Creating { requirements_txt_path } ...' )
1023- with open (requirements_txt_path , 'w' , encoding = 'utf-8' ) as f :
1024- f .write (_AGENT_ENGINE_REQUIREMENT + '\n ' )
1025- click .echo (f'Created { requirements_txt_path } ' )
1026- _ensure_agent_engine_dependency (requirements_txt_path )
1027- agent_config ['requirements_file' ] = f'{ temp_folder } /requirements.txt'
1028-
983+ warnings .warn (
984+ 'WARNING: `--requirements_file` is deprecated and will be removed in the'
985+ ' future. Please drop it from the list of arguments.' ,
986+ DeprecationWarning ,
987+ stacklevel = 2 ,
988+ )
1029989 env_vars = {}
1030990 if not env_file :
1031991 # Attempt to read the env variables from .env in the dir (if any).
@@ -1094,92 +1054,97 @@ def to_agent_engine(
10941054
10951055 from ..utils ._google_client_headers import get_tracking_headers
10961056
1057+ http_options = {'headers' : get_tracking_headers ()}
10971058 if project and region :
1098- click .echo ('Initializing Vertex AI ...' )
1059+ click .echo ('Initializing Client with project and region ...' )
10991060 client = vertexai .Client (
11001061 project = project ,
11011062 location = region ,
1102- http_options = { 'headers' : get_tracking_headers ()} ,
1063+ http_options = http_options ,
11031064 )
11041065 elif api_key :
1105- click .echo ('Initializing Vertex AI in Express Mode with API key...' )
1106- client = vertexai .Client (
1107- api_key = api_key , http_options = {'headers' : get_tracking_headers ()}
1108- )
1066+ click .echo ('Initializing Client with Express Mode API key...' )
1067+ client = vertexai .Client (api_key = api_key , http_options = http_options )
11091068 else :
11101069 click .echo (
11111070 'No project/region or api_key provided. '
11121071 'Please specify either project/region or api_key.'
11131072 )
11141073 return
1115- click .echo ('Vertex AI initialized.' )
1116-
1117- is_config_agent = False
1118- config_root_agent_file = os .path .join (agent_src_path , 'root_agent.yaml' )
1119- if os .path .exists (config_root_agent_file ):
1120- click .echo (f'Config agent detected: { config_root_agent_file } ' )
1121- is_config_agent = True
1122-
1123- # Validate that the agent module can be imported before deployment.
1124- if not skip_agent_import_validation :
1125- click .echo ('Validating agent module...' )
1126- _validate_agent_import (agent_src_path , adk_app_object , is_config_agent )
1127-
1128- adk_app_file = os .path .join (temp_folder , f'{ adk_app } .py' )
1129- if adk_app_object == 'root_agent' :
1130- adk_app_type = 'agent'
1131- elif adk_app_object == 'app' :
1132- adk_app_type = 'app'
1133- else :
1134- click .echo (
1135- f'Invalid adk_app_object: { adk_app_object } . Please use "root_agent"'
1136- ' or "app".'
1074+
1075+ if skip_agent_import_validation :
1076+ warnings .warn (
1077+ 'WARNING: `--skip-agent-import-validation` is deprecated and will be'
1078+ ' removed in the future. Please drop it from the list of arguments.' ,
1079+ DeprecationWarning ,
1080+ stacklevel = 2 ,
11371081 )
1138- return
1139- with open (adk_app_file , 'w' , encoding = 'utf-8' ) as f :
1140- f .write (
1141- _AGENT_ENGINE_APP_TEMPLATE .format (
1142- app_name = app_name ,
1143- trace_to_cloud_option = trace_to_cloud ,
1144- is_config_agent = is_config_agent ,
1145- agent_folder = f'./{ temp_folder } ' ,
1146- adk_app_object = adk_app_object ,
1147- adk_app_type = adk_app_type ,
1148- express_mode = api_key is not None ,
1149- )
1082+ def create_dockerfile_for_agent_engine (resource_name : str ):
1083+ requirements_txt_path = os .path .join (agent_src_path , 'requirements.txt' )
1084+ install_agent_deps = (
1085+ f'RUN pip install -r "/app/agents/{ app_name } /requirements.txt"'
1086+ if os .path .exists (requirements_txt_path )
1087+ else '# No requirements.txt found.'
1088+ )
1089+ trigger_sources_option = (
1090+ f'--trigger_sources={ trigger_sources } ' if trigger_sources else ''
1091+ )
1092+ agent_engine_uri = f'agentengine://{ resource_name } '
1093+ dockerfile_content = _DOCKERFILE_TEMPLATE .format (
1094+ gcp_project_id = project ,
1095+ gcp_region = region ,
1096+ app_name = app_name ,
1097+ port = 8080 ,
1098+ command = 'api_server' ,
1099+ install_agent_deps = install_agent_deps ,
1100+ service_option = _get_service_option_by_adk_version (
1101+ adk_version ,
1102+ agent_engine_uri , # session_service_uri
1103+ artifact_service_uri ,
1104+ agent_engine_uri , # memory_service_uri
1105+ False , # use_local_storage
1106+ ),
1107+ trace_to_cloud_option = '--trace_to_cloud' if trace_to_cloud else '' ,
1108+ otel_to_cloud_option = '--otel_to_cloud' if otel_to_cloud else '' ,
1109+ allow_origins_option = '' , # Not supported for now.
1110+ adk_version = adk_version ,
1111+ host_option = '--host=0.0.0.0' ,
1112+ a2a_option = '' , # '--a2a',
1113+ trigger_sources_option = trigger_sources_option ,
1114+ gemini_enterprise_option = f'--gemini_enterprise_app_name={ app_name } ' ,
11501115 )
1151- click .echo (f'Created { adk_app_file } ' )
1152- click .echo ('Files and dependencies resolved' )
1116+ with open ('Dockerfile' , 'w' , encoding = 'utf-8' ) as f :
1117+ f .write (dockerfile_content )
1118+
11531119 if absolutize_imports :
1154- click .echo (
1155- 'Agent Engine deployments have switched to source-based deployment, '
1156- 'so it is no longer necessary to absolutize imports.'
1120+ warnings .warn (
1121+ 'WARNING: `--absolutize_imports` is deprecated and will be removed'
1122+ ' in the future. Please drop it from the list of arguments.' ,
1123+ DeprecationWarning ,
1124+ stacklevel = 2 ,
11571125 )
11581126 click .echo ('Deploying to agent engine...' )
1159- agent_config ['entrypoint_module' ] = f'{ temp_folder } .{ adk_app } '
1160- agent_config ['entrypoint_object' ] = 'adk_app'
1161- agent_config ['source_packages' ] = [temp_folder ]
1127+ agent_config ['source_packages' ] = [f'agents/{ app_name } ' , 'Dockerfile' ]
1128+ agent_config ['image_spec' ] = {} # Use the Dockerfile
11621129 agent_config ['class_methods' ] = _AGENT_ENGINE_CLASS_METHODS
11631130 agent_config ['agent_framework' ] = 'google-adk'
11641131
11651132 if not agent_engine_id :
1166- agent_engine = client .agent_engines .create (config = agent_config )
1167- click .secho (
1168- f'✅ Created agent engine: { agent_engine .api_resource .name } ' ,
1169- fg = 'green' ,
1170- )
1171- _print_agent_engine_url (agent_engine .api_resource .name )
1172- else :
1173- if project and region and not agent_engine_id .startswith ('projects/' ):
1174- agent_engine_id = f'projects/{ project } /locations/{ region } /reasoningEngines/{ agent_engine_id } '
1175- client .agent_engines .update (name = agent_engine_id , config = agent_config )
1176- click .secho (f'✅ Updated agent engine: { agent_engine_id } ' , fg = 'green' )
1177- _print_agent_engine_url (agent_engine_id )
1133+ agent_engine = client .agent_engines .create ()
1134+ agent_engine_id = agent_engine .api_resource .name
1135+ click .secho (f'Created a new agent engine: { agent_engine_id } ' , fg = 'green' )
1136+ elif project and region and not agent_engine_id .startswith ('projects/' ):
1137+ agent_engine_id = f'projects/{ project } /locations/{ region } /reasoningEngines/{ agent_engine_id } '
1138+ click .echo ('Creating Dockerfile...' )
1139+ create_dockerfile_for_agent_engine (agent_engine_id )
1140+ click .echo (f'Dockerfile created at { os .getcwd ()} /Dockerfile.' )
1141+ client .agent_engines .update (name = agent_engine_id , config = agent_config )
1142+ click .secho (f'Deployed to agent engine: { agent_engine_id } ' , fg = 'green' )
1143+ _print_agent_engine_url (agent_engine_id )
11781144 finally :
11791145 click .echo (f'Cleaning up the temp folder: { temp_folder } ' )
1146+ os .chdir (original_cwd )
11801147 shutil .rmtree (agent_src_path )
1181- if did_change_cwd :
1182- os .chdir (original_cwd )
11831148
11841149
11851150def to_gke (
0 commit comments