You can use Terraform to provision and manage Agent Runtime instances declaratively. When deploying agents with Terraform, you manage the google_vertex_ai_reasoning_engine resource using the official Google Cloud Terraform provider (GA provider or Beta provider).
The instructions on this page correspond to the sample containerized agent implementation described in the Deploy a containerized agent with Agent Runtime codelab.
Prerequisites
Before using Terraform to deploy an agent, ensure that you have completed the following setup:
- Install Terraform (version 1.5.0 or later) and review the official HashiCorp Terraform Registry documentation for the
google_vertex_ai_reasoning_engineresource (GA provider and Beta provider). - Set up your Google Cloud environment and enable the Vertex AI API (
aiplatform.googleapis.com), Artifact Registry API (artifactregistry.googleapis.com), and Cloud Build API (cloudbuild.googleapis.com). Authenticate your local environment using Google Cloud credentials:
gcloud auth application-default loginTo keep your application code separate from infrastructure management, organize your agent workspace into dedicated application and Terraform directories:
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 outputsApplication files (
main.py,requirements.txt,Dockerfile): Contain your agent logic, web framework wrapper (such as FastAPI or ADK App), Python dependencies, and container build instructions.Terraform directory (
terraform/): Contains all Terraform configuration files used to provision resources:variables.tf: Declares input variables such asproject_id,location,repository_name, andimage_tag.main.tf: Declares provider settings, local variables, IAM role bindings, andgoogle_vertex_ai_reasoning_engineresource specifications.outputs.tf: Exports provisioned resource attributes, such as the Agent Runtime ID and full resource name, after deployment.
Grant the appropriate IAM roles depending on who is executing the deployment:
Human developer or CI/CD service account executing
terraform applyand local build commands.System-managed Agent Runtime Service Agent (
service-<var>PROJECT_NUMBER</var>@gcp-sa-aiplatform-re.).
Prepare for deployment
Terraform supports the following deployment paths for Agent Runtime:
- Deploy from prebuilt container image: Pre-build and push a container image to Artifact Registry (
{region}-docker.pkg.dev/...) and deploy it usingcontainer_spec. Use this method when you require full control over the container build process, custom base images, or lower deployment latency. - Deploy from source files or Dockerfile: Deploy your agent directly from local source files or a Dockerfile. Agent Runtime builds and provisions the container image automatically without requiring manual image management.
- Deploy using Python package specs Deploy using (
package_spec) staged in Cloud Storage. Agent Runtime builds and provisions the container image automatically without requiring manual image management.
Deploy from a prebuilt container image
If you pre-build and push container images to Artifact Registry (for example, to include custom system libraries, optimize cold-start performance, or enforce organizational image build controls), you can deploy using container_spec. For details on image requirements, see Deploy from Container Image.
Container images must be stored in Artifact Registry ({LOCATION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}:{TAG}), listen on port 8080 (or a custom port specified in container_spec), and conform to the runtime contract.
Build your container image locally and push it to your Artifact Registry repository:
# 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:latestConfigure your prebuilt container image for Terraform deployment. The following configuration demonstrates deploying a prebuilt container image hosted in Artifact Registry by creating the
variables.tf,main.tf, andoutputs.tffiles in yourterraform/directory:Input variables (
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" }Resource specifications (
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." } # 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] }Resource outputs (
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" }
Deploy from Dockerfile or source repository
When deploying from a Dockerfile, specify your source archive in
source_code_spec and set an empty image_spec {} block to instruct
Agent Runtime to build the container image using your Dockerfile. The
container built from your Dockerfile must adhere to the runtime
contract.
For more details about how deployment works, see Deploy from Dockerfile or Deploy from source files.
Compress your application code (
main.py), Python dependency manifest (requirements.txt), and container build instructions (Dockerfile) into a gzipped tar file archive.Run the following command from your application root directory (the example uses the root directory
weather-agent-byoc/and the tar file archiveweather_agent_source.tar.gz):cd weather-agent-byoc tar -czvf terraform/weather_agent_source.tar.gz main.py requirements.txt DockerfileCreate the
variables.tf,main.tf, andoutputs.tffiles in yourterraform/directory:Input variables (
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" }Resource specifications (
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" } ]) } }Resource outputs (
terraform/outputs.tf)output "dockerfile_agent_id" { value = google_vertex_ai_reasoning_engine.dockerfile_agent.id description = "Resource ID of the deployed Dockerfile agent" }
Deploy using Python package spec
If your agent is built using Python SDK objects or pickled applications (such as
ADK, LangChain, or custom Python agents), you can stage your serialized agent
(.pkl) and dependency configuration (requirements.txt) in a Cloud Storage
bucket and reference them using package_spec.
For more details about how deployment works, see Deploy from Python object.
Run the following Python script to serialize your agent and stage the deployment artifacts in 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}/")Create the
variables.tf,main.tf, andoutputs.tffiles in yourterraform/directory referencing the staged Cloud Storage URIs:Input variables (
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" }Resource specifications (
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" } } }Resource outputs (
terraform/outputs.tf)output "package_agent_id" { value = google_vertex_ai_reasoning_engine.package_agent.id description = "Resource ID of the deployed package agent" }
Configure environment variables and secrets
Before deployment, you can attach a custom runtime service account to your agent
and pass environment variables (env) or Secret Manager references
(secret_env).
The following example configures environment variables (LOCATION, MODEL,
MODEL_REGION) and passes an API key securely from Secret Manager to
the runtime service account through the terraform/main.tf file:
# 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."
}
# 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
]
}
Execution and lifecycle
Execute the standard Terraform lifecycle to plan, deploy, invoke, and destroy your agent resources.
Apply Terraform configuration
Deploy your agent by applying your Terraform configuration:
Change into your Terraform directory (for example,
cd weather-agent-byoc/terraform):cd weather-agent-byoc/terraformInitialize the working directory:
terraform initPreview the deployment plan:
terraform plan -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"Apply the configuration to provision the agent:
terraform apply -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"
Query the deployed agent
After Terraform provisions the google_vertex_ai_reasoning_engine resource,
send an HTTP POST request to the :streamQuery?alt=sse endpoint to stream
response events in real time using Server-Sent Events (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"
- OAuth Access Token:
Authorization: Bearer $(gcloud auth print-access-token)generates a short-lived OAuth 2.0 access token using your local Google Cloud credentials. - JSON
inputenvelope: The request body requires a JSON payload containing aninputobject. When calling explicit class methods (such asasync_stream_query), include the"class_method"parameter alongside"input". - Response payload: Responses are delivered continuously as
data: { ... }Server-Sent Event (SSE) chunks.
Destroy agent resources
To clean up resources and prevent unexpected billing charges, change into your
terraform/ directory (for example, cd weather-agent-byoc/terraform) and run
terraform destroy:
cd weather-agent-byoc/terraform
terraform destroy -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"What's next
- HashiCorp Terraform Registry —
google_vertex_ai_reasoning_engine(GA) - HashiCorp Terraform Registry —
google_vertex_ai_reasoning_engine(Beta) - Google Cloud Generative AI — Agent Runtime Terraform Deployment Tutorial (GitHub)
- Google Developer Forum — Deploy Your Agent Runtime with Terraform the Enterprise Way