diff --git a/modules/agent-engine/README.md b/modules/agent-engine/README.md index f886a4972..eba288e52 100644 --- a/modules/agent-engine/README.md +++ b/modules/agent-engine/README.md @@ -2,13 +2,16 @@ The module creates Agent Engine and related dependencies. -- It can automatically generate and update the Pickle file for you, given a source file. -- It optionally creates a GCS storage bucket or can use an existing one and loads on it all your dependencies (`pickle`, `dependencies.tar.gz`, `requirements.txt`) -- Manages the service accounts lifecycle +- It supports both source based deployments (aka in-line deployment) and serialized object deployment (aka pickle deployment). +- For serialized object deployment, it optionally creates a GCS storage bucket or can use an existing one and loads on it all your dependencies (`pickle`, `dependencies.tar.gz`, `requirements.txt`). +- Manages custom service accounts lifecycle. -- [Packaging dependencies](#packaging-dependencies) -- [Minimal deployment](#minimal-deployment) +- [Source based deployment](#source-based-deployment) + - [Create the tar.gz package](#create-the-targz-package) + - [Minimal deployment](#minimal-deployment) +- [Serialized Object Deployment](#serialized-object-deployment) + - [Unmanaged deployments](#unmanaged-deployments) - [Service accounts](#service-accounts) - [Specify an encryption key](#specify-an-encryption-key) - [Define environment variables and use secrets](#define-environment-variables-and-use-secrets) @@ -17,20 +20,20 @@ The module creates Agent Engine and related dependencies. - [Outputs](#outputs) -## Packaging dependencies +## Source based deployment -To deploy an agent, you first need package your dependencies. This consists of a folder with +The source based deployment is the newest, most efficient and easiest way to deploy your agents. -- The source Python file defining your agent to be pickled (or the equivalent pickle file). -- The `dependencies.tar.gz`. +### Create the tar.gz package + +First, create a *tar.gz* file with these files: + +- The source Python file defining your agent, called `agent.py`. - The `requirements.txt` file. -By default, the module expects these files to be in an `src` subfolder. +By default, the module expects the `tar.gz` file to be in the `src` subfolder and to be called `source.tar.gz`. -You can decide to **let the module create the pickle file for you**, starting from a source agent file. -In this case, the module expects you to have in `src` a source file called `agent.py` with a variable referencing your agent function definition called `local_agent`. - -This is an example of `agent.py` file for ADK: +This is an example of an `agent.py` file for ADK: ```python from google.adk.agents import LlmAgent @@ -55,19 +58,12 @@ root_agent = LlmAgent( tools=[get_exchange_rate], ) -local_agent = AdkApp(agent=root_agent) +agent = AdkApp(agent=root_agent) ``` -The [tools/serialize_agent.py](tools/serialize_agent.py) is used to generate the `pickle.pkl` file. -You module needs [these packages](tools/requirements.txt) to work. +### Minimal deployment -If you **already have a pickle file**, the module expects you to have in the `src` subfolder a `pickle.pkl` file. - -You can customize these values by using the `source_files` variable. - -## Minimal deployment - -This example assumes you are providing the [source packages](#packaging-dependencies) (`agent.py`, `dependencies.tar.gz` and `requirements.txt`) in the `src` subfolder. Every time you will change the agent definition, the module will generate the new pickle file for you, will update it on the GCS bucket and will update your agent. +You can now deploy the agent. ```hcl module "agent_engine" { @@ -80,34 +76,71 @@ module "agent_engine" { agent_framework = "google-adk" } - source_files = { - path = "assets/src/" + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } } } # tftest inventory=minimal.yaml ``` -Alternatively, you can pass a pre-generated `pickle.pkl` file. +You can change the name of the tar.gz package, of the requirement file, the name of the Python file and the name of the agent function by using the `deployment_files.source_config` variable. + +## Serialized Object Deployment + +You can also manually serialize your agent by using the [cloudpickle library](https://github.com/cloudpipe/cloudpickle) and pass the `pickle.pkl`, `dependencies.tar.gz` and `requirements.txt` files to the module. ```hcl module "agent_engine" { - source = "./fabric/modules/agent-engine" - name = "my-agent" - project_id = var.project_id - region = var.region - generate_pickle = false + source = "./fabric/modules/agent-engine" + name = "my-agent" + project_id = var.project_id + region = var.region agent_engine_config = { agent_framework = "google-adk" } - source_files = { - path = "assets/src/" + deployment_files = { + package_config = { + dependencies_path = "assets/src/dependencies.tar.gz" + pickle_path = "assets/src/pickle.pkl" + requirements_path = "assets/src/requirements.txt" + } + source_config = null } } # tftest inventory=minimal-pickle.yaml ``` +### Unmanaged deployments + +By default, this module tracks and controls code updates. This means you can only the agent code via Terraform. +Anyway, you may want to delegate this operation to third-party tools, outside Terraform. +To do so, deploy the first revision of your code by using the module (this can even be a hello world) and set `var.managed` to `false`. + +```hcl +module "agent_engine" { + source = "./fabric/modules/agent-engine" + name = "my-agent" + project_id = var.project_id + region = var.region + managed = false + + agent_engine_config = { + agent_framework = "google-adk" + } + + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } + } +} +# tftest inventory=unmanaged.yaml +``` + ## Service accounts By default, the module creates a dedicated service account for your agent and grants it the roles needed to deploy the agent. The default roles are defined in `var.service_account_config.roles`. You can add more roles, as needed. @@ -131,8 +164,10 @@ module "agent_engine" { create = false } - source_files = { - path = "assets/src/" + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } } } # tftest inventory=sa-default.yaml @@ -156,8 +191,10 @@ module "agent_engine" { email = "my-sa@${var.project_id}.iam.gserviceaccount.com" } - source_files = { - path = "assets/src/" + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } } } # tftest inventory=sa-custom.yaml @@ -181,8 +218,10 @@ module "agent_engine" { agent_framework = "google-adk" } - source_files = { - path = "assets/src/" + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } } } # tftest inventory=encryption.yaml @@ -212,8 +251,10 @@ module "agent_engine" { } } - source_files = { - path = "assets/src/" + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } } } # tftest inventory=environment.yaml @@ -227,22 +268,23 @@ The module allows you to dynamically reference context values for resources crea | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [agent_engine_config](variables.tf#L17) | The agent configuration. | object({…}) | ✓ | | -| [name](variables.tf#L77) | The name of the agent. | string | ✓ | | -| [project_id](variables.tf#L83) | The id of the project where to deploy the agent. | string | ✓ | | -| [region](variables.tf#L89) | The region where to deploy the agent. | string | ✓ | | -| [bucket_config](variables.tf#L32) | The GCS bucket configuration. | object({…}) | | {} | -| [context](variables.tf#L44) | Context-specific interpolations. | object({…}) | | {} | -| [description](variables.tf#L57) | The Agent Engine description. | string | | "Terraform managed." | -| [encryption_key](variables.tf#L64) | The full resource name of the Cloud KMS CryptoKey. | string | | null | -| [generate_pickle](variables.tf#L70) | Generate the pickle file from a source file. | bool | | true | +| [agent_engine_config](variables.tf#L17) | The agent configuration. | object({…}) | ✓ | | +| [name](variables.tf#L121) | The name of the agent. | string | ✓ | | +| [project_id](variables.tf#L127) | The id of the project where to deploy the agent. | string | ✓ | | +| [region](variables.tf#L133) | The region where to deploy the agent. | string | ✓ | | +| [bucket_config](variables.tf#L40) | The GCS bucket configuration. | object({…}) | | {} | +| [context](variables.tf#L52) | Context-specific interpolations. | object({…}) | | {} | +| [deployment_files](variables.tf#L65) | The to source files path and names. | object({…}) | | {…} | +| [description](variables.tf#L101) | The Agent Engine description. | string | | "Terraform managed." | +| [encryption_key](variables.tf#L108) | The full resource name of the Cloud KMS CryptoKey. | string | | null | +| [managed](variables.tf#L114) | Whether the Terraform module should control the code updates. | bool | | true | | [service_account_config](variables-serviceaccount.tf#L18) | Service account configurations. | object({…}) | | {} | -| [source_files](variables.tf#L95) | The to source files path and names. | object({…}) | | {} | ## Outputs | name | description | sensitive | |---|---|:---:| -| [id](outputs.tf#L17) | Fully qualified Agent Engine id. | | -| [service_account](outputs.tf#L22) | Service account resource. | | +| [agent](outputs.tf#L17) | The Agent Engine object. | | +| [id](outputs.tf#L22) | Fully qualified Agent Engine id. | | +| [service_account](outputs.tf#L27) | Service account resource. | | diff --git a/modules/agent-engine/agent-managed.tf b/modules/agent-engine/agent-managed.tf new file mode 100644 index 000000000..5c1a10948 --- /dev/null +++ b/modules/agent-engine/agent-managed.tf @@ -0,0 +1,115 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +resource "google_vertex_ai_reasoning_engine" "managed" { + count = var.managed ? 1 : 0 + display_name = var.name + project = local.project_id + description = var.description + region = local.location + + dynamic "encryption_spec" { + for_each = var.encryption_key == null ? {} : { 1 = 1 } + + content { + kms_key_name = lookup( + local.ctx.kms_keys, + var.encryption_key, + var.encryption_key + ) + } + } + + spec { + agent_framework = var.agent_engine_config.agent_framework + class_methods = ( + length(var.agent_engine_config.class_methods) > 0 + ? jsonencode(var.agent_engine_config.class_methods) + : null + ) + service_account = local.service_account_email + + dynamic "deployment_spec" { + for_each = ( + var.agent_engine_config.container_concurrency != null || + var.agent_engine_config.max_instances != null || + var.agent_engine_config.min_instances != null || + var.agent_engine_config.resource_limits != null || + length(var.agent_engine_config.environment_variables) > 0 || + length(var.agent_engine_config.secret_environment_variables) > 0 + ? { 1 = 1 } + : {} + ) + + content { + container_concurrency = var.agent_engine_config.container_concurrency + max_instances = var.agent_engine_config.max_instances + min_instances = var.agent_engine_config.min_instances + resource_limits = var.agent_engine_config.resource_limits + + dynamic "env" { + for_each = var.agent_engine_config.environment_variables + + content { + name = env.key + value = env.value + } + } + + dynamic "secret_env" { + for_each = var.agent_engine_config.secret_environment_variables + + content { + name = secret_env.key + + secret_ref { + secret = secret_env.value.secret_id + version = secret_env.value.version + } + } + } + } + } + + dynamic "package_spec" { + for_each = var.deployment_files.package_config != null ? { 1 = 1 } : {} + + content { + python_version = var.agent_engine_config.python_version + dependency_files_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" + requirements_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" + pickle_object_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + } + } + + dynamic "source_code_spec" { + for_each = var.deployment_files.source_config != null ? { 1 = 1 } : {} + + content { + inline_source { + source_archive = filebase64(var.deployment_files.source_config.source_path) + } + + python_spec { + entrypoint_module = var.deployment_files.source_config.entrypoint_module + entrypoint_object = var.deployment_files.source_config.entrypoint_object + requirements_file = var.deployment_files.source_config.requirements_path + version = var.agent_engine_config.python_version + } + } + } + } +} diff --git a/modules/agent-engine/agent-unmanaged.tf b/modules/agent-engine/agent-unmanaged.tf new file mode 100644 index 000000000..9c7b5260d --- /dev/null +++ b/modules/agent-engine/agent-unmanaged.tf @@ -0,0 +1,122 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +resource "google_vertex_ai_reasoning_engine" "unmanaged" { + count = var.managed ? 0 : 1 + display_name = var.name + project = local.project_id + description = var.description + region = local.location + + dynamic "encryption_spec" { + for_each = var.encryption_key == null ? {} : { 1 = 1 } + + content { + kms_key_name = lookup( + local.ctx.kms_keys, + var.encryption_key, + var.encryption_key + ) + } + } + + spec { + agent_framework = var.agent_engine_config.agent_framework + class_methods = ( + length(var.agent_engine_config.class_methods) > 0 + ? jsonencode(var.agent_engine_config.class_methods) + : null + ) + service_account = local.service_account_email + + dynamic "deployment_spec" { + for_each = ( + var.agent_engine_config.container_concurrency != null || + var.agent_engine_config.max_instances != null || + var.agent_engine_config.min_instances != null || + var.agent_engine_config.resource_limits != null || + length(var.agent_engine_config.environment_variables) > 0 || + length(var.agent_engine_config.secret_environment_variables) > 0 + ? { 1 = 1 } + : {} + ) + + content { + container_concurrency = var.agent_engine_config.container_concurrency + max_instances = var.agent_engine_config.max_instances + min_instances = var.agent_engine_config.min_instances + resource_limits = var.agent_engine_config.resource_limits + + dynamic "env" { + for_each = var.agent_engine_config.environment_variables + + content { + name = env.key + value = env.value + } + } + + dynamic "secret_env" { + for_each = var.agent_engine_config.secret_environment_variables + + content { + name = secret_env.key + + secret_ref { + secret = secret_env.value.secret_id + version = secret_env.value.version + } + } + } + } + } + + dynamic "package_spec" { + for_each = var.deployment_files.package_config == null ? {} : { 1 = 1 } + + content { + python_version = var.agent_engine_config.python_version + dependency_files_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" + requirements_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" + pickle_object_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + } + } + + dynamic "source_code_spec" { + for_each = var.deployment_files.source_config == null ? {} : { 1 = 1 } + + content { + inline_source { + source_archive = filebase64(var.deployment_files.source_config.source_path) + } + + python_spec { + entrypoint_module = var.deployment_files.source_config.entrypoint_module + entrypoint_object = var.deployment_files.source_config.entrypoint_object + requirements_file = var.deployment_files.source_config.requirements_path + version = var.agent_engine_config.python_version + } + } + } + } + + lifecycle { + ignore_changes = [ + spec[0].package_spec, + spec[0].source_code_spec[0].inline_source[0].source_archive + ] + } +} diff --git a/modules/agent-engine/main.tf b/modules/agent-engine/main.tf index a50c42c27..a700778c8 100644 --- a/modules/agent-engine/main.tf +++ b/modules/agent-engine/main.tf @@ -16,8 +16,13 @@ locals { _ctx_p = "$" + _resource = ( + var.managed + ? try(google_vertex_ai_reasoning_engine.managed[0], null) + : try(google_vertex_ai_reasoning_engine.unmanaged[0], null) + ) bucket_name = ( - var.bucket_config.create + var.deployment_files.package_config != null && var.bucket_config.create ? google_storage_bucket.default[0].name : coalesce(var.bucket_config.name, var.name) ) @@ -32,79 +37,9 @@ locals { project_id = lookup( local.ctx.project_ids, var.project_id, var.project_id ) -} - -resource "google_vertex_ai_reasoning_engine" "default" { - display_name = var.name - project = local.project_id - description = var.description - region = local.location - - dynamic "encryption_spec" { - for_each = var.encryption_key == null ? {} : { 1 = 1 } - - content { - kms_key_name = lookup( - local.ctx.kms_keys, - var.encryption_key, - var.encryption_key - ) - } - } - - spec { - agent_framework = var.agent_engine_config.agent_framework - class_methods = ( - length(var.agent_engine_config.class_methods) > 0 - ? jsonencode(var.agent_engine_config.class_methods) - : null - ) - service_account = local.service_account_email - - dynamic "deployment_spec" { - for_each = ( - # length(var.container_spec) > 0 || - length(var.agent_engine_config.environment_variables) > 0 || - length(var.agent_engine_config.secret_environment_variables) > 0 - ? { 1 = 1 } - : {} - ) - - content { - dynamic "env" { - for_each = var.agent_engine_config.environment_variables - - content { - name = env.key - value = env.value - } - } - - dynamic "secret_env" { - for_each = var.agent_engine_config.secret_environment_variables - - content { - name = secret_env.key - - secret_ref { - secret = secret_env.value.secret_id - version = secret_env.value.version - } - } - } - } - } - - package_spec { - python_version = var.agent_engine_config.python_version - dependency_files_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies.name}" - requirements_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.requirements.name}" - pickle_object_gcs_uri = ( - var.generate_pickle - ? "gs://${local.bucket_name}/${google_storage_bucket_object.pickle_from_src[0].name}" - : "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" - ) - } + resource = { + id = local._resource.id + object = local._resource } } @@ -119,7 +54,11 @@ resource "time_sleep" "wait_5_minutes" { } resource "google_storage_bucket" "default" { - count = var.bucket_config.create ? 1 : 0 + count = ( + var.bucket_config.create + && var.deployment_files.package_config != null + ? 1 : 0 + ) name = coalesce(var.bucket_config.name, var.name) project = local.project_id location = local.location @@ -127,50 +66,32 @@ resource "google_storage_bucket" "default" { force_destroy = !var.bucket_config.deletion_protection } -resource "null_resource" "default" { - count = var.generate_pickle ? 1 : 0 - - provisioner "local-exec" { - command = join(" ", [ - "python", - "./tools/serialize_agent.py", - "${var.source_files.path}/${var.source_files.pickle_src}", - "--output-file ${var.source_files.path}/${var.source_files.pickle_out}", - "--variable-name ${var.source_files.pickle_src_var_name}" - ]) - } -} - resource "google_storage_bucket_object" "dependencies" { - name = "dependencies.tar.gz" - bucket = local.bucket_name - source = "${var.source_files.path}/${var.source_files.dependencies}" - source_md5hash = filemd5("${var.source_files.path}/${var.source_files.dependencies}") -} - -resource "google_storage_bucket_object" "pickle_from_src" { - count = var.generate_pickle ? 1 : 0 - name = "pickle.pkl" - bucket = local.bucket_name - source = "${var.source_files.path}/${var.source_files.pickle_out}" - source_md5hash = filemd5("${var.source_files.path}/${var.source_files.pickle_out}") - - depends_on = [ - null_resource.default - ] + count = var.deployment_files.package_config != null ? 1 : 0 + name = "dependencies.tar.gz" + bucket = local.bucket_name + source = try(var.deployment_files.package_config.dependencies_path, null) + source_md5hash = filemd5( + try(var.deployment_files.package_config.dependencies_path, null) + ) } resource "google_storage_bucket_object" "pickle" { - count = var.generate_pickle ? 0 : 1 - name = "pickle.pkl" - bucket = local.bucket_name - source = "${var.source_files.path}/${var.source_files.pickle_out}" - source_md5hash = filemd5("${var.source_files.path}/${var.source_files.pickle_out}") + count = var.deployment_files.package_config != null ? 1 : 0 + name = "pickle.pkl" + bucket = local.bucket_name + source = try(var.deployment_files.package_config.pickle_path, null) + source_md5hash = filemd5( + try(var.deployment_files.package_config.pickle_path) + ) } resource "google_storage_bucket_object" "requirements" { - name = "requirements.txt" - bucket = local.bucket_name - source = "${var.source_files.path}/${var.source_files.requirements}" - source_md5hash = filemd5("${var.source_files.path}/${var.source_files.requirements}") + count = var.deployment_files.package_config != null ? 1 : 0 + name = "requirements.txt" + bucket = local.bucket_name + source = try(var.deployment_files.package_config.requirements_path, null) + source_md5hash = filemd5( + try(var.deployment_files.package_config.requirements_path) + ) } diff --git a/modules/agent-engine/outputs.tf b/modules/agent-engine/outputs.tf index 0b418d1c1..8eaa48647 100644 --- a/modules/agent-engine/outputs.tf +++ b/modules/agent-engine/outputs.tf @@ -14,9 +14,14 @@ * limitations under the License. */ +output "agent" { + description = "The Agent Engine object." + value = local.resource.object +} + output "id" { description = "Fully qualified Agent Engine id." - value = google_vertex_ai_reasoning_engine.default.id + value = local.resource.id } output "service_account" { diff --git a/modules/agent-engine/tools/requirements.txt b/modules/agent-engine/tools/requirements.txt deleted file mode 100644 index 37d5682cf..000000000 --- a/modules/agent-engine/tools/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -cloudpickle diff --git a/modules/agent-engine/tools/serialize_agent.py b/modules/agent-engine/tools/serialize_agent.py deleted file mode 100644 index 9b5619303..000000000 --- a/modules/agent-engine/tools/serialize_agent.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import cloudpickle -import importlib.util -import os -import sys -from google.adk.agents import LlmAgent - - -def serialize_agent_from_file(input_file, variable_name, output_file): - """ - Dynamically loads a Python module from a full file path, accesses a - top-level variable containing an agent object, and serializes that object - to a specified output file. - - Args: - input_file (str): The full path to the Python source file. - variable_name (str): The name of the variable holding the agent object. - output_file (str): The full path for the output pickle file. - """ - try: - output_dir = os.path.dirname(output_file) - if output_dir and not os.path.isdir(output_dir): - print(f"Error: The output directory '{output_dir}' does not exist.", - file=sys.stderr) - return - - module_name = os.path.splitext(os.path.basename(input_file))[0] - - spec = importlib.util.spec_from_file_location(module_name, input_file) - if spec is None or spec.loader is None: - print(f"Error: Could not import module from {input_file}", - file=sys.stderr) - return - - module = importlib.util.module_from_spec(spec) - - spec.loader.exec_module(module) - - local_agent = getattr(module, variable_name) - - with open(output_file, "wb") as f: - cloudpickle.dump(local_agent, f) - - print( - f"Successfully serialized '{variable_name}' from '{input_file}' to '{output_file}'" - ) - - except FileNotFoundError: - print(f"Error: The input file '{input_file}' was not found.", - file=sys.stderr) - except AttributeError: - print( - f"Error: The variable '{variable_name}' was not found in '{input_file}'.", - file=sys.stderr) - except Exception as e: - print(f"An unexpected error occurred: {e}", file=sys.stderr) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description= - "Serialize a dynamically loaded agent from a variable in a specified file." - ) - parser.add_argument( - "input_file", - help="The full path to the Python source file (e.g., 'my_agents/main.py')." - ) - parser.add_argument( - "--variable-name", default="local_agent", help= - "The name of the agent variable to serialize (default: 'local_agent').") - parser.add_argument( - "--output-file", default="pickle.pkl", help= - "The full path for the output pickle file (e.g., 'output/agent.pkl'). Default is 'pickle.pkl' in the current directory." - ) - - args = parser.parse_args() - - serialize_agent_from_file(args.input_file, args.variable_name, - args.output_file) diff --git a/modules/agent-engine/variables-serviceaccount.tf b/modules/agent-engine/variables-serviceaccount.tf index 5f4166c69..8d599bb1c 100644 --- a/modules/agent-engine/variables-serviceaccount.tf +++ b/modules/agent-engine/variables-serviceaccount.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/agent-engine/variables.tf b/modules/agent-engine/variables.tf index c40ae635c..cf96bb908 100644 --- a/modules/agent-engine/variables.tf +++ b/modules/agent-engine/variables.tf @@ -20,13 +20,21 @@ variable "agent_engine_config" { # Add validation once API stabilizes agent_framework = string class_methods = optional(list(any), []) + container_concurrency = optional(number) environment_variables = optional(map(string), {}) + max_instances = optional(number) + min_instances = optional(number) python_version = optional(string, "3.12") + resource_limits = optional(object({ + cpu = string + memory = string + })) secret_environment_variables = optional(map(object({ secret_id = string version = optional(string, "latest") })), {}) }) + nullable = false } variable "bucket_config" { @@ -54,6 +62,42 @@ variable "context" { default = {} } +variable "deployment_files" { + description = "The to source files path and names." + type = object({ + package_config = optional(object({ + dependencies_path = optional(string, "./src/dependencies.tar.gz") + pickle_path = optional(string, "./src/pickle.pkl") + requirements_path = optional(string, "./src/requirements.txt") + }), null) + source_config = optional(object({ + entrypoint_module = optional(string, "agent") + entrypoint_object = optional(string, "agent") + requirements_path = optional(string, "requirements.txt") + source_path = optional(string, "./src/source.tar.gz") + }), null) + }) + nullable = false + default = { + package_config = null + source_config = {} + } + validation { + condition = ( + var.deployment_files.package_config != null || + var.deployment_files.source_config != null + ) + error_message = "You must provide either 'package_config' or 'source_config'." + } + validation { + condition = !( + var.deployment_files.package_config != null && + var.deployment_files.source_config != null + ) + error_message = "You cannot specify both 'package_config' and 'source_config' simultaneously." + } +} + variable "description" { description = "The Agent Engine description." type = string @@ -67,8 +111,8 @@ variable "encryption_key" { default = null } -variable "generate_pickle" { - description = "Generate the pickle file from a source file." +variable "managed" { + description = "Whether the Terraform module should control the code updates." type = bool nullable = false default = true @@ -91,17 +135,3 @@ variable "region" { type = string nullable = false } - -variable "source_files" { - description = "The to source files path and names." - type = object({ - dependencies = optional(string, "dependencies.tar.gz") - path = optional(string, "./src") - pickle_out = optional(string, "pickle.pkl") - pickle_src = optional(string, "agent.py") - pickle_src_var_name = optional(string, "local_agent") - requirements = optional(string, "requirements.txt") - }) - nullable = false - default = {} -} diff --git a/tests/modules/agent_engine/assets/src/agent.py b/tests/modules/agent_engine/assets/src/agent.py index 1cea69c4c..d928375a0 100644 --- a/tests/modules/agent_engine/assets/src/agent.py +++ b/tests/modules/agent_engine/assets/src/agent.py @@ -42,4 +42,4 @@ root_agent = LlmAgent( tools=[get_exchange_rate], ) -local_agent = AdkApp(agent=root_agent) +agent = AdkApp(agent=root_agent) diff --git a/tests/modules/agent_engine/assets/src/source.tar.gz b/tests/modules/agent_engine/assets/src/source.tar.gz new file mode 100644 index 000000000..d8a8f24bd Binary files /dev/null and b/tests/modules/agent_engine/assets/src/source.tar.gz differ diff --git a/tests/modules/agent_engine/examples/encryption.yaml b/tests/modules/agent_engine/examples/encryption.yaml index d0c02a74c..6f319226c 100644 --- a/tests/modules/agent_engine/examples/encryption.yaml +++ b/tests/modules/agent_engine/examples/encryption.yaml @@ -38,86 +38,7 @@ values: member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com project: project-id timeouts: null - module.agent_engine.google_storage_bucket.default[0]: - autoclass: [] - cors: [] - custom_placement_config: [] - default_event_based_hold: null - effective_labels: - goog-terraform-provisioned: 'true' - enable_object_retention: null - encryption: [] - force_destroy: false - hierarchical_namespace: [] - ip_filter: [] - labels: null - lifecycle_rule: [] - location: EUROPE-WEST8 - logging: [] - name: my-agent - project: project-id - requester_pays: null - retention_policy: [] - storage_class: STANDARD - terraform_labels: - goog-terraform-provisioned: 'true' - timeouts: null - uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: dependencies.tar.gz - retention: [] - source: assets/src//dependencies.tar.gz - source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.pickle_from_src[0]: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: pickle.pkl - retention: [] - source: assets/src//pickle.pkl - source_md5hash: 493cf9bf3e59e39913e61916549f95a5 - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: requirements.txt - retention: [] - source: assets/src//requirements.txt - source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff - temporary_hold: null - timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: @@ -128,15 +49,17 @@ values: - agent_framework: google-adk class_methods: null deployment_spec: [] - package_spec: - - dependency_files_gcs_uri: gs://my-agent/dependencies.tar.gz - pickle_object_gcs_uri: gs://my-agent/pickle.pkl - python_version: '3.12' - requirements_gcs_uri: gs://my-agent/requirements.txt + package_spec: [] service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' timeouts: null - module.agent_engine.null_resource.default[0]: - triggers: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m destroy_duration: null @@ -145,12 +68,9 @@ values: counts: google_project_iam_member: 3 google_service_account: 1 - google_storage_bucket: 1 - google_storage_bucket_object: 3 google_vertex_ai_reasoning_engine: 1 modules: 1 - null_resource: 1 - resources: 11 + resources: 6 time_sleep: 1 outputs: {} diff --git a/tests/modules/agent_engine/examples/environment.yaml b/tests/modules/agent_engine/examples/environment.yaml index a92d3d1e6..dfd2b5a61 100644 --- a/tests/modules/agent_engine/examples/environment.yaml +++ b/tests/modules/agent_engine/examples/environment.yaml @@ -38,86 +38,7 @@ values: member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com project: project-id timeouts: null - module.agent_engine.google_storage_bucket.default[0]: - autoclass: [] - cors: [] - custom_placement_config: [] - default_event_based_hold: null - effective_labels: - goog-terraform-provisioned: 'true' - enable_object_retention: null - encryption: [] - force_destroy: false - hierarchical_namespace: [] - ip_filter: [] - labels: null - lifecycle_rule: [] - location: EUROPE-WEST8 - logging: [] - name: my-agent - project: project-id - requester_pays: null - retention_policy: [] - storage_class: STANDARD - terraform_labels: - goog-terraform-provisioned: 'true' - timeouts: null - uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: dependencies.tar.gz - retention: [] - source: assets/src//dependencies.tar.gz - source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.pickle_from_src[0]: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: pickle.pkl - retention: [] - source: assets/src//pickle.pkl - source_md5hash: 493cf9bf3e59e39913e61916549f95a5 - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: requirements.txt - retention: [] - source: assets/src//requirements.txt - source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff - temporary_hold: null - timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: [] @@ -135,15 +56,17 @@ values: secret_ref: - secret: projects/YOUR_PROJECT_NUMBER/secrets/my-bar-secret version: latest - package_spec: - - dependency_files_gcs_uri: gs://my-agent/dependencies.tar.gz - pickle_object_gcs_uri: gs://my-agent/pickle.pkl - python_version: '3.12' - requirements_gcs_uri: gs://my-agent/requirements.txt + package_spec: [] service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' timeouts: null - module.agent_engine.null_resource.default[0]: - triggers: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m destroy_duration: null @@ -152,12 +75,9 @@ values: counts: google_project_iam_member: 3 google_service_account: 1 - google_storage_bucket: 1 - google_storage_bucket_object: 3 google_vertex_ai_reasoning_engine: 1 modules: 1 - null_resource: 1 - resources: 11 + resources: 6 time_sleep: 1 outputs: {} diff --git a/tests/modules/agent_engine/examples/minimal-pickle.yaml b/tests/modules/agent_engine/examples/minimal-pickle.yaml index 8cb0cd285..e63942921 100644 --- a/tests/modules/agent_engine/examples/minimal-pickle.yaml +++ b/tests/modules/agent_engine/examples/minimal-pickle.yaml @@ -63,12 +63,13 @@ values: goog-terraform-provisioned: 'true' timeouts: null uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: + module.agent_engine.google_storage_bucket_object.dependencies[0]: bucket: my-agent cache_control: null content_disposition: null content_encoding: null content_language: null + contexts: [] customer_encryption: [] deletion_policy: null detect_md5hash: null @@ -77,7 +78,7 @@ values: metadata: null name: dependencies.tar.gz retention: [] - source: assets/src//dependencies.tar.gz + source: assets/src/dependencies.tar.gz source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a temporary_hold: null timeouts: null @@ -87,6 +88,7 @@ values: content_disposition: null content_encoding: null content_language: null + contexts: [] customer_encryption: [] deletion_policy: null detect_md5hash: null @@ -95,16 +97,17 @@ values: metadata: null name: pickle.pkl retention: [] - source: assets/src//pickle.pkl + source: assets/src/pickle.pkl source_md5hash: 493cf9bf3e59e39913e61916549f95a5 temporary_hold: null timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: + module.agent_engine.google_storage_bucket_object.requirements[0]: bucket: my-agent cache_control: null content_disposition: null content_encoding: null content_language: null + contexts: [] customer_encryption: [] deletion_policy: null detect_md5hash: null @@ -113,11 +116,11 @@ values: metadata: null name: requirements.txt retention: [] - source: assets/src//requirements.txt + source: assets/src/requirements.txt source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff temporary_hold: null timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: [] @@ -133,6 +136,7 @@ values: python_version: '3.12' requirements_gcs_uri: gs://my-agent/requirements.txt service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: [] timeouts: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m diff --git a/tests/modules/agent_engine/examples/minimal.yaml b/tests/modules/agent_engine/examples/minimal.yaml index ba1a04600..02fa8092d 100644 --- a/tests/modules/agent_engine/examples/minimal.yaml +++ b/tests/modules/agent_engine/examples/minimal.yaml @@ -38,86 +38,7 @@ values: member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com project: project-id timeouts: null - module.agent_engine.google_storage_bucket.default[0]: - autoclass: [] - cors: [] - custom_placement_config: [] - default_event_based_hold: null - effective_labels: - goog-terraform-provisioned: 'true' - enable_object_retention: null - encryption: [] - force_destroy: false - hierarchical_namespace: [] - ip_filter: [] - labels: null - lifecycle_rule: [] - location: EUROPE-WEST8 - logging: [] - name: my-agent - project: project-id - requester_pays: null - retention_policy: [] - storage_class: STANDARD - terraform_labels: - goog-terraform-provisioned: 'true' - timeouts: null - uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: dependencies.tar.gz - retention: [] - source: assets/src//dependencies.tar.gz - source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.pickle_from_src[0]: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: pickle.pkl - retention: [] - source: assets/src//pickle.pkl - source_md5hash: 493cf9bf3e59e39913e61916549f95a5 - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: requirements.txt - retention: [] - source: assets/src//requirements.txt - source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff - temporary_hold: null - timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: [] @@ -127,15 +48,17 @@ values: - agent_framework: google-adk class_methods: null deployment_spec: [] - package_spec: - - dependency_files_gcs_uri: gs://my-agent/dependencies.tar.gz - pickle_object_gcs_uri: gs://my-agent/pickle.pkl - python_version: '3.12' - requirements_gcs_uri: gs://my-agent/requirements.txt + package_spec: [] service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' timeouts: null - module.agent_engine.null_resource.default[0]: - triggers: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m destroy_duration: null @@ -144,12 +67,9 @@ values: counts: google_project_iam_member: 3 google_service_account: 1 - google_storage_bucket: 1 - google_storage_bucket_object: 3 google_vertex_ai_reasoning_engine: 1 modules: 1 - null_resource: 1 - resources: 11 + resources: 6 time_sleep: 1 outputs: {} diff --git a/tests/modules/agent_engine/examples/sa-custom.yaml b/tests/modules/agent_engine/examples/sa-custom.yaml index e8778ebb6..9679cc7e7 100644 --- a/tests/modules/agent_engine/examples/sa-custom.yaml +++ b/tests/modules/agent_engine/examples/sa-custom.yaml @@ -13,86 +13,7 @@ # limitations under the License. values: - module.agent_engine.google_storage_bucket.default[0]: - autoclass: [] - cors: [] - custom_placement_config: [] - default_event_based_hold: null - effective_labels: - goog-terraform-provisioned: 'true' - enable_object_retention: null - encryption: [] - force_destroy: false - hierarchical_namespace: [] - ip_filter: [] - labels: null - lifecycle_rule: [] - location: EUROPE-WEST8 - logging: [] - name: my-agent - project: project-id - requester_pays: null - retention_policy: [] - storage_class: STANDARD - terraform_labels: - goog-terraform-provisioned: 'true' - timeouts: null - uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: dependencies.tar.gz - retention: [] - source: assets/src//dependencies.tar.gz - source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.pickle_from_src[0]: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: pickle.pkl - retention: [] - source: assets/src//pickle.pkl - source_md5hash: 493cf9bf3e59e39913e61916549f95a5 - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: requirements.txt - retention: [] - source: assets/src//requirements.txt - source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff - temporary_hold: null - timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: [] @@ -102,27 +23,26 @@ values: - agent_framework: google-adk class_methods: null deployment_spec: [] - package_spec: - - dependency_files_gcs_uri: gs://my-agent/dependencies.tar.gz - pickle_object_gcs_uri: gs://my-agent/pickle.pkl - python_version: '3.12' - requirements_gcs_uri: gs://my-agent/requirements.txt + package_spec: [] service_account: my-sa@project-id.iam.gserviceaccount.com + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' timeouts: null - module.agent_engine.null_resource.default[0]: - triggers: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m destroy_duration: null triggers: null counts: - google_storage_bucket: 1 - google_storage_bucket_object: 3 google_vertex_ai_reasoning_engine: 1 modules: 1 - null_resource: 1 - resources: 7 + resources: 2 time_sleep: 1 outputs: {} diff --git a/tests/modules/agent_engine/examples/sa-default.yaml b/tests/modules/agent_engine/examples/sa-default.yaml index d843ee1a8..768175f47 100644 --- a/tests/modules/agent_engine/examples/sa-default.yaml +++ b/tests/modules/agent_engine/examples/sa-default.yaml @@ -13,86 +13,7 @@ # limitations under the License. values: - module.agent_engine.google_storage_bucket.default[0]: - autoclass: [] - cors: [] - custom_placement_config: [] - default_event_based_hold: null - effective_labels: - goog-terraform-provisioned: 'true' - enable_object_retention: null - encryption: [] - force_destroy: false - hierarchical_namespace: [] - ip_filter: [] - labels: null - lifecycle_rule: [] - location: EUROPE-WEST8 - logging: [] - name: my-agent - project: project-id - requester_pays: null - retention_policy: [] - storage_class: STANDARD - terraform_labels: - goog-terraform-provisioned: 'true' - timeouts: null - uniform_bucket_level_access: true - module.agent_engine.google_storage_bucket_object.dependencies: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: dependencies.tar.gz - retention: [] - source: assets/src//dependencies.tar.gz - source_md5hash: 49a4c43e6bef605c2fa6ddabac48ba6a - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.pickle_from_src[0]: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: pickle.pkl - retention: [] - source: assets/src//pickle.pkl - source_md5hash: 493cf9bf3e59e39913e61916549f95a5 - temporary_hold: null - timeouts: null - module.agent_engine.google_storage_bucket_object.requirements: - bucket: my-agent - cache_control: null - content_disposition: null - content_encoding: null - content_language: null - customer_encryption: [] - deletion_policy: null - detect_md5hash: null - event_based_hold: null - force_empty_content_type: null - metadata: null - name: requirements.txt - retention: [] - source: assets/src//requirements.txt - source_md5hash: 0acf2b14e855722af60e03e8fa8b04ff - temporary_hold: null - timeouts: null - module.agent_engine.google_vertex_ai_reasoning_engine.default: + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: description: Terraform managed. display_name: my-agent encryption_spec: [] @@ -102,27 +23,26 @@ values: - agent_framework: google-adk class_methods: null deployment_spec: [] - package_spec: - - dependency_files_gcs_uri: gs://my-agent/dependencies.tar.gz - pickle_object_gcs_uri: gs://my-agent/pickle.pkl - python_version: '3.12' - requirements_gcs_uri: gs://my-agent/requirements.txt + package_spec: [] service_account: null + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' timeouts: null - module.agent_engine.null_resource.default[0]: - triggers: null module.agent_engine.time_sleep.wait_5_minutes: create_duration: 5m destroy_duration: null triggers: null counts: - google_storage_bucket: 1 - google_storage_bucket_object: 3 google_vertex_ai_reasoning_engine: 1 modules: 1 - null_resource: 1 - resources: 7 + resources: 2 time_sleep: 1 outputs: {} diff --git a/tests/modules/agent_engine/examples/unmanaged.yaml b/tests/modules/agent_engine/examples/unmanaged.yaml new file mode 100644 index 000000000..30f8f50a2 --- /dev/null +++ b/tests/modules/agent_engine/examples/unmanaged.yaml @@ -0,0 +1,75 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.agent_engine.google_project_iam_member.default["roles/aiplatform.user"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/aiplatform.user + module.agent_engine.google_project_iam_member.default["roles/storage.objectViewer"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/storage.objectViewer + module.agent_engine.google_project_iam_member.default["roles/viewer"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/viewer + module.agent_engine.google_service_account.service_account[0]: + account_id: my-agent + create_ignore_already_exists: null + description: null + disabled: false + display_name: my-agent + email: my-agent@project-id.iam.gserviceaccount.com + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + timeouts: null + module.agent_engine.google_vertex_ai_reasoning_engine.unmanaged[0]: + description: Terraform managed. + display_name: my-agent + encryption_spec: [] + project: project-id + region: europe-west8 + spec: + - agent_framework: google-adk + class_methods: null + deployment_spec: [] + package_spec: [] + service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: + - inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.12' + timeouts: null + module.agent_engine.time_sleep.wait_5_minutes: + create_duration: 5m + destroy_duration: null + triggers: null + +counts: + google_project_iam_member: 3 + google_service_account: 1 + google_vertex_ai_reasoning_engine: 1 + modules: 1 + resources: 6 + time_sleep: 1 + +outputs: {}