agent-starter-pack 0.18.2__py3-none-any.whl → 0.21.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. agent_starter_pack/agents/{langgraph_base_react → adk_a2a_base}/.template/templateconfig.yaml +5 -12
  2. agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
  3. agent_starter_pack/{frontends/streamlit/frontend/style/app_markdown.py → agents/adk_a2a_base/app/__init__.py} +3 -23
  4. agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
  5. agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
  6. agent_starter_pack/agents/{crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → adk_a2a_base/notebooks/evaluating_adk_agent.ipynb} +163 -199
  7. agent_starter_pack/agents/adk_a2a_base/tests/integration/test_agent.py +58 -0
  8. agent_starter_pack/agents/adk_base/app/__init__.py +2 -2
  9. agent_starter_pack/agents/adk_base/app/agent.py +3 -0
  10. agent_starter_pack/agents/adk_base/notebooks/adk_app_testing.ipynb +13 -28
  11. agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
  12. agent_starter_pack/agents/adk_live/app/agent.py +3 -0
  13. agent_starter_pack/agents/agentic_rag/app/__init__.py +2 -2
  14. agent_starter_pack/agents/agentic_rag/app/agent.py +3 -0
  15. agent_starter_pack/agents/agentic_rag/notebooks/adk_app_testing.ipynb +13 -28
  16. agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/.template/templateconfig.yaml +12 -9
  17. agent_starter_pack/agents/langgraph_base/README.md +30 -0
  18. agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
  19. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/app/agent.py +4 -4
  20. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/tests/integration/test_agent.py +1 -1
  21. agent_starter_pack/base_template/.gitignore +4 -2
  22. agent_starter_pack/base_template/Makefile +110 -16
  23. agent_starter_pack/base_template/README.md +97 -12
  24. agent_starter_pack/base_template/deployment/terraform/dev/apis.tf +4 -6
  25. agent_starter_pack/base_template/deployment/terraform/dev/providers.tf +5 -1
  26. agent_starter_pack/base_template/deployment/terraform/dev/variables.tf +5 -3
  27. agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
  28. agent_starter_pack/base_template/deployment/terraform/github.tf +16 -9
  29. agent_starter_pack/base_template/deployment/terraform/locals.tf +7 -7
  30. agent_starter_pack/base_template/deployment/terraform/providers.tf +5 -1
  31. agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
  32. agent_starter_pack/base_template/deployment/terraform/storage.tf +0 -9
  33. agent_starter_pack/base_template/deployment/terraform/variables.tf +15 -19
  34. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +20 -22
  35. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
  36. agent_starter_pack/base_template/pyproject.toml +5 -17
  37. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +19 -4
  38. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +36 -11
  39. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +24 -5
  40. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +44 -9
  41. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
  42. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/typing.py +4 -6
  43. agent_starter_pack/{agents/crewai_coding_crew/app/crew/config/agents.yaml → base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py } +9 -23
  44. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/part_converter.py +138 -0
  45. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/__init__.py +13 -0
  46. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/a2a_agent_executor.py +265 -0
  47. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/task_result_aggregator.py +152 -0
  48. agent_starter_pack/cli/commands/create.py +40 -4
  49. agent_starter_pack/cli/commands/enhance.py +1 -1
  50. agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
  51. agent_starter_pack/cli/main.py +2 -0
  52. agent_starter_pack/cli/utils/cicd.py +20 -4
  53. agent_starter_pack/cli/utils/template.py +257 -25
  54. agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +113 -16
  55. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +2 -2
  56. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +178 -9
  57. agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
  58. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +193 -307
  59. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
  60. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/{utils → app_utils}/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +13 -14
  61. agent_starter_pack/deployment_targets/cloud_run/Dockerfile +4 -1
  62. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +85 -86
  63. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +139 -107
  64. agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +228 -12
  65. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +4 -4
  66. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +92 -12
  67. agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/{server.py → fast_api_app.py} +194 -121
  68. agent_starter_pack/frontends/adk_live_react/frontend/package-lock.json +18 -18
  69. agent_starter_pack/frontends/adk_live_react/frontend/src/multimodal-live-types.ts +5 -3
  70. agent_starter_pack/resources/docs/adk-cheatsheet.md +198 -41
  71. agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
  72. agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
  73. agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +1443 -709
  74. agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +1058 -874
  75. agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +1443 -709
  76. agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +1058 -874
  77. agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +1568 -749
  78. agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +1123 -929
  79. agent_starter_pack/resources/locks/{uv-langgraph_base_react-agent_engine.lock → uv-langgraph_base-agent_engine.lock} +1714 -1689
  80. agent_starter_pack/resources/locks/{uv-langgraph_base_react-cloud_run.lock → uv-langgraph_base-cloud_run.lock} +1285 -2374
  81. agent_starter_pack/utils/watch_and_rebuild.py +1 -1
  82. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/METADATA +3 -6
  83. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/RECORD +89 -93
  84. agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
  85. llm.txt +4 -5
  86. agent_starter_pack/agents/crewai_coding_crew/README.md +0 -34
  87. agent_starter_pack/agents/crewai_coding_crew/app/agent.py +0 -47
  88. agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
  89. agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py +0 -71
  90. agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
  91. agent_starter_pack/agents/langgraph_base_react/README.md +0 -9
  92. agent_starter_pack/agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -1574
  93. agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf +0 -69
  94. agent_starter_pack/base_template/deployment/terraform/log_sinks.tf +0 -79
  95. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +0 -155
  96. agent_starter_pack/cli/utils/register_gemini_enterprise.py +0 -406
  97. agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +0 -82
  98. agent_starter_pack/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
  99. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +0 -99
  100. agent_starter_pack/frontends/streamlit/frontend/side_bar.py +0 -214
  101. agent_starter_pack/frontends/streamlit/frontend/streamlit_app.py +0 -265
  102. agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
  103. agent_starter_pack/frontends/streamlit/frontend/utils/local_chat_history.py +0 -127
  104. agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py +0 -59
  105. agent_starter_pack/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
  106. agent_starter_pack/frontends/streamlit/frontend/utils/stream_handler.py +0 -310
  107. agent_starter_pack/frontends/streamlit/frontend/utils/title_summary.py +0 -94
  108. agent_starter_pack/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6650
  109. agent_starter_pack/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -7825
  110. agent_starter_pack-0.18.2.dist-info/entry_points.txt +0 -3
  111. /agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +0 -0
  112. /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/gcs.py +0 -0
  113. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
  114. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
@@ -50,35 +50,21 @@ variable "repository_name" {
50
50
  type = string
51
51
  }
52
52
 
53
- variable "telemetry_logs_filter" {
54
- type = string
55
- description = "Log Sink filter for capturing telemetry data. Captures logs with the `traceloop.association.properties.log_type` attribute set to `tracing`."
56
- {%- if cookiecutter.is_adk %}
57
- default = "labels.service_name=\"{{cookiecutter.project_name}}\" labels.type=\"agent_telemetry\""
58
- {%- else %}
59
- default = "jsonPayload.attributes.\"traceloop.association.properties.log_type\"=\"tracing\" jsonPayload.resource.attributes.\"service.name\"=\"{{cookiecutter.project_name}}\""
60
- {%- endif %}
61
- }
62
-
63
- variable "feedback_logs_filter" {
64
- type = string
65
- description = "Log Sink filter for capturing feedback data. Captures logs where the `log_type` field is `feedback`."
66
- default = "jsonPayload.log_type=\"feedback\""
67
- }
68
-
69
53
  variable "app_sa_roles" {
70
54
  description = "List of roles to assign to the application service account"
71
55
  type = list(string)
72
56
  default = [
73
- {%- if cookiecutter.session_type == "alloydb" %}
74
- "roles/secretmanager.secretAccessor",
75
- {%- endif %}
57
+
76
58
  "roles/aiplatform.user",
77
59
  "roles/discoveryengine.editor",
78
60
  "roles/logging.logWriter",
79
61
  "roles/cloudtrace.agent",
80
62
  "roles/storage.admin",
81
63
  "roles/serviceusage.serviceUsageConsumer",
64
+ {%- if cookiecutter.session_type == "cloud_sql" %}
65
+ "roles/cloudsql.client",
66
+ "roles/secretmanager.secretAccessor",
67
+ {%- endif %}
82
68
  ]
83
69
  }
84
70
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
@@ -186,6 +172,7 @@ variable "repository_owner" {
186
172
  description = "Owner of the Git repository - username or organization"
187
173
  type = string
188
174
  }
175
+
189
176
  {% if cookiecutter.cicd_runner == "github_actions" %}
190
177
 
191
178
 
@@ -220,3 +207,12 @@ variable "create_repository" {
220
207
  default = false
221
208
  }
222
209
  {% endif %}
210
+ {% if cookiecutter.is_adk %}
211
+
212
+ variable "feedback_logs_filter" {
213
+ type = string
214
+ description = "Log Sink filter for capturing feedback data. Captures logs where the `log_type` field is `feedback`."
215
+ default = "jsonPayload.log_type=\"feedback\" jsonPayload.service_name=\"{{cookiecutter.project_name}}\""
216
+ }
217
+ {% endif %}
218
+
@@ -73,29 +73,27 @@ resource "google_cloudbuild_trigger" "cd_pipeline" {
73
73
  include_build_logs = "INCLUDE_BUILD_LOGS_WITH_STATUS"
74
74
  substitutions = {
75
75
  _STAGING_PROJECT_ID = var.staging_project_id
76
- _BUCKET_NAME_LOAD_TEST_RESULTS = resource.google_storage_bucket.bucket_load_test_results.name
77
- _LOGS_BUCKET_NAME_STAGING = resource.google_storage_bucket.logs_data_bucket[var.staging_project_id].url
76
+ _LOGS_BUCKET_NAME_STAGING = resource.google_storage_bucket.logs_data_bucket[var.staging_project_id].name
77
+ _APP_SERVICE_ACCOUNT_STAGING = google_service_account.app_sa["staging"].email
78
78
  _REGION = var.region
79
- {% if cookiecutter.deployment_target == 'cloud_run' %}
79
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
80
80
  _CONTAINER_NAME = var.project_name
81
81
  _ARTIFACT_REGISTRY_REPO_NAME = resource.google_artifact_registry_repository.repo-artifacts-genai.repository_id
82
- {% elif cookiecutter.deployment_target == 'agent_engine' %}
83
-
84
- {% endif %}
85
- {% if cookiecutter.data_ingestion %}
82
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
83
+ {%- endif %}
84
+ {%- if cookiecutter.data_ingestion %}
86
85
  _PIPELINE_GCS_ROOT_STAGING = "gs://${resource.google_storage_bucket.data_ingestion_pipeline_gcs_root["staging"].name}"
87
86
  _PIPELINE_SA_EMAIL_STAGING = resource.google_service_account.vertexai_pipeline_app_sa["staging"].email
88
87
  _PIPELINE_CRON_SCHEDULE = var.pipeline_cron_schedule
89
- {% if cookiecutter.datastore_type == "vertex_ai_search" %}
88
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
90
89
  _DATA_STORE_ID_STAGING = resource.google_discovery_engine_data_store.data_store_staging.data_store_id
91
90
  _DATA_STORE_REGION = var.data_store_region
92
- {% elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
91
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
93
92
  _VECTOR_SEARCH_INDEX_STAGING = resource.google_vertex_ai_index.vector_search_index_staging.id
94
93
  _VECTOR_SEARCH_INDEX_ENDPOINT_STAGING = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_staging.id
95
94
  _VECTOR_SEARCH_BUCKET_STAGING = resource.google_storage_bucket.vector_search_data_bucket["staging"].url
96
-
97
- {% endif %}
98
- {% endif %}
95
+ {%- endif %}
96
+ {%- endif %}
99
97
  # Your other CD Pipeline substitutions
100
98
  }
101
99
  depends_on = [
@@ -124,27 +122,27 @@ resource "google_cloudbuild_trigger" "deploy_to_prod_pipeline" {
124
122
  }
125
123
  substitutions = {
126
124
  _PROD_PROJECT_ID = var.prod_project_id
127
- _LOGS_BUCKET_NAME_PROD = resource.google_storage_bucket.logs_data_bucket[var.prod_project_id].url
125
+ _LOGS_BUCKET_NAME_PROD = resource.google_storage_bucket.logs_data_bucket[var.prod_project_id].name
126
+ _APP_SERVICE_ACCOUNT_PROD = google_service_account.app_sa["prod"].email
128
127
  _REGION = var.region
129
- {% if cookiecutter.deployment_target == 'cloud_run' %}
128
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
130
129
  _CONTAINER_NAME = var.project_name
131
130
  _ARTIFACT_REGISTRY_REPO_NAME = resource.google_artifact_registry_repository.repo-artifacts-genai.repository_id
132
- {% elif cookiecutter.deployment_target == 'agent_engine' %}
133
-
134
- {% endif %}
135
- {% if cookiecutter.data_ingestion %}
131
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
132
+ {%- endif %}
133
+ {%- if cookiecutter.data_ingestion %}
136
134
  _PIPELINE_GCS_ROOT_PROD = "gs://${resource.google_storage_bucket.data_ingestion_pipeline_gcs_root["prod"].name}"
137
135
  _PIPELINE_SA_EMAIL_PROD = resource.google_service_account.vertexai_pipeline_app_sa["prod"].email
138
136
  _PIPELINE_CRON_SCHEDULE = var.pipeline_cron_schedule
139
- {% if cookiecutter.datastore_type == "vertex_ai_search" %}
137
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
140
138
  _DATA_STORE_ID_PROD = resource.google_discovery_engine_data_store.data_store_prod.data_store_id
141
139
  _DATA_STORE_REGION = var.data_store_region
142
- {% elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
140
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
143
141
  _VECTOR_SEARCH_INDEX_PROD = resource.google_vertex_ai_index.vector_search_index_prod.id
144
142
  _VECTOR_SEARCH_INDEX_ENDPOINT_PROD = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_prod.id
145
143
  _VECTOR_SEARCH_BUCKET_PROD = resource.google_storage_bucket.vector_search_data_bucket["prod"].url
146
- {% endif %}
147
- {% endif %}
144
+ {%- endif %}
145
+ {%- endif %}
148
146
  # Your other Deploy to Prod Pipeline substitutions
149
147
  }
150
148
  depends_on = [
@@ -0,0 +1,206 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # BigQuery dataset for telemetry external tables
16
+ resource "google_bigquery_dataset" "telemetry_dataset" {
17
+ for_each = local.deploy_project_ids
18
+ project = each.value
19
+ dataset_id = replace("${var.project_name}_telemetry", "-", "_")
20
+ friendly_name = "${var.project_name} Telemetry"
21
+ location = var.region
22
+ description = "Dataset for GenAI telemetry data stored in GCS"
23
+ depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
24
+ }
25
+
26
+ # BigQuery connection for accessing GCS telemetry data
27
+ resource "google_bigquery_connection" "genai_telemetry_connection" {
28
+ for_each = local.deploy_project_ids
29
+ project = each.value
30
+ location = var.region
31
+ connection_id = "${var.project_name}-genai-telemetry"
32
+ friendly_name = "${var.project_name} GenAI Telemetry Connection"
33
+
34
+ cloud_resource {}
35
+
36
+ depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
37
+ }
38
+
39
+ # Wait for the BigQuery connection service account to propagate in IAM
40
+ resource "time_sleep" "wait_for_bq_connection_sa" {
41
+ for_each = local.deploy_project_ids
42
+
43
+ create_duration = "10s"
44
+
45
+ depends_on = [google_bigquery_connection.genai_telemetry_connection]
46
+ }
47
+
48
+ # Grant the BigQuery connection service account access to read from the logs bucket
49
+ resource "google_storage_bucket_iam_member" "telemetry_connection_access" {
50
+ for_each = local.deploy_project_ids
51
+ bucket = google_storage_bucket.logs_data_bucket[each.value].name
52
+ role = "roles/storage.objectViewer"
53
+ member = "serviceAccount:${google_bigquery_connection.genai_telemetry_connection[each.key].cloud_resource[0].service_account_id}"
54
+
55
+ depends_on = [time_sleep.wait_for_bq_connection_sa]
56
+ }
57
+
58
+ # ====================================================================
59
+ # Dedicated Cloud Logging Bucket for GenAI Telemetry
60
+ # ====================================================================
61
+
62
+ # Create a custom Cloud Logging bucket for GenAI telemetry logs with long-term retention
63
+ resource "google_logging_project_bucket_config" "genai_telemetry_bucket" {
64
+ for_each = local.deploy_project_ids
65
+ project = each.value
66
+ location = var.region
67
+ bucket_id = "${var.project_name}-genai-telemetry"
68
+ retention_days = 3650 # 10 years retention (maximum allowed)
69
+ enable_analytics = true # Required for linked datasets
70
+ description = "Dedicated Cloud Logging bucket for ${var.project_name} GenAI telemetry with 10 year retention"
71
+
72
+ depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
73
+ }
74
+
75
+ # Log sink to route only GenAI telemetry logs to the dedicated bucket
76
+ # Filter by bucket name in the GCS path (which includes project_name) to isolate this agent's logs
77
+ resource "google_logging_project_sink" "genai_logs_to_bucket" {
78
+ for_each = local.deploy_project_ids
79
+ name = "${var.project_name}-genai-logs"
80
+ project = each.value
81
+ destination = "logging.googleapis.com/projects/${each.value}/locations/${var.region}/buckets/${google_logging_project_bucket_config.genai_telemetry_bucket[each.key].bucket_id}"
82
+ filter = "log_name=\"projects/${each.value}/logs/gen_ai.client.inference.operation.details\" AND (labels.\"gen_ai.input.messages_ref\" =~ \".*${var.project_name}.*\" OR labels.\"gen_ai.output.messages_ref\" =~ \".*${var.project_name}.*\")"
83
+
84
+ unique_writer_identity = true
85
+ depends_on = [google_logging_project_bucket_config.genai_telemetry_bucket]
86
+ }
87
+
88
+ # Create a linked dataset to the GenAI telemetry logs bucket for querying via BigQuery
89
+ resource "google_logging_linked_dataset" "genai_logs_linked_dataset" {
90
+ for_each = local.deploy_project_ids
91
+ link_id = replace("${var.project_name}_genai_telemetry_logs", "-", "_")
92
+ bucket = google_logging_project_bucket_config.genai_telemetry_bucket[each.key].bucket_id
93
+ description = "Linked dataset for ${var.project_name} GenAI telemetry Cloud Logging bucket"
94
+ location = var.region
95
+ parent = "projects/${each.value}"
96
+
97
+ depends_on = [
98
+ google_logging_project_bucket_config.genai_telemetry_bucket,
99
+ google_logging_project_sink.genai_logs_to_bucket
100
+ ]
101
+ }
102
+
103
+ # Wait for linked dataset to fully propagate
104
+ resource "time_sleep" "wait_for_linked_dataset" {
105
+ for_each = local.deploy_project_ids
106
+
107
+ create_duration = "10s"
108
+
109
+ depends_on = [google_logging_linked_dataset.genai_logs_linked_dataset]
110
+ }
111
+
112
+ # ====================================================================
113
+ # Feedback Logs to Cloud Logging Bucket
114
+ # ====================================================================
115
+
116
+ # Log sink for user feedback logs - routes to the same Cloud Logging bucket
117
+ resource "google_logging_project_sink" "feedback_logs_to_bucket" {
118
+ for_each = local.deploy_project_ids
119
+ name = "${var.project_name}-feedback"
120
+ project = each.value
121
+ destination = "logging.googleapis.com/projects/${each.value}/locations/${var.region}/buckets/${google_logging_project_bucket_config.genai_telemetry_bucket[each.key].bucket_id}"
122
+ filter = var.feedback_logs_filter
123
+
124
+ unique_writer_identity = true
125
+ depends_on = [google_logging_project_bucket_config.genai_telemetry_bucket]
126
+ }
127
+
128
+ # ====================================================================
129
+ # Completions External Table (GCS-based)
130
+ # ====================================================================
131
+
132
+ # External table for completions data (messages/parts) stored in GCS
133
+ resource "google_bigquery_table" "completions_external_table" {
134
+ for_each = local.deploy_project_ids
135
+ project = each.value
136
+ dataset_id = google_bigquery_dataset.telemetry_dataset[each.key].dataset_id
137
+ table_id = "completions"
138
+ deletion_protection = false
139
+
140
+ external_data_configuration {
141
+ autodetect = false
142
+ source_format = "NEWLINE_DELIMITED_JSON"
143
+ source_uris = ["gs://${google_storage_bucket.logs_data_bucket[each.value].name}/completions/*"]
144
+ connection_id = google_bigquery_connection.genai_telemetry_connection[each.key].name
145
+ ignore_unknown_values = true
146
+ max_bad_records = 1000
147
+ }
148
+
149
+ # Schema matching the ADK completions format
150
+ schema = jsonencode([
151
+ {
152
+ name = "parts"
153
+ type = "RECORD"
154
+ mode = "REPEATED"
155
+ fields = [
156
+ { name = "type", type = "STRING", mode = "NULLABLE" },
157
+ { name = "content", type = "STRING", mode = "NULLABLE" },
158
+ { name = "mime_type", type = "STRING", mode = "NULLABLE" },
159
+ { name = "uri", type = "STRING", mode = "NULLABLE" },
160
+ { name = "data", type = "BYTES", mode = "NULLABLE" },
161
+ { name = "id", type = "STRING", mode = "NULLABLE" },
162
+ { name = "name", type = "STRING", mode = "NULLABLE" },
163
+ { name = "arguments", type = "JSON", mode = "NULLABLE" },
164
+ { name = "response", type = "JSON", mode = "NULLABLE" }
165
+ ]
166
+ },
167
+ { name = "role", type = "STRING", mode = "NULLABLE" },
168
+ { name = "index", type = "INTEGER", mode = "NULLABLE" }
169
+ ])
170
+
171
+ depends_on = [
172
+ google_storage_bucket.logs_data_bucket,
173
+ google_bigquery_connection.genai_telemetry_connection,
174
+ google_storage_bucket_iam_member.telemetry_connection_access
175
+ ]
176
+ }
177
+
178
+ # ====================================================================
179
+ # Completions View (Joins Logs with GCS Data)
180
+ # ====================================================================
181
+
182
+ # View that joins Cloud Logging data with GCS-stored completions data
183
+ resource "google_bigquery_table" "completions_view" {
184
+ for_each = local.deploy_project_ids
185
+ project = each.value
186
+ dataset_id = google_bigquery_dataset.telemetry_dataset[each.key].dataset_id
187
+ table_id = "completions_view"
188
+ description = "View of GenAI completion logs joined with the GCS prompt/response external table"
189
+ deletion_protection = false
190
+
191
+ view {
192
+ query = templatefile("${path.module}/sql/completions.sql", {
193
+ project_id = each.value
194
+ dataset_id = google_bigquery_dataset.telemetry_dataset[each.key].dataset_id
195
+ completions_external_table = google_bigquery_table.completions_external_table[each.key].table_id
196
+ logs_link_id = google_logging_linked_dataset.genai_logs_linked_dataset[each.key].link_id
197
+ })
198
+ use_legacy_sql = false
199
+ }
200
+
201
+ depends_on = [
202
+ google_logging_linked_dataset.genai_logs_linked_dataset,
203
+ google_bigquery_table.completions_external_table,
204
+ time_sleep.wait_for_linked_dataset
205
+ ]
206
+ }
@@ -9,10 +9,9 @@ dependencies = [
9
9
  {%- for dep in cookiecutter.extra_dependencies %}
10
10
  "{{ dep }}",
11
11
  {%- endfor %}
12
- "opentelemetry-exporter-gcp-trace>=1.9.0,<2.0.0",
13
- {%- if not cookiecutter.is_adk %}
14
- "langchain-core~=0.3.9",
15
- "traceloop-sdk~=0.38.7",
12
+ {%- if cookiecutter.is_adk %}
13
+ "opentelemetry-instrumentation-google-genai>=0.1.0,<1.0.0",
14
+ "gcsfs>=2024.11.0",
16
15
  {%- endif %}
17
16
  "google-cloud-logging>=3.12.0,<4.0.0",
18
17
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
@@ -22,14 +21,11 @@ dependencies = [
22
21
  "psycopg2-binary>=2.9.10,<3.0.0",
23
22
  {%- elif cookiecutter.deployment_target == 'agent_engine' %}
24
23
  "google-cloud-aiplatform[evaluation,agent-engines]>=1.118.0,<2.0.0",
25
- "protobuf>=6.31.1,<7.0.0"
24
+ "protobuf>=6.31.1,<7.0.0",
26
25
  {%- endif %}
27
26
  ]
28
- {% if cookiecutter.deployment_target == 'cloud_run' %}
29
27
  requires-python = ">=3.10,<3.14"
30
- {% elif cookiecutter.deployment_target == 'agent_engine' %}
31
- requires-python = ">=3.10,<3.13"
32
- {%- endif %}
28
+
33
29
 
34
30
  [dependency-groups]
35
31
  dev = [
@@ -39,14 +35,6 @@ dev = [
39
35
  ]
40
36
 
41
37
  [project.optional-dependencies]
42
- {% if not cookiecutter.is_adk %}
43
- streamlit = [
44
- "streamlit>=1.42.0,<2.0.0",
45
- "streamlit-extras>=0.4.3,<1.0.0",
46
- "extra-streamlit-components>=0.1.71,<1.0.0",
47
- "streamlit-feedback>=0.1.3,<1.0.0",
48
- ]
49
- {% endif %}
50
38
  jupyter = [
51
39
  "jupyter>=1.0.0,<2.0.0",
52
40
  ]
@@ -69,6 +69,14 @@ jobs:
69
69
  run: |
70
70
  pip install uv==0.8.13
71
71
  uv sync --locked
72
+ {%- if cookiecutter.is_a2a %}
73
+
74
+ - name: Extract version from pyproject.toml
75
+ id: extract-version
76
+ run: |
77
+ VERSION=$(awk -F'"' '/^version = / {print $2}' pyproject.toml || echo '0.0.0')
78
+ echo "version=${VERSION}" >> $GITHUB_OUTPUT
79
+ {%- endif %}
72
80
  {%- endif %}
73
81
 
74
82
  {%- if cookiecutter.data_ingestion %}
@@ -107,11 +115,18 @@ jobs:
107
115
 
108
116
  - name: Deploy to Production (Agent Engine)
109
117
  run: |
110
- uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > .requirements.txt
111
- uv run {{cookiecutter.agent_directory}}/agent_engine_app.py \
118
+ {%- if cookiecutter.is_a2a %}
119
+ AGENT_VERSION={% raw %}${{ steps.extract-version.outputs.version }}{% endraw %}
120
+ {%- endif %}
121
+ uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > {{cookiecutter.agent_directory}}/app_utils/.requirements.txt
122
+ uv run python -m {{cookiecutter.agent_directory}}.app_utils.deploy \
112
123
  --project {% raw %}${{ vars.PROD_PROJECT_ID }}{% endraw %} \
113
124
  --location {% raw %}${{ vars.REGION }}{% endraw %} \
114
- --artifacts-bucket-name {% raw %}${{ vars.LOGS_BUCKET_NAME_PROD }}{% endraw %} \
115
- --set-env-vars="COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID={% raw %}${{ vars.DATA_STORE_ID_PROD }}{% endraw %},DATA_STORE_REGION={% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX={% raw %}${{ vars.VECTOR_SEARCH_INDEX_PROD }}{% endraw %},VECTOR_SEARCH_INDEX_ENDPOINT={% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_PROD }}{% endraw %},VECTOR_SEARCH_BUCKET={% raw %}${{ vars.VECTOR_SEARCH_BUCKET_PROD }}{% endraw %}{%- endif %}{%- endif %}"
125
+ --source-packages=./{{cookiecutter.agent_directory}} \
126
+ --entrypoint-module={{cookiecutter.agent_directory}}.agent_engine_app \
127
+ --entrypoint-object=agent_engine \
128
+ --requirements-file={{cookiecutter.agent_directory}}/app_utils/.requirements.txt \
129
+ --service-account={% raw %}${{ vars.APP_SERVICE_ACCOUNT_PROD }}{% endraw %} \
130
+ --set-env-vars="COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %}{%- if cookiecutter.is_a2a %},AGENT_VERSION=$AGENT_VERSION{%- endif %},LOGS_BUCKET_NAME={% raw %}${{ vars.LOGS_BUCKET_NAME_PROD }}{% endraw %}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID={% raw %}${{ vars.DATA_STORE_ID_PROD }}{% endraw %},DATA_STORE_REGION={% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX={% raw %}${{ vars.VECTOR_SEARCH_INDEX_PROD }}{% endraw %},VECTOR_SEARCH_INDEX_ENDPOINT={% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_PROD }}{% endraw %},VECTOR_SEARCH_BUCKET={% raw %}${{ vars.VECTOR_SEARCH_BUCKET_PROD }}{% endraw %}{%- endif %}{%- endif %}"
116
131
  {%- endif %}
117
132
 
@@ -81,11 +81,23 @@ jobs:
81
81
  - name: Configure Docker for Artifact Registry
82
82
  run: |
83
83
  gcloud auth configure-docker {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev --quiet
84
-
84
+ {%- if cookiecutter.is_a2a %}
85
+
86
+ - name: Extract version from pyproject.toml
87
+ id: extract-version
88
+ run: |
89
+ VERSION=$(awk -F'"' '/^version = / {print $2}' pyproject.toml || echo '0.0.0')
90
+ echo "version=${VERSION}" >> $GITHUB_OUTPUT
91
+ {%- endif %}
92
+
85
93
  - name: Build and Push Docker Image
86
94
  run: |
87
95
  docker build -t {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev/{% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}/{% raw %}${{ vars.ARTIFACT_REGISTRY_REPO_NAME }}{% endraw %}/{% raw %}${{ vars.CONTAINER_NAME }}{% endraw %} \
88
- --build-arg COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %} .
96
+ --build-arg COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %} \
97
+ {%- if cookiecutter.is_a2a %}
98
+ --build-arg AGENT_VERSION={% raw %}${{ steps.extract-version.outputs.version }}{% endraw %} \
99
+ {%- endif %}
100
+ .
89
101
  docker push {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev/{% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}/{% raw %}${{ vars.ARTIFACT_REGISTRY_REPO_NAME }}{% endraw %}/{% raw %}${{ vars.CONTAINER_NAME }}{% endraw %}
90
102
 
91
103
  - name: Deploy to Staging (Cloud Run)
@@ -115,15 +127,28 @@ jobs:
115
127
  run: |
116
128
  pip install uv==0.8.13
117
129
  uv sync --locked
130
+ {%- if cookiecutter.is_a2a %}
131
+
132
+ - name: Extract version from pyproject.toml
133
+ id: extract-version
134
+ run: |
135
+ VERSION=$(awk -F'"' '/^version = / {print $2}' pyproject.toml || echo '0.0.0')
136
+ echo "version=${VERSION}" >> $GITHUB_OUTPUT
137
+ echo "Extracted version: ${VERSION}"
138
+ {%- endif %}
118
139
 
119
140
  - name: Deploy to Staging (Agent Engine)
120
141
  run: |
121
- uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > .requirements.txt
122
- uv run {{cookiecutter.agent_directory}}/agent_engine_app.py \
142
+ uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > {{cookiecutter.agent_directory}}/app_utils/.requirements.txt
143
+ uv run python -m {{cookiecutter.agent_directory}}.app_utils.deploy \
123
144
  --project {% raw %}${{ vars.STAGING_PROJECT_ID }}{% endraw %} \
124
145
  --location {% raw %}${{ vars.REGION }}{% endraw %} \
125
- --artifacts-bucket-name {% raw %}${{ vars.LOGS_BUCKET_NAME_STAGING }}{% endraw %} \
126
- --set-env-vars="COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID={% raw %}${{ vars.DATA_STORE_ID_STAGING }}{% endraw %},DATA_STORE_REGION={% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX={% raw %}${{ vars.VECTOR_SEARCH_INDEX_STAGING }}{% endraw %},VECTOR_SEARCH_INDEX_ENDPOINT={% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_STAGING }}{% endraw %},VECTOR_SEARCH_BUCKET={% raw %}${{ vars.VECTOR_SEARCH_BUCKET_STAGING }}{% endraw %}{%- endif %}{%- endif %}"
146
+ --source-packages=./{{cookiecutter.agent_directory}} \
147
+ --entrypoint-module={{cookiecutter.agent_directory}}.agent_engine_app \
148
+ --entrypoint-object=agent_engine \
149
+ --requirements-file={{cookiecutter.agent_directory}}/app_utils/.requirements.txt \
150
+ --service-account={% raw %}${{ vars.APP_SERVICE_ACCOUNT_STAGING }}{% endraw %} \
151
+ --set-env-vars="COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %}{%- if cookiecutter.is_a2a %},AGENT_VERSION={% raw %}${{ steps.extract-version.outputs.version }}{% endraw %}{%- endif %},LOGS_BUCKET_NAME={% raw %}${{ vars.LOGS_BUCKET_NAME_STAGING }}{% endraw %}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID={% raw %}${{ vars.DATA_STORE_ID_STAGING }}{% endraw %},DATA_STORE_REGION={% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX={% raw %}${{ vars.VECTOR_SEARCH_INDEX_STAGING }}{% endraw %},VECTOR_SEARCH_INDEX_ENDPOINT={% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_STAGING }}{% endraw %},VECTOR_SEARCH_BUCKET={% raw %}${{ vars.VECTOR_SEARCH_BUCKET_STAGING }}{% endraw %}{%- endif %}{%- endif %}"
127
152
 
128
153
  - name: Fetch Auth Token
129
154
  id: fetch-token
@@ -174,7 +199,7 @@ jobs:
174
199
  {%- elif cookiecutter.deployment_target == 'cloud_run' %}
175
200
  export _ID_TOKEN="{% raw %}${{ steps.fetch-token.outputs._id_token }}{% endraw %}"
176
201
  export _STAGING_URL="{% raw %}${{ steps.fetch-url.outputs._staging_url }}{% endraw %}"
177
- pip install locust==2.31.1
202
+ pip install locust==2.31.1{%- if cookiecutter.is_a2a %} a2a-sdk~=0.3.9{%- endif %}
178
203
  locust -f tests/load_test/load_test.py \
179
204
  --headless \
180
205
  -H ${_STAGING_URL} \
@@ -183,7 +208,7 @@ jobs:
183
208
  --html=tests/load_test/.results/report.html
184
209
  {%- elif cookiecutter.deployment_target == 'agent_engine' and cookiecutter.is_adk_live %}
185
210
  # Start expose app in remote mode (uses deployment_metadata.json by default)
186
- uv run python -m {{cookiecutter.agent_directory}}.utils.expose_app --mode remote &
211
+ uv run python -m {{cookiecutter.agent_directory}}.app_utils.expose_app --mode remote &
187
212
  EXPOSE_PID=$!
188
213
 
189
214
  # Wait for expose app to be ready
@@ -219,10 +244,10 @@ jobs:
219
244
  - name: Export Load Test Results to GCS
220
245
  run: |
221
246
  TIMESTAMP=$(date +%Y%m%d-%H%M%S)
222
- gcloud storage cp --recursive tests/load_test/.results gs://{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP} --quiet
247
+ gcloud storage cp --recursive tests/load_test/.results gs://{% raw %}${{ vars.LOGS_BUCKET_NAME_STAGING }}{% endraw %}/load-test-results/results-${TIMESTAMP} --quiet
223
248
  echo "_________________________________________________________________________"
224
- echo "Load test results copied to gs://{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP}"
225
- echo "HTTP link: https://console.cloud.google.com/storage/browser/{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP}"
249
+ echo "Load test results copied to gs://{% raw %}${{ vars.LOGS_BUCKET_NAME_STAGING }}{% endraw %}/load-test-results/results-${TIMESTAMP}"
250
+ echo "HTTP link: https://console.cloud.google.com/storage/browser/{% raw %}${{ vars.LOGS_BUCKET_NAME_STAGING }}{% endraw %}/load-test-results/results-${TIMESTAMP}"
226
251
  echo "_________________________________________________________________________"
227
252
 
228
253
  call_production_workflow:
@@ -42,7 +42,7 @@ steps:
42
42
  {%- endif %}
43
43
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
44
44
 
45
- - name: "gcr.io/cloud-builders/gcloud"
45
+ - name: "gcr.io/cloud-builders/gcloud-slim"
46
46
  id: trigger-deployment
47
47
  entrypoint: gcloud
48
48
  args:
@@ -57,6 +57,18 @@ steps:
57
57
  - $_PROD_PROJECT_ID
58
58
 
59
59
  {%- elif cookiecutter.deployment_target == 'agent_engine' %}
60
+ {%- if cookiecutter.is_a2a %}
61
+ # Extract version from pyproject.toml
62
+ - name: "gcr.io/cloud-builders/gcloud-slim"
63
+ id: extract-version
64
+ entrypoint: /bin/bash
65
+ args:
66
+ - "-c"
67
+ - |
68
+ VERSION=$(awk -F'"' '/^version = / {print $$2}' pyproject.toml || echo '0.0.0')
69
+ echo "$${VERSION}" > /workspace/agent_version.txt
70
+
71
+ {%- endif %}
60
72
  - name: "python:3.12-slim"
61
73
  id: install-dependencies
62
74
  entrypoint: /bin/bash
@@ -73,12 +85,19 @@ steps:
73
85
  args:
74
86
  - "-c"
75
87
  - |
76
- uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > .requirements.txt
77
- uv run {{cookiecutter.agent_directory}}/agent_engine_app.py \
88
+ {%- if cookiecutter.is_a2a %}
89
+ AGENT_VERSION=$(cat /workspace/agent_version.txt || echo '0.0.0')
90
+ {%- endif %}
91
+ uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > {{cookiecutter.agent_directory}}/app_utils/.requirements.txt
92
+ uv run python -m {{cookiecutter.agent_directory}}.app_utils.deploy \
78
93
  --project ${_PROD_PROJECT_ID} \
79
94
  --location ${_REGION} \
80
- --artifacts-bucket-name ${_LOGS_BUCKET_NAME_PROD} \
81
- --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID_PROD},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_PROD},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_PROD},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_PROD}{%- endif %}{%- endif %}"
95
+ --source-packages=./{{cookiecutter.agent_directory}} \
96
+ --entrypoint-module={{cookiecutter.agent_directory}}.agent_engine_app \
97
+ --entrypoint-object=agent_engine \
98
+ --requirements-file={{cookiecutter.agent_directory}}/app_utils/.requirements.txt \
99
+ --service-account=${_APP_SERVICE_ACCOUNT_PROD} \
100
+ --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.is_a2a %},AGENT_VERSION=$${AGENT_VERSION}{%- endif %},LOGS_BUCKET_NAME=${_LOGS_BUCKET_NAME_PROD}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID_PROD},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_PROD},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_PROD},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_PROD}{%- endif %}{%- endif %}"
82
101
  env:
83
102
  - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin'
84
103
  {%- endif %}