From 44f7ba265556c721649d947ae7b1302265bf3224 Mon Sep 17 00:00:00 2001 From: Shawn Yang Date: Wed, 25 Feb 2026 15:04:39 -0800 Subject: [PATCH] feat: add support for agent_config_source (ADK) in AgentEngines PiperOrigin-RevId: 875355220 --- .../unit/vertexai/genai/test_agent_engines.py | 210 ++++++++++++++++-- vertexai/_genai/agent_engines.py | 86 ++++++- vertexai/_genai/types/__init__.py | 24 +- vertexai/_genai/types/common.py | 166 ++++++++++---- 4 files changed, 402 insertions(+), 84 deletions(-) diff --git a/tests/unit/vertexai/genai/test_agent_engines.py b/tests/unit/vertexai/genai/test_agent_engines.py index c705f93753..6bb2f96f40 100644 --- a/tests/unit/vertexai/genai/test_agent_engines.py +++ b/tests/unit/vertexai/genai/test_agent_engines.py @@ -577,16 +577,16 @@ def register_operations(self) -> Dict[str, List[str]]: OperationRegistrableEngine().custom_method, schema_name=_TEST_CUSTOM_METHOD_NAME, ) -_TEST_AGENT_ENGINE_CUSTOM_METHOD_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_STANDARD_API_MODE -) +_TEST_AGENT_ENGINE_CUSTOM_METHOD_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_STANDARD_API_MODE _TEST_AGENT_ENGINE_ASYNC_CUSTOM_METHOD_SCHEMA = _agent_engines_utils._generate_schema( OperationRegistrableEngine().custom_async_method, schema_name=_TEST_CUSTOM_ASYNC_METHOD_NAME, ) -_TEST_AGENT_ENGINE_ASYNC_CUSTOM_METHOD_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_ASYNC_API_MODE -) +_TEST_AGENT_ENGINE_ASYNC_CUSTOM_METHOD_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_ASYNC_API_MODE _TEST_AGENT_ENGINE_STREAM_QUERY_SCHEMA = _agent_engines_utils._generate_schema( StreamQueryEngine().stream_query, schema_name=_TEST_DEFAULT_STREAM_METHOD_NAME, @@ -596,41 +596,41 @@ def register_operations(self) -> Dict[str, List[str]]: OperationRegistrableEngine().custom_stream_method, schema_name=_TEST_CUSTOM_STREAM_METHOD_NAME, ) -_TEST_AGENT_ENGINE_CUSTOM_STREAM_QUERY_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_STREAM_API_MODE -) +_TEST_AGENT_ENGINE_CUSTOM_STREAM_QUERY_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_STREAM_API_MODE _TEST_AGENT_ENGINE_ASYNC_STREAM_QUERY_SCHEMA = _agent_engines_utils._generate_schema( AsyncStreamQueryEngine().async_stream_query, schema_name=_TEST_DEFAULT_ASYNC_STREAM_METHOD_NAME, ) -_TEST_AGENT_ENGINE_ASYNC_STREAM_QUERY_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_ASYNC_STREAM_API_MODE -) +_TEST_AGENT_ENGINE_ASYNC_STREAM_QUERY_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_ASYNC_STREAM_API_MODE _TEST_AGENT_ENGINE_CUSTOM_ASYNC_STREAM_QUERY_SCHEMA = ( _agent_engines_utils._generate_schema( OperationRegistrableEngine().custom_async_stream_method, schema_name=_TEST_CUSTOM_ASYNC_STREAM_METHOD_NAME, ) ) -_TEST_AGENT_ENGINE_CUSTOM_ASYNC_STREAM_QUERY_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_ASYNC_STREAM_API_MODE -) +_TEST_AGENT_ENGINE_CUSTOM_ASYNC_STREAM_QUERY_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_ASYNC_STREAM_API_MODE _TEST_AGENT_ENGINE_BIDI_STREAM_QUERY_SCHEMA = _agent_engines_utils._generate_schema( OperationRegistrableEngine().bidi_stream_query, schema_name=_TEST_DEFAULT_BIDI_STREAM_METHOD_NAME, ) -_TEST_AGENT_ENGINE_BIDI_STREAM_QUERY_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_BIDI_STREAM_API_MODE -) +_TEST_AGENT_ENGINE_BIDI_STREAM_QUERY_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_BIDI_STREAM_API_MODE _TEST_AGENT_ENGINE_CUSTOM_BIDI_STREAM_QUERY_SCHEMA = ( _agent_engines_utils._generate_schema( OperationRegistrableEngine().custom_bidi_stream_method, schema_name=_TEST_CUSTOM_BIDI_STREAM_METHOD_NAME, ) ) -_TEST_AGENT_ENGINE_CUSTOM_BIDI_STREAM_QUERY_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_BIDI_STREAM_API_MODE -) +_TEST_AGENT_ENGINE_CUSTOM_BIDI_STREAM_QUERY_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_BIDI_STREAM_API_MODE _TEST_OPERATION_REGISTRABLE_SCHEMAS = [ _TEST_AGENT_ENGINE_QUERY_SCHEMA, _TEST_AGENT_ENGINE_CUSTOM_METHOD_SCHEMA, @@ -657,9 +657,9 @@ def register_operations(self) -> Dict[str, List[str]]: MethodToBeUnregisteredEngine().method_to_be_unregistered, schema_name=_TEST_METHOD_TO_BE_UNREGISTERED_NAME, ) -_TEST_METHOD_TO_BE_UNREGISTERED_SCHEMA[_TEST_MODE_KEY_IN_SCHEMA] = ( - _TEST_STANDARD_API_MODE -) +_TEST_METHOD_TO_BE_UNREGISTERED_SCHEMA[ + _TEST_MODE_KEY_IN_SCHEMA +] = _TEST_STANDARD_API_MODE _TEST_ASYNC_QUERY_SCHEMAS = [_TEST_AGENT_ENGINE_ASYNC_METHOD_SCHEMA] _TEST_STREAM_QUERY_SCHEMAS = [ _TEST_AGENT_ENGINE_STREAM_QUERY_SCHEMA, @@ -1113,6 +1113,63 @@ def test_create_agent_engine_config_with_developer_connect_source(self): == _TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT ) + def test_create_agent_engine_config_with_agent_config_source_and_requirements_file( + self, + ): + with tempfile.TemporaryDirectory() as tmpdir: + requirements_file_path = os.path.join(tmpdir, "requirements.txt") + with open(requirements_file_path, "w") as f: + f.write("requests==2.0.0") + + config = self.client.agent_engines._create_config( + mode="create", + display_name=_TEST_AGENT_ENGINE_DISPLAY_NAME, + description=_TEST_AGENT_ENGINE_DESCRIPTION, + class_methods=_TEST_AGENT_ENGINE_CLASS_METHODS, + agent_framework=_TEST_AGENT_FRAMEWORK, + identity_type=_TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT, + python_version=_TEST_PYTHON_VERSION_OVERRIDE, + agent_config_source={"adk_config": {"json_config": {}}}, + requirements_file=requirements_file_path, + ) + + assert config["spec"]["source_code_spec"] == { + "agent_config_source": {"adk_config": {"json_config": {}}}, + "python_spec": { + "version": _TEST_PYTHON_VERSION_OVERRIDE, + "requirements_file": requirements_file_path, + }, + } + + def test_create_agent_engine_config_with_agent_config_source_and_entrypoint_module_warns( + self, caplog + ): + caplog.set_level(logging.WARNING, logger="vertexai_genai.agentengines") + + config = self.client.agent_engines._create_config( + mode="create", + display_name=_TEST_AGENT_ENGINE_DISPLAY_NAME, + description=_TEST_AGENT_ENGINE_DESCRIPTION, + class_methods=_TEST_AGENT_ENGINE_CLASS_METHODS, + agent_framework=_TEST_AGENT_FRAMEWORK, + identity_type=_TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT, + python_version=_TEST_PYTHON_VERSION_OVERRIDE, + agent_config_source={"adk_config": {"json_config": {}}}, + entrypoint_module="some_module", + ) + + assert ( + "`entrypoint_module` and `entrypoint_object` are ignored when" + in caplog.text + ) + assert config["spec"]["source_code_spec"] == { + "agent_config_source": {"adk_config": {"json_config": {}}}, + "python_spec": { + "version": _TEST_PYTHON_VERSION_OVERRIDE, + }, + } + # entrypoint_module is NOT in python_spec + @mock.patch.object( _agent_engines_utils, "_create_base64_encoded_tarball", @@ -1146,6 +1203,106 @@ def test_create_agent_engine_config_with_source_packages_and_image_spec_raises( ) assert "`image_spec` cannot be specified alongside" in str(excinfo.value) + @mock.patch.object( + _agent_engines_utils, + "_create_base64_encoded_tarball", + return_value="test_tarball", + ) + def test_create_agent_engine_config_with_agent_config_source_and_image_spec_raises( + self, mock_create_base64_encoded_tarball + ): + with tempfile.TemporaryDirectory() as tmpdir: + test_file_path = os.path.join(tmpdir, "test_file.txt") + with open(test_file_path, "w") as f: + f.write("test content") + requirements_file_path = os.path.join(tmpdir, "requirements.txt") + with open(requirements_file_path, "w") as f: + f.write("requests==2.0.0") + + with pytest.raises(ValueError) as excinfo: + self.client.agent_engines._create_config( + mode="create", + display_name=_TEST_AGENT_ENGINE_DISPLAY_NAME, + description=_TEST_AGENT_ENGINE_DESCRIPTION, + class_methods=_TEST_AGENT_ENGINE_CLASS_METHODS, + agent_framework=_TEST_AGENT_FRAMEWORK, + identity_type=_TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT, + python_version=_TEST_PYTHON_VERSION_OVERRIDE, + image_spec={}, + agent_config_source={"adk_config": {"json_config": {}}}, + ) + assert "`image_spec` cannot be specified alongside" in str(excinfo.value) + + def test_create_agent_engine_config_with_agent_config_source(self): + config = self.client.agent_engines._create_config( + mode="create", + display_name=_TEST_AGENT_ENGINE_DISPLAY_NAME, + description=_TEST_AGENT_ENGINE_DESCRIPTION, + class_methods=_TEST_AGENT_ENGINE_CLASS_METHODS, + agent_framework=_TEST_AGENT_FRAMEWORK, + identity_type=_TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT, + python_version=_TEST_PYTHON_VERSION_OVERRIDE, + agent_config_source={"adk_config": {"json_config": {}}}, + ) + assert config["display_name"] == _TEST_AGENT_ENGINE_DISPLAY_NAME + assert config["description"] == _TEST_AGENT_ENGINE_DESCRIPTION + assert config["spec"]["agent_framework"] == _TEST_AGENT_FRAMEWORK + assert config["spec"]["source_code_spec"] == { + "agent_config_source": {"adk_config": {"json_config": {}}}, + "python_spec": {"version": _TEST_PYTHON_VERSION_OVERRIDE}, + } + assert config["spec"]["class_methods"] == _TEST_AGENT_ENGINE_CLASS_METHODS + assert ( + config["spec"]["identity_type"] + == _TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT + ) + + @mock.patch.object( + _agent_engines_utils, + "_create_base64_encoded_tarball", + return_value="test_tarball", + ) + def test_create_agent_engine_config_with_source_packages_and_agent_config_source( + self, mock_create_base64_encoded_tarball + ): + with tempfile.TemporaryDirectory() as tmpdir: + test_file_path = os.path.join(tmpdir, "test_file.txt") + with open(test_file_path, "w") as f: + f.write("test content") + requirements_file_path = os.path.join(tmpdir, "requirements.txt") + with open(requirements_file_path, "w") as f: + f.write("requests==2.0.0") + + config = self.client.agent_engines._create_config( + mode="create", + display_name=_TEST_AGENT_ENGINE_DISPLAY_NAME, + description=_TEST_AGENT_ENGINE_DESCRIPTION, + source_packages=[test_file_path], + class_methods=_TEST_AGENT_ENGINE_CLASS_METHODS, + agent_framework=_TEST_AGENT_FRAMEWORK, + identity_type=_TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT, + python_version=_TEST_PYTHON_VERSION_OVERRIDE, + agent_config_source={"adk_config": {"json_config": {}}}, + ) + assert config["display_name"] == _TEST_AGENT_ENGINE_DISPLAY_NAME + assert config["description"] == _TEST_AGENT_ENGINE_DESCRIPTION + assert config["spec"]["agent_framework"] == _TEST_AGENT_FRAMEWORK + assert config["spec"]["source_code_spec"] == { + "agent_config_source": { + "adk_config": {"json_config": {}}, + "inline_source": {"source_archive": "test_tarball"}, + }, + "python_spec": {"version": _TEST_PYTHON_VERSION_OVERRIDE}, + } + assert config["spec"]["class_methods"] == _TEST_AGENT_ENGINE_CLASS_METHODS + mock_create_base64_encoded_tarball.assert_called_once_with( + source_packages=[test_file_path] + ) + assert ( + config["spec"]["identity_type"] + == _TEST_AGENT_ENGINE_IDENTITY_TYPE_SERVICE_ACCOUNT + ) + @mock.patch.object( _agent_engines_utils, "_create_base64_encoded_tarball", @@ -1916,6 +2073,7 @@ def test_create_agent_engine_with_env_vars_dict( python_version=None, build_options=None, image_spec=None, + agent_config_source=None, ) request_mock.assert_called_with( "post", @@ -2018,6 +2176,7 @@ def test_create_agent_engine_with_custom_service_account( python_version=None, build_options=None, image_spec=None, + agent_config_source=None, ) request_mock.assert_called_with( "post", @@ -2119,6 +2278,7 @@ def test_create_agent_engine_with_experimental_mode( python_version=None, build_options=None, image_spec=None, + agent_config_source=None, ) request_mock.assert_called_with( "post", @@ -2289,6 +2449,7 @@ def test_create_agent_engine_with_class_methods( python_version=None, build_options=None, image_spec=None, + agent_config_source=None, ) request_mock.assert_called_with( "post", @@ -2385,6 +2546,7 @@ def test_create_agent_engine_with_agent_framework( python_version=None, build_options=None, image_spec=None, + agent_config_source=None, ) request_mock.assert_called_with( "post", diff --git a/vertexai/_genai/agent_engines.py b/vertexai/_genai/agent_engines.py index 23fcf2ecf9..6a0113ccd2 100644 --- a/vertexai/_genai/agent_engines.py +++ b/vertexai/_genai/agent_engines.py @@ -786,7 +786,12 @@ def _list_pager( def _is_lightweight_creation( self, agent: Any, config: types.AgentEngineConfig ) -> bool: - if agent or config.source_packages or config.developer_connect_source: + if ( + agent + or config.source_packages + or config.developer_connect_source + or config.agent_config_source + ): return False return True @@ -937,6 +942,9 @@ def create( developer_connect_source = json.loads( developer_connect_source.model_dump_json() ) + agent_config_source = config.agent_config_source + if agent_config_source is not None: + agent_config_source = json.loads(agent_config_source.model_dump_json()) if agent and agent_engine: raise ValueError("Please specify only one of `agent` or `agent_engine`.") elif agent_engine: @@ -975,6 +983,7 @@ def create( python_version=config.python_version, build_options=config.build_options, image_spec=config.image_spec, + agent_config_source=agent_config_source, ) operation = self._create(config=api_config) reasoning_engine_id = _agent_engines_utils._get_reasoning_engine_id( @@ -1034,10 +1043,13 @@ def _set_source_code_spec( image_spec: Optional[ types.ReasoningEngineSpecSourceCodeSpecImageSpecDict ] = None, + agent_config_source: Optional[ + types.ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict + ] = None, ) -> None: """Sets source_code_spec for agent engine inside the `spec`.""" source_code_spec = types.ReasoningEngineSpecSourceCodeSpecDict() - if source_packages: + if source_packages and not agent_config_source: source_packages = _agent_engines_utils._validate_packages_or_raise( packages=source_packages, build_options=build_options, @@ -1053,13 +1065,15 @@ def _set_source_code_spec( source_code_spec["developer_connect_source"] = { "config": developer_connect_source } - else: + elif not agent_config_source: raise ValueError( - "Please specify one of `source_packages` or `developer_connect_source`." + "Please specify one of `source_packages`, `developer_connect_source`, " + "or `agent_config_source`." ) if class_methods is None: raise ValueError( - "`class_methods` must be specified if `source_packages` or `developer_connect_source` is specified." + "`class_methods` must be specified if `source_packages`, " + "`developer_connect_source`, or `agent_config_source` is specified." ) update_masks.append("spec.class_methods") class_methods_spec_list = ( @@ -1078,13 +1092,55 @@ def _set_source_code_spec( "`entrypoint_object`, or `requirements_file`, as they are " "mutually exclusive." ) + if agent_config_source: + raise ValueError( + "`image_spec` cannot be specified alongside `agent_config_source`, " + "as they are mutually exclusive." + ) update_masks.append("spec.source_code_spec.image_spec") source_code_spec["image_spec"] = image_spec spec["source_code_spec"] = source_code_spec return + if agent_config_source is not None: + if entrypoint_module or entrypoint_object: + logger.warning( + "`entrypoint_module` and `entrypoint_object` are ignored when " + "`agent_config_source` is specified, as they are pre-defined." + ) + if source_packages: + source_packages = _agent_engines_utils._validate_packages_or_raise( + packages=source_packages, + build_options=build_options, + ) + inline_source = agent_config_source.get("inline_source") + if inline_source is None: + inline_source = {} + agent_config_source["inline_source"] = inline_source + inline_source["source_archive"] = ( + _agent_engines_utils._create_base64_encoded_tarball( + source_packages=source_packages + ) + ) + update_masks.append("spec.source_code_spec.agent_config_source") + source_code_spec["agent_config_source"] = agent_config_source + + update_masks.append("spec.source_code_spec.python_spec.version") + python_spec = { + "version": sys_version, + } + if requirements_file is not None: + update_masks.append( + "spec.source_code_spec.python_spec.requirements_file" + ) + python_spec["requirements_file"] = requirements_file + source_code_spec["python_spec"] = python_spec + + spec["source_code_spec"] = source_code_spec + return + update_masks.append("spec.source_code_spec.python_spec.version") - python_spec: types.ReasoningEngineSpecSourceCodeSpecPythonSpecDict = { + python_spec = { "version": sys_version, } if not entrypoint_module: @@ -1235,6 +1291,9 @@ def _create_config( image_spec: Optional[ types.ReasoningEngineSpecSourceCodeSpecImageSpecDict ] = None, + agent_config_source: Optional[ + types.ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict + ] = None, ) -> types.UpdateAgentEngineConfigDict: import sys @@ -1307,7 +1366,12 @@ def _create_config( sys_version=sys_version, build_options=build_options, ) - elif source_packages or developer_connect_source: + elif ( + source_packages + or developer_connect_source + or image_spec + or agent_config_source + ): agent_engine_spec = {} self._set_source_code_spec( spec=agent_engine_spec, @@ -1321,6 +1385,7 @@ def _create_config( sys_version=sys_version, build_options=build_options, image_spec=image_spec, + agent_config_source=agent_config_source, ) is_deployment_spec_updated = ( @@ -1336,7 +1401,8 @@ def _create_config( "To update `env_vars`, `psc_interface_config`, `min_instances`, " "`max_instances`, `resource_limits`, or `container_concurrency`, " "you must also provide the `agent` variable or the source code " - "options (`source_packages` or `developer_connect_source`)." + "options (`source_packages`, `developer_connect_source` or " + "`agent_config_source`)." ) if agent_engine_spec is not None: @@ -1598,6 +1664,9 @@ def update( developer_connect_source = json.loads( developer_connect_source.model_dump_json() ) + agent_config_source = config.agent_config_source + if agent_config_source is not None: + agent_config_source = json.loads(agent_config_source.model_dump_json()) if agent and agent_engine: raise ValueError("Please specify only one of `agent` or `agent_engine`.") elif agent_engine: @@ -1633,6 +1702,7 @@ def update( agent_framework=config.agent_framework, python_version=config.python_version, build_options=config.build_options, + agent_config_source=agent_config_source, ) operation = self._update(name=name, config=api_config) reasoning_engine_id = _agent_engines_utils._get_reasoning_engine_id( diff --git a/vertexai/_genai/types/__init__.py b/vertexai/_genai/types/__init__.py index e1d4e73d23..5eff899c3a 100644 --- a/vertexai/_genai/types/__init__.py +++ b/vertexai/_genai/types/__init__.py @@ -809,6 +809,12 @@ from .common import ReasoningEngineSpecPackageSpecDict from .common import ReasoningEngineSpecPackageSpecOrDict from .common import ReasoningEngineSpecSourceCodeSpec +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSource +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfig +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigDict +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigOrDict +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict +from .common import ReasoningEngineSpecSourceCodeSpecAgentConfigSourceOrDict from .common import ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfig from .common import ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfigDict from .common import ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfigOrDict @@ -1591,21 +1597,27 @@ "ReasoningEngineSpecPackageSpec", "ReasoningEngineSpecPackageSpecDict", "ReasoningEngineSpecPackageSpecOrDict", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfig", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigDict", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigOrDict", + "ReasoningEngineSpecSourceCodeSpecInlineSource", + "ReasoningEngineSpecSourceCodeSpecInlineSourceDict", + "ReasoningEngineSpecSourceCodeSpecInlineSourceOrDict", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSource", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict", + "ReasoningEngineSpecSourceCodeSpecAgentConfigSourceOrDict", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfig", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfigDict", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfigOrDict", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectSource", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectSourceDict", "ReasoningEngineSpecSourceCodeSpecDeveloperConnectSourceOrDict", - "ReasoningEngineSpecSourceCodeSpecInlineSource", - "ReasoningEngineSpecSourceCodeSpecInlineSourceDict", - "ReasoningEngineSpecSourceCodeSpecInlineSourceOrDict", - "ReasoningEngineSpecSourceCodeSpecPythonSpec", - "ReasoningEngineSpecSourceCodeSpecPythonSpecDict", - "ReasoningEngineSpecSourceCodeSpecPythonSpecOrDict", "ReasoningEngineSpecSourceCodeSpecImageSpec", "ReasoningEngineSpecSourceCodeSpecImageSpecDict", "ReasoningEngineSpecSourceCodeSpecImageSpecOrDict", + "ReasoningEngineSpecSourceCodeSpecPythonSpec", + "ReasoningEngineSpecSourceCodeSpecPythonSpecDict", + "ReasoningEngineSpecSourceCodeSpecPythonSpecOrDict", "ReasoningEngineSpecSourceCodeSpec", "ReasoningEngineSpecSourceCodeSpecDict", "ReasoningEngineSpecSourceCodeSpecOrDict", diff --git a/vertexai/_genai/types/common.py b/vertexai/_genai/types/common.py index 0903178153..d9e37aff44 100644 --- a/vertexai/_genai/types/common.py +++ b/vertexai/_genai/types/common.py @@ -6192,6 +6192,82 @@ class ReasoningEngineSpecPackageSpecDict(TypedDict, total=False): ] +class ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfig(_common.BaseModel): + """Configuration for the Agent Development Kit (ADK).""" + + json_config: Optional[dict[str, Any]] = Field( + default=None, + description="""Required. The value of the ADK config in JSON format.""", + ) + + +class ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigDict( + TypedDict, total=False +): + """Configuration for the Agent Development Kit (ADK).""" + + json_config: Optional[dict[str, Any]] + """Required. The value of the ADK config in JSON format.""" + + +ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigOrDict = Union[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfig, + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigDict, +] + + +class ReasoningEngineSpecSourceCodeSpecInlineSource(_common.BaseModel): + """Specifies source code provided as a byte stream.""" + + source_archive: Optional[bytes] = Field( + default=None, + description="""Required. Input only. The application source code archive, provided as a compressed tarball (.tar.gz) file.""", + ) + + +class ReasoningEngineSpecSourceCodeSpecInlineSourceDict(TypedDict, total=False): + """Specifies source code provided as a byte stream.""" + + source_archive: Optional[bytes] + """Required. Input only. The application source code archive, provided as a compressed tarball (.tar.gz) file.""" + + +ReasoningEngineSpecSourceCodeSpecInlineSourceOrDict = Union[ + ReasoningEngineSpecSourceCodeSpecInlineSource, + ReasoningEngineSpecSourceCodeSpecInlineSourceDict, +] + + +class ReasoningEngineSpecSourceCodeSpecAgentConfigSource(_common.BaseModel): + """Specification for the deploying from agent config.""" + + adk_config: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfig + ] = Field(default=None, description="""Required. The ADK configuration.""") + inline_source: Optional[ReasoningEngineSpecSourceCodeSpecInlineSource] = Field( + default=None, + description="""Optional. Any additional files needed to interpret the config. If a `requirements.txt` file is present in the `inline_source`, the corresponding packages will be installed. If no `requirements.txt` file is present in `inline_source`, then the latest version of `google-adk` will be installed for interpreting the ADK config.""", + ) + + +class ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict(TypedDict, total=False): + """Specification for the deploying from agent config.""" + + adk_config: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceAdkConfigDict + ] + """Required. The ADK configuration.""" + + inline_source: Optional[ReasoningEngineSpecSourceCodeSpecInlineSourceDict] + """Optional. Any additional files needed to interpret the config. If a `requirements.txt` file is present in the `inline_source`, the corresponding packages will be installed. If no `requirements.txt` file is present in `inline_source`, then the latest version of `google-adk` will be installed for interpreting the ADK config.""" + + +ReasoningEngineSpecSourceCodeSpecAgentConfigSourceOrDict = Union[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSource, + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict, +] + + class ReasoningEngineSpecSourceCodeSpecDeveloperConnectConfig(_common.BaseModel): """Specifies the configuration for fetching source code from a Git repository that is managed by Developer Connect. @@ -6260,25 +6336,31 @@ class ReasoningEngineSpecSourceCodeSpecDeveloperConnectSourceDict( ] -class ReasoningEngineSpecSourceCodeSpecInlineSource(_common.BaseModel): - """Specifies source code provided as a byte stream.""" +class ReasoningEngineSpecSourceCodeSpecImageSpec(_common.BaseModel): + """The image spec for building an image (within a single build step). - source_archive: Optional[bytes] = Field( + It is based on the config file (i.e. Dockerfile) in the source directory. + """ + + build_args: Optional[dict[str, str]] = Field( default=None, - description="""Required. Input only. The application source code archive, provided as a compressed tarball (.tar.gz) file.""", + description="""Optional. Build arguments to be used. They will be passed through --build-arg flags.""", ) -class ReasoningEngineSpecSourceCodeSpecInlineSourceDict(TypedDict, total=False): - """Specifies source code provided as a byte stream.""" +class ReasoningEngineSpecSourceCodeSpecImageSpecDict(TypedDict, total=False): + """The image spec for building an image (within a single build step). - source_archive: Optional[bytes] - """Required. Input only. The application source code archive, provided as a compressed tarball (.tar.gz) file.""" + It is based on the config file (i.e. Dockerfile) in the source directory. + """ + build_args: Optional[dict[str, str]] + """Optional. Build arguments to be used. They will be passed through --build-arg flags.""" -ReasoningEngineSpecSourceCodeSpecInlineSourceOrDict = Union[ - ReasoningEngineSpecSourceCodeSpecInlineSource, - ReasoningEngineSpecSourceCodeSpecInlineSourceDict, + +ReasoningEngineSpecSourceCodeSpecImageSpecOrDict = Union[ + ReasoningEngineSpecSourceCodeSpecImageSpec, + ReasoningEngineSpecSourceCodeSpecImageSpecDict, ] @@ -6325,72 +6407,54 @@ class ReasoningEngineSpecSourceCodeSpecPythonSpecDict(TypedDict, total=False): ] -class ReasoningEngineSpecSourceCodeSpecImageSpec(_common.BaseModel): - """The image spec for building an image (within a single build step). - - It is based on the config file (i.e. Dockerfile) in the source directory. - """ - - build_args: Optional[dict[str, str]] = Field( - default=None, - description="""Optional. Build arguments to be used. They will be passed through --build-arg flags.""", - ) - - -class ReasoningEngineSpecSourceCodeSpecImageSpecDict(TypedDict, total=False): - """The image spec for building an image (within a single build step). - - It is based on the config file (i.e. Dockerfile) in the source directory. - """ - - build_args: Optional[dict[str, str]] - """Optional. Build arguments to be used. They will be passed through --build-arg flags.""" - - -ReasoningEngineSpecSourceCodeSpecImageSpecOrDict = Union[ - ReasoningEngineSpecSourceCodeSpecImageSpec, - ReasoningEngineSpecSourceCodeSpecImageSpecDict, -] - - class ReasoningEngineSpecSourceCodeSpec(_common.BaseModel): """Specification for deploying from source code.""" + agent_config_source: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSource + ] = Field( + default=None, description="""Source code is generated from the agent config.""" + ) developer_connect_source: Optional[ ReasoningEngineSpecSourceCodeSpecDeveloperConnectSource ] = Field( default=None, description="""Source code is in a Git repository managed by Developer Connect.""", ) + image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpec] = Field( + default=None, + description="""Optional. Configuration for building an image with custom config file.""", + ) inline_source: Optional[ReasoningEngineSpecSourceCodeSpecInlineSource] = Field( default=None, description="""Source code is provided directly in the request.""" ) python_spec: Optional[ReasoningEngineSpecSourceCodeSpecPythonSpec] = Field( default=None, description="""Configuration for a Python application.""" ) - image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpec] = Field( - default=None, - description="""Optional. Configuration for building an image with custom config file.""", - ) class ReasoningEngineSpecSourceCodeSpecDict(TypedDict, total=False): """Specification for deploying from source code.""" + agent_config_source: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict + ] + """Source code is generated from the agent config.""" + developer_connect_source: Optional[ ReasoningEngineSpecSourceCodeSpecDeveloperConnectSourceDict ] """Source code is in a Git repository managed by Developer Connect.""" + image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpecDict] + """Optional. Configuration for building an image with custom config file.""" + inline_source: Optional[ReasoningEngineSpecSourceCodeSpecInlineSourceDict] """Source code is provided directly in the request.""" python_spec: Optional[ReasoningEngineSpecSourceCodeSpecPythonSpecDict] """Configuration for a Python application.""" - image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpecDict] - """Optional. Configuration for building an image with custom config file.""" - ReasoningEngineSpecSourceCodeSpecOrDict = Union[ ReasoningEngineSpecSourceCodeSpec, ReasoningEngineSpecSourceCodeSpecDict @@ -15291,6 +15355,11 @@ class AgentEngineConfig(_common.BaseModel): image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpec] = Field( default=None, description="""The image spec for the Agent Engine.""" ) + agent_config_source: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSource + ] = Field( + default=None, description="""The agent config source for the Agent Engine.""" + ) class AgentEngineConfigDict(TypedDict, total=False): @@ -15457,6 +15526,11 @@ class AgentEngineConfigDict(TypedDict, total=False): image_spec: Optional[ReasoningEngineSpecSourceCodeSpecImageSpecDict] """The image spec for the Agent Engine.""" + agent_config_source: Optional[ + ReasoningEngineSpecSourceCodeSpecAgentConfigSourceDict + ] + """The agent config source for the Agent Engine.""" + AgentEngineConfigOrDict = Union[AgentEngineConfig, AgentEngineConfigDict]