Aprovisiona agentes con Terraform

Puedes usar Terraform para aprovisionar y administrar instancias de Agent Runtime de forma declarativa. Cuando implementas agentes con Terraform, administras el recurso google_vertex_ai_reasoning_engine con el proveedor oficial Google Cloud de Terraform (proveedor de GA o proveedor de versión beta).

Las instrucciones de esta página corresponden a la implementación de agente en contenedores de muestra que se describe en el codelab Implementa un agente en contenedores con Agent Runtime.

Requisitos previos

Antes de usar Terraform para implementar un agente, asegúrate de haber completado la siguiente configuración:

  1. Instala Terraform (versión 1.5.0 o posterior) y revisa la documentación oficial del registro de Terraform de HashiCorp para el recurso google_vertex_ai_reasoning_engine (proveedor de GA y proveedor de versión beta).
  2. Configura tu Google Cloud entorno y habilita la API de Vertex AI (aiplatform.googleapis.com), la API de Artifact Registry (artifactregistry.googleapis.com) y la API de Cloud Build (cloudbuild.googleapis.com).
  3. Autentica tu entorno local con Google Cloud credenciales:

    gcloud auth application-default login
  4. Para mantener el código de la aplicación separado de la administración de la infraestructura, organiza tu espacio de trabajo del agente en directorios de Terraform y de aplicación dedicados:

    weather-agent-byoc/
    ├── main.py                # Python ADK agent entrypoint
    ├── requirements.txt       # Python dependencies
    ├── Dockerfile             # Container build definition
    └── terraform/             # Terraform configuration directory
        ├── main.tf            # Agent Runtime resources and specifications
        ├── variables.tf       # Project, region, and container variables
        └── outputs.tf         # Resource name outputs
    
    • Archivos de aplicación (main.py, requirements.txt, Dockerfile): Contienen la lógica del agente, el wrapper del framework web (como FastAPI o ADK App), las dependencias de Python y las instrucciones de compilación del contenedor.

    • Directorio de Terraform (terraform/): Contiene todos los archivos de configuración de Terraform que se usan para aprovisionar recursos:

      • variables.tf: Declara variables de entrada como project_id, location, repository_name y image_tag.
      • main.tf: Declara la configuración del proveedor, las variables locales, las vinculaciones de roles de IAM y las especificaciones de recursos google_vertex_ai_reasoning_engine.
      • outputs.tf: Exporta atributos de recursos aprovisionados, como el ID de Agent Runtime y el nombre completo del recurso, después de la implementación.
  5. Otorga los roles de IAM adecuados según quién ejecute la implementación:

    • Desarrollador humano o cuenta de servicio de CI/CD que ejecuta terraform apply y comandos de compilación locales.

    • Agente de servicio de Agent Runtime administrado por el sistema (service-<var>PROJECT_NUMBER</var>@gcp-sa-aiplatform-re.iam.gserviceaccount.com).

Prepárate para la implementación

Terraform admite las siguientes rutas de implementación para Agent Runtime:

  • Implementa desde una imagen de contenedor compilada previamente: Compila previamente y envía una imagen de contenedor a Artifact Registry ({region}-docker.pkg.dev/...) y, luego, impleméntala con container_spec. Usa este método cuando necesites un control total sobre el proceso de compilación del contenedor, imágenes base personalizadas o una latencia de implementación más baja.
  • Implementa desde archivos de origen o Dockerfile: Implementa tu agente directamente desde archivos de origen locales o un Dockerfile. Agent Runtime compila y aprovisiona la imagen de contenedor automáticamente sin requerir la administración manual de imágenes.
  • Implementa con especificaciones de paquetes de Python Implementa con (package_spec) en etapa de pruebas en Cloud Storage. Agent Runtime compila y aprovisiona la imagen de contenedor automáticamente sin requerir la administración manual de imágenes.

Implementa desde una imagen de contenedor compilada previamente

Si compilas previamente y envías imágenes de contenedor a Artifact Registry (por ejemplo, para incluir bibliotecas del sistema personalizadas, optimizar el rendimiento del inicio en frío o aplicar controles de compilación de imágenes organizacionales), puedes implementar con container_spec. Para obtener detalles sobre los requisitos de la imagen, consulta Implementa desde una imagen de contenedor.

Las imágenes de contenedor deben almacenarse en Artifact Registry ({LOCATION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}:{TAG}), escuchar en el puerto 8080 (o un puerto personalizado especificado en container_spec) y cumplir con el contrato de entorno de ejecución.

  1. Compila tu imagen de contenedor de forma local y envíala a tu repositorio de Artifact Registry:

    # 1. Authenticate Docker with your Artifact Registry region
    gcloud auth configure-docker us-central1-docker.pkg.dev
    # 2. Build the container image from your application root directory
    cd weather-agent-byoc
    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/agents-repo/weather-agent-image:latest .
    # 3. Push the container image to Artifact Registry
    docker push us-central1-docker.pkg.dev/PROJECT_ID/agents-repo/weather-agent-image:latest
  2. Configura tu imagen de contenedor compilada previamente para la implementación de Terraform. En la siguiente configuración, se muestra la implementación de una imagen de contenedor compilada previamente alojada en Artifact Registry mediante la creación de los archivos variables.tf, main.tf y outputs.tf en tu directorio terraform/:

    Variables de entrada (terraform/variables.tf)

    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "project_number" {
      type        = string
      description = "The Google Cloud Project Number"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    
    variable "repository_name" {
      type        = string
      default     = "agents-repo"
      description = "The Artifact Registry repository name"
    }
    
    variable "image_tag" {
      type        = string
      default     = "latest"
      description = "The tag of the container image to deploy"
    }
    

    Especificaciones de recursos (terraform/main.tf)

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    locals {
      class_methods = [
        { "name" = "get_session", "api_mode" = "" },
        { "name" = "list_sessions", "api_mode" = "" },
        { "name" = "create_session", "api_mode" = "" },
        { "name" = "delete_session", "api_mode" = "" },
        { "name" = "async_get_session", "api_mode" = "async" },
        { "name" = "async_list_sessions", "api_mode" = "async" },
        { "name" = "async_create_session", "api_mode" = "async" },
        { "name" = "async_delete_session", "api_mode" = "async" },
        { "name" = "async_add_session_to_memory", "api_mode" = "async" },
        { "name" = "async_search_memory", "api_mode" = "async" },
        { "name" = "stream_query", "api_mode" = "stream" },
        { "name" = "async_stream_query", "api_mode" = "async_stream" },
        { "name" = "streaming_agent_run_with_events", "api_mode" = "async_stream" }
      ]
    }
    
    # Grant Artifact Registry Reader permission to the Agent Runtime Service Agent
    resource "google_project_iam_member" "re_service_agent_ar_reader" {
      project = var.project_id
      role    = "roles/artifactregistry.reader"
      member  = "serviceAccount:service-${var.project_number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
    }
    
    # Define the Agent Runtime resource with BYOC container configuration
    resource "google_vertex_ai_reasoning_engine" "byoc_weather_agent" {
      display_name = "byoc_weather_agent_tf"
      description  = "BYOC weather agent deployed using Terraform"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
    
        container_spec {
          image_uri = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_name}/weather-agent-image:${var.image_tag}"
        }
    
        class_methods = jsonencode(local.class_methods)
      }
    
      # Ensure service agent permission exists before provisioning to prevent IMAGE_PULL_BACKOFF
      depends_on = [google_project_iam_member.re_service_agent_ar_reader]
    }
    

    Resultados de recursos (terraform/outputs.tf)

    output "reasoning_engine_id" {
      value       = google_vertex_ai_reasoning_engine.byoc_weather_agent.id
      description = "The ID of the deployed Agent Runtime instance"
    }
    
    output "reasoning_engine_resource_name" {
      value       = google_vertex_ai_reasoning_engine.byoc_weather_agent.name
      description = "The resource name of the deployed Agent Runtime instance"
    }
    

Implementa desde Dockerfile o un repositorio de código fuente

Cuando implementes desde un Dockerfile, especifica tu archivo de origen en source_code_spec y establece un bloque image_spec {} vacío para indicarle a Agent Runtime que compile la imagen de contenedor con tu Dockerfile. El contenedor compilado desde tu Dockerfile debe cumplir con el contrato de entorno de ejecución.

Para obtener más detalles sobre cómo funciona la implementación, consulta Implementa desde Dockerfile o Implementa desde archivos de origen.

  1. Comprime el código de tu aplicación (main.py), el manifiesto de dependencias de Python (requirements.txt) y las instrucciones de compilación del contenedor (Dockerfile) en un archivo tar comprimido con gzip.

  2. Ejecuta el siguiente comando desde el directorio raíz de tu aplicación (en el ejemplo, se usa el directorio raíz weather-agent-byoc/ y el archivo tar weather_agent_source.tar.gz):

    cd weather-agent-byoc
    tar -czvf terraform/weather_agent_source.tar.gz main.py requirements.txt Dockerfile
  3. Crea los archivos variables.tf, main.tf y outputs.tf en tu directorio terraform/:

    Variables de entrada (terraform/variables.tf)
    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    

    Especificaciones de recursos (terraform/main.tf)

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    resource "google_vertex_ai_reasoning_engine" "dockerfile_agent" {
      display_name = "dockerfile_weather_agent_tf"
      description  = "BYOC weather agent deployed using Dockerfile"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
    
        source_code_spec {
          inline_source {
            source_archive = filebase64("weather_agent_source.tar.gz")
          }
    
          # Empty image_spec instructs the runtime to build using the Dockerfile
          image_spec {}
        }
    
        class_methods = jsonencode([
          { "name" = "get_session", "api_mode" = "" },
          { "name" = "list_sessions", "api_mode" = "" },
          { "name" = "create_session", "api_mode" = "" },
          { "name" = "delete_session", "api_mode" = "" },
          { "name" = "async_get_session", "api_mode" = "async" },
          { "name" = "async_list_sessions", "api_mode" = "async" },
          { "name" = "async_create_session", "api_mode" = "async" },
          { "name" = "async_delete_session", "api_mode" = "async" },
          { "name" = "async_add_session_to_memory", "api_mode" = "async" },
          { "name" = "async_search_memory", "api_mode" = "async" },
          { "name" = "stream_query", "api_mode" = "stream" },
          { "name" = "async_stream_query", "api_mode" = "async_stream" },
          { "name" = "streaming_agent_run_with_events", "api_mode" = "async_stream" }
        ])
      }
    }
    

    Resultados de recursos (terraform/outputs.tf)

    output "dockerfile_agent_id" {
      value       = google_vertex_ai_reasoning_engine.dockerfile_agent.id
      description = "Resource ID of the deployed Dockerfile agent"
    }
    

Implementa con la especificación de paquetes de Python

Si tu agente se compila con objetos del SDK de Python o aplicaciones serializadas (como ADK, LangChain o agentes personalizados de Python), puedes preparar tu agente serializado (.pkl) y la configuración de dependencias (requirements.txt) en un bucket de Cloud Storage y hacer referencia a ellos con package_spec.

Para obtener más detalles sobre cómo funciona la implementación, consulta Implementa desde un objeto de Python.

  1. Ejecuta la siguiente secuencia de comandos de Python para serializar tu agente y preparar los artefactos de implementación en Cloud Storage:

    import cloudpickle
    from google.adk.agents import Agent
    from google.cloud import storage
    from vertexai.agent_engines import AdkApp
    PROJECT_ID = "PROJECT_ID"
    BUCKET_NAME = "BUCKET_NAME"
    GCS_DIR = "agents/weather_agent"
    
    # 1. Define agent logic
    root_agent = Agent(
        model="gemini-3.1-flash-lite",
        name="weather_agent",
        description="Agent deployed using Terraform package_spec.",
    )
    local_app = AdkApp(agent=root_agent)
    
    # 2. Upload pickle to Cloud Storage
    storage_client = storage.Client(project=PROJECT_ID)
    bucket = storage_client.bucket(BUCKET_NAME)
    
    pkl_blob = bucket.blob(f"{GCS_DIR}/agent.pkl")
    with pkl_blob.open("wb") as f:
        cloudpickle.dump(local_app, f)
    
    # 3. Upload requirements.txt
    requirements_content = """google-cloud-aiplatform[agent_engines,adk]>=1.144
    cloudpickle==3.0.0
    """
    req_blob = bucket.blob(f"{GCS_DIR}/requirements.txt")
    req_blob.upload_from_string(requirements_content)
    
    print(f"Artifacts uploaded to gs://{BUCKET_NAME}/{GCS_DIR}/")
    
  2. Crea los archivos variables.tf, main.tf y outputs.tf en tu directorio terraform/ que hagan referencia a los URIs de Cloud Storage preparados:

    Variables de entrada (terraform/variables.tf)
    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    
    variable "bucket_name" {
      type        = string
      description = "Cloud Storage bucket name containing agent artifacts"
    }
    
    Especificaciones de recursos (terraform/main.tf)
    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    resource "google_vertex_ai_reasoning_engine" "package_agent" {
      display_name = "weather_agent_package_tf"
      description  = "Agent Runtime instance deployed using package_spec"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
        package_spec {
          python_version        = "3.11"
          pickle_object_gcs_uri = "gs://${var.bucket_name}/agents/weather_agent/agent.pkl"
          requirements_gcs_uri  = "gs://${var.bucket_name}/agents/weather_agent/requirements.txt"
        }
      }
    }
    
    Resultados de recursos (terraform/outputs.tf)
    output "package_agent_id" {
      value       = google_vertex_ai_reasoning_engine.package_agent.id
      description = "Resource ID of the deployed package agent"
    }
    

Configura variables de entorno y secretos

Antes de la implementación, puedes conectar una cuenta de servicio de entorno de ejecución personalizado a tu agente y pasar variables de entorno (env) o referencias de Secret Manager (secret_env).

En el siguiente ejemplo, se configuran variables de entorno (LOCATION, MODEL, MODEL_REGION) y se pasa una clave de API de forma segura desde Secret Manager a la cuenta de servicio de entorno de ejecución a través del archivo terraform/main.tf:

# 1. Dedicated Runtime Service Account
resource "google_service_account" "agent_runtime_sa" {
  account_id   = "agent-runtime-sa"
  display_name = "Agent Runtime Identity"
  project      = var.project_id
}

# 2. Secret Manager Secret for Agent Credentials
resource "google_secret_manager_secret" "api_key_secret" {
  secret_id = "agent-api-key"
  project   = var.project_id

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "api_key_version" {
  secret      = google_secret_manager_secret.api_key_secret.id
  secret_data = var.api_key_value
}

# Grant Secret Accessor role to Runtime Service Account
resource "google_secret_manager_secret_iam_member" "secret_accessor" {
  secret_id = google_secret_manager_secret.api_key_secret.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.agent_runtime_sa.email}"
}

# Grant Artifact Registry Reader permission to the Agent Runtime Service Agent
resource "google_project_iam_member" "re_service_agent_ar_reader" {
  project = var.project_id
  role    = "roles/artifactregistry.reader"
  member  = "serviceAccount:service-${var.project_number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
}

# 3. Agent Runtime Resource with Environment Variables and Secret References
resource "google_vertex_ai_reasoning_engine" "advanced_weather_agent" {
  display_name = "byoc_weather_agent_advanced_tf"
  description  = "BYOC weather agent with custom service account and secrets"
  project      = var.project_id
  location     = var.location

  spec {
    agent_framework = "google-adk"
    service_account = google_service_account.agent_runtime_sa.email

    container_spec {
      image_uri = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_name}/weather-agent-image:${var.image_tag}"
    }

    deployment_spec {
      env {
        name  = "LOCATION"
        value = var.location
      }
      env {
        name  = "MODEL"
        value = "gemini-3.1-flash-lite"
      }
      env {
        name  = "MODEL_REGION"
        value = "global"
      }

      secret_env {
        name = "API_KEY"
        secret_ref {
          secret  = google_secret_manager_secret.api_key_secret.secret_id
          version = "latest"
        }
      }
    }

    class_methods = jsonencode([
      { "name" = "get_session", "api_mode" = "" },
      { "name" = "create_session", "api_mode" = "" },
      { "name" = "stream_query", "api_mode" = "stream" },
      { "name" = "async_stream_query", "api_mode" = "async_stream" }
    ])
  }

  depends_on = [
    google_secret_manager_secret_iam_member.secret_accessor,
    google_project_iam_member.re_service_agent_ar_reader
  ]
}

Ejecución y ciclo de vida

Ejecuta el ciclo de vida estándar de Terraform para planificar, implementar, invocar y destruir los recursos de tu agente.

Aplica la configuración de Terraform

Para implementar tu agente, aplica la configuración de Terraform:

  1. Cambia a tu directorio de Terraform (por ejemplo, cd weather-agent-byoc/terraform):

    cd weather-agent-byoc/terraform
  2. Inicializa el directorio de trabajo:

    terraform init
  3. Obtén una vista previa del plan de implementación:

    terraform plan -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"
  4. Aplica la configuración para aprovisionar el agente:

    terraform apply -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"

Hazle preguntas al agente implementado

Después de que Terraform aprovisione el recurso google_vertex_ai_reasoning_engine, envía una solicitud POST HTTP al extremo :streamQuery?alt=sse para transmitir eventos de respuesta en tiempo real con eventos enviados por el servidor (SSE):

LOCATION="LOCATION"
PROJECT_ID="PROJECT_ID"
REASONING_ENGINE_ID="REASONING_ENGINE_ID"
curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "class_method": "async_stream_query",
    "input": {
      "user_id": "terraform_test_user",
      "message": "What is the temperature in Seattle?"
    }
  }' \
  "https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/reasoningEngines/${REASONING_ENGINE_ID}:streamQuery?alt=sse"
  • Token de acceso de OAuth: Authorization: Bearer $(gcloud auth print-access-token) genera un token de acceso de OAuth 2.0 de corta duración con tus Google Cloud credenciales locales.
  • Sobre input de JSON: El cuerpo de la solicitud requiere una carga útil de JSON que contenga un objeto input. Cuando llames a métodos de clase explícitos (como async_stream_query), incluye el parámetro "class_method" junto con "input".
  • Carga útil de respuesta: Las respuestas se entregan de forma continua como fragmentos de eventos enviados por el servidor (SSE) data: { ... }.

Destruye los recursos del agente

Para limpiar los recursos y evitar cargos de facturación inesperados, cambia a tu directorio terraform/ (por ejemplo, cd weather-agent-byoc/terraform) y ejecuta terraform destroy:

cd weather-agent-byoc/terraform
terraform destroy -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"

¿Qué sigue?