agent-starter-pack 0.15.0__py3-none-any.whl → 0.15.2__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.

Potentially problematic release.


This version of agent-starter-pack might be problematic. Click here for more details.

Files changed (25) hide show
  1. {agent_starter_pack-0.15.0.dist-info → agent_starter_pack-0.15.2.dist-info}/METADATA +1 -1
  2. {agent_starter_pack-0.15.0.dist-info → agent_starter_pack-0.15.2.dist-info}/RECORD +25 -25
  3. agents/adk_base/.template/templateconfig.yaml +1 -1
  4. agents/adk_base/README.md +1 -1
  5. agents/adk_base/notebooks/adk_app_testing.ipynb +16 -10
  6. agents/agentic_rag/.template/templateconfig.yaml +1 -1
  7. agents/agentic_rag/notebooks/adk_app_testing.ipynb +16 -10
  8. agents/live_api/.template/templateconfig.yaml +1 -1
  9. src/base_template/pyproject.toml +2 -2
  10. src/cli/commands/enhance.py +170 -78
  11. src/cli/utils/gcp.py +1 -1
  12. src/cli/utils/template.py +35 -2
  13. src/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +6 -0
  14. src/resources/locks/uv-adk_base-agent_engine.lock +385 -271
  15. src/resources/locks/uv-adk_base-cloud_run.lock +439 -310
  16. src/resources/locks/uv-agentic_rag-agent_engine.lock +418 -304
  17. src/resources/locks/uv-agentic_rag-cloud_run.lock +488 -359
  18. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +412 -404
  19. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +511 -488
  20. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +343 -334
  21. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +445 -421
  22. src/resources/locks/uv-live_api-cloud_run.lock +398 -373
  23. {agent_starter_pack-0.15.0.dist-info → agent_starter_pack-0.15.2.dist-info}/WHEEL +0 -0
  24. {agent_starter_pack-0.15.0.dist-info → agent_starter_pack-0.15.2.dist-info}/entry_points.txt +0 -0
  25. {agent_starter_pack-0.15.0.dist-info → agent_starter_pack-0.15.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-starter-pack
3
- Version: 0.15.0
3
+ Version: 0.15.2
4
4
  Summary: CLI to bootstrap production-ready Google Cloud GenAI agent projects from templates.
5
5
  Author-email: Google LLC <agent-starter-pack@google.com>
6
6
  License: Apache-2.0
@@ -1,18 +1,18 @@
1
1
  agents/README.md,sha256=L8__lIXXjxLTZbkCmTC4taTFUMRVrO3QI2mCKZTdhJM,462
2
- agents/adk_base/README.md,sha256=eLf-F9Z4u_mQOchAnUaSrOAHXRSx8wUQN29kkwz1SF4,894
3
- agents/adk_base/.template/templateconfig.yaml,sha256=8mQ_IIgC0h4eiTUM7FEIPSxwI73aenspcHsnqUb4AfY,923
2
+ agents/adk_base/README.md,sha256=_rnoIkHupZ4afDZEAtrDZzeYSS4WqtJWnvtX2H-RrCM,894
3
+ agents/adk_base/.template/templateconfig.yaml,sha256=OwPdd3NoOpT4WpnlOHM5tk_PFdptDdqnS3v7UdwjeOQ,924
4
4
  agents/adk_base/app/__init__.py,sha256=wT1TtenBOdA4LTtf6mQjvAT5aRR1N2PCx_A-MrDLGsg,631
5
5
  agents/adk_base/app/agent.py,sha256=6Q6QegQDxEaAck989DPIb3ArHMZtw_YJBqhHFqg-UjQ,2182
6
- agents/adk_base/notebooks/adk_app_testing.ipynb,sha256=81L1kbeUlkC3DpTY9nGyB8h5ezCdEeNCVHkBPyG0fgc,10497
6
+ agents/adk_base/notebooks/adk_app_testing.ipynb,sha256=hyPBwXOmZBWu1Dte6lUU0LDW_vV2VA57yQZ3AjBMzDU,10729
7
7
  agents/adk_base/notebooks/evaluating_adk_agent.ipynb,sha256=SdZC1htgXtXw3oyi8d70dNVpDgUmV9T5hqiwGxM9plk,57034
8
8
  agents/adk_base/tests/integration/test_agent.py,sha256=_zb3GMWMtMRq2rOyYC-uL1eNhpg2XBkm8Noj0O_UOng,1998
9
9
  agents/agentic_rag/README.md,sha256=cPeY_XGt79ava22PIM0x92oi67R-TnlEKBQGpK1MOkA,2262
10
- agents/agentic_rag/.template/templateconfig.yaml,sha256=Gfw3FOjj3XNxoXn6WGwC2PG59f4qB3p2cYTQ49ykvJc,1248
10
+ agents/agentic_rag/.template/templateconfig.yaml,sha256=o8D1Yx7zWsIgI1zVOS3K1pDgc_Lczevw6cveaj2T7HQ,1249
11
11
  agents/agentic_rag/app/__init__.py,sha256=wT1TtenBOdA4LTtf6mQjvAT5aRR1N2PCx_A-MrDLGsg,631
12
12
  agents/agentic_rag/app/agent.py,sha256=joSAfrVcS9eRtOT3MXPSoiwElpwVq-hjpCHkqTj6vuM,4041
13
13
  agents/agentic_rag/app/retrievers.py,sha256=qfxwSEixMddvAu4FvUTZAFh1Gdp3RPY65s0Wp6gEFVk,4561
14
14
  agents/agentic_rag/app/templates.py,sha256=8N_uRchwiN7hlH9Y8rdJ1CAtOhpHUWZkXZZ7IU-YJJk,867
15
- agents/agentic_rag/notebooks/adk_app_testing.ipynb,sha256=81L1kbeUlkC3DpTY9nGyB8h5ezCdEeNCVHkBPyG0fgc,10497
15
+ agents/agentic_rag/notebooks/adk_app_testing.ipynb,sha256=hyPBwXOmZBWu1Dte6lUU0LDW_vV2VA57yQZ3AjBMzDU,10729
16
16
  agents/agentic_rag/notebooks/evaluating_adk_agent.ipynb,sha256=SdZC1htgXtXw3oyi8d70dNVpDgUmV9T5hqiwGxM9plk,57034
17
17
  agents/agentic_rag/tests/integration/test_agent.py,sha256=YcwOZXa9uJqcqZN8UPikNm_dlSh9XduEfcuQa0wkby8,2170
18
18
  agents/crewai_coding_crew/README.md,sha256=4No7sfHQVHELARGiT3fWANJzDR0NP48ow4ct3FoPwlA,1672
@@ -30,7 +30,7 @@ agents/langgraph_base_react/app/agent.py,sha256=yzCc5JaOJgItoBiZOzHPiSy9aD2HGeGI
30
30
  agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb,sha256=PlW41fL-ji9NKkimW6u25YRLGWN2pgoX2G8w5nzIEPE,58737
31
31
  agents/langgraph_base_react/tests/integration/test_agent.py,sha256=xy0A_3eGhxM8A5rc81revMztJN5GtFA-o5-CG5JzeQw,1630
32
32
  agents/live_api/README.md,sha256=c3lu5WguOUBc5hO_UtNZfVhfYxvSzMXuGFICn9M38mU,2897
33
- agents/live_api/.template/templateconfig.yaml,sha256=DD_hihMsuqmd5VWS18vVGZ3ZGVVpFWVXJ2dU07eKb6k,964
33
+ agents/live_api/.template/templateconfig.yaml,sha256=Y_UQcxq5ql2YPrC5kd-SK7kfGb6Q6IqScaNDRv-vG5I,964
34
34
  agents/live_api/app/agent.py,sha256=dYE2qd64OhL-fOgwzrjqN50LYXAgJ1TWbx6ohqtV5Rc,2434
35
35
  agents/live_api/tests/integration/test_server_e2e.py,sha256=SBowHiVj-_Okbk1dqyITFVIG6yvr5BGNrfxHVpO4TFs,8635
36
36
  agents/live_api/tests/load_test/load_test.py,sha256=HHZyfC4gqiQtZVF_CbbxENGgWQccMLpwMv0IdoQ6cbQ,1275
@@ -40,7 +40,7 @@ src/base_template/.gitignore,sha256=Fq0w34x4sfbwP4RqDqh6hdHNYRUEsFNI-9XONzLWBIs,
40
40
  src/base_template/GEMINI.md,sha256=WzscHWlQeYkKORZ-453P8KM9IHuj1kAxW-69c7Ytuwk,133
41
41
  src/base_template/Makefile,sha256=1UKB6rlIbGStc-hUfnwKanOtxhz-vzaKxrCxTlPilqs,8087
42
42
  src/base_template/README.md,sha256=_TjEIWOK75GfaG3qfaOQdfC9J5AlPo_dckRY7e84dlM,10184
43
- src/base_template/pyproject.toml,sha256=HsLasS9vm6PZi7BiGrHe0tgBnwvgafa4eIj4k1P3DCU,2940
43
+ src/base_template/pyproject.toml,sha256=Ch69IVTRzNn9zueU5TunZjb-dTmvCM_G_NwXDFUiIp8,2940
44
44
  src/base_template/deployment/README.md,sha256=gZJvSWdQh_Mi-bZ3dmuPv7fMezIw04fgN5tq7KgglPw,692
45
45
  src/base_template/deployment/terraform/apis.tf,sha256=KX8Oe2gjT-gh9Bkntz9yIAyRjPc1gZvwOhroJ6NZVp4,1513
46
46
  src/base_template/deployment/terraform/github.tf,sha256=KhfNBAzeUH9jDr8FOw_DiypesA5AEC8IZT1PRqntSt8,10838
@@ -73,16 +73,16 @@ src/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py,sha256=2rv1U
73
73
  src/base_template/{{cookiecutter.agent_directory}}/utils/typing.py,sha256=DP5OZC3IGvqA1XbvWt8kI3gyAK3ZjzUSL5Ca17wNeLI,4249
74
74
  src/cli/main.py,sha256=Dya7Sw3ozMTaGDcwMh_-W7udkGZHGzgAj8aBdSZaZxI,1832
75
75
  src/cli/commands/create.py,sha256=R1KKf419Wd2QMi98LrVgm68OyaHKFd0rtm5P3_SIZhI,46779
76
- src/cli/commands/enhance.py,sha256=6_daqd0te1vj0eMrsyQwr9psr0d1PKU1UEVya8KOcy8,19472
76
+ src/cli/commands/enhance.py,sha256=AF58CFikNLPib8PULKkzM6r9JGXkTvRWspBaEvGnR3k,24237
77
77
  src/cli/commands/list.py,sha256=ZGol9eYB9Yon7JysMUCtpEOwdXzrApdTHzErx6KvT04,6856
78
78
  src/cli/commands/setup_cicd.py,sha256=3BtHChOPvp0I-4tlPqwz5hZFm13gtw9gvlWQwF-F7oE,32492
79
79
  src/cli/utils/__init__.py,sha256=_cTmsXGPqOtK0q8UW5164QTltbJRJFR_Efxq_BRL1-o,1311
80
80
  src/cli/utils/cicd.py,sha256=l9hPdqFXo5SxdtOG1yEoQdmRff5vNcqf0sqxBTtPQig,30704
81
81
  src/cli/utils/datastores.py,sha256=gv1V6eDcOEKx4MRNG5C3Y-VfixYq1AzQuaYMLp8QRNo,1058
82
- src/cli/utils/gcp.py,sha256=_Eq2bsNVS_Npj6ZPzjZA1J6SCu2srGUgsrgu1mIhKh0,9261
82
+ src/cli/utils/gcp.py,sha256=wGgTOc1EWuq7FIHyXa80OUgE1ypGm7zwMF-dvI0jDOE,9261
83
83
  src/cli/utils/logging.py,sha256=61ulUY1hUrpxHDFi0szqsjPlrpxdBvwzfYEEV0o97GA,3530
84
84
  src/cli/utils/remote_template.py,sha256=ITN1a5GQmVIb1dHpExPLTz1k5c9j7M6fF-HXUDCl6i8,23967
85
- src/cli/utils/template.py,sha256=wvd-bLus_Z_SNFh_F9A5eqGWKGe74ZkbpQOlMrrp5Ek,50876
85
+ src/cli/utils/template.py,sha256=YIJu0xZJTyP0XmyNN08Fj7Wc7Wl9ROT45rcZvsvgLb0,52108
86
86
  src/cli/utils/version.py,sha256=F4udQmzniPStqWZFIgnv3Qg3l9non4mfy2An-Oveqmc,2916
87
87
  src/data_ingestion/README.md,sha256=LNxSQoJW9JozK-TbyGQLj5L_MGWNwrfLk6V6RmQ2oBQ,4032
88
88
  src/data_ingestion/pyproject.toml,sha256=-1Mf2QB8K70ICQV5UPZDpf-fN3UwEQLVzQyxfakCSTY,445
@@ -97,7 +97,7 @@ src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py,s
97
97
  src/deployment_targets/agent_engine/tests/load_test/README.md,sha256=aQP7nDAqd2jKBET4noI39HC9PVHpgpned7cxucWpVJo,1302
98
98
  src/deployment_targets/agent_engine/tests/load_test/load_test.py,sha256=VbQjm8uR8JsdJe3upO1eUIz5SZR7IQsHYyJy88cAjy0,4516
99
99
  src/deployment_targets/agent_engine/tests/load_test/.results/.placeholder,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
- src/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py,sha256=G2X3hY5i1MqFxL6rQpxITZYaLT_mGHIfVh_FiKiziFY,12718
100
+ src/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py,sha256=cjrqlRR9ORt42Sb_snSFmNQEj6egWkJrL6l2divhmAk,12876
101
101
  src/deployment_targets/cloud_run/Dockerfile,sha256=rSpmFK7uJhZYwYMtxH8W7mywcCPvaoFn7gL_mXRYuF8,1449
102
102
  src/deployment_targets/cloud_run/deployment/terraform/service.tf,sha256=09F6jkkMtoQlbQNdzJl8OZs-ZlfmzZmgCaUFvniJnlQ,11146
103
103
  src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf,sha256=l6fG-kMyYOOrRwnsUys_Vq46-76bMiRyXzHYkVD2XFM,6993
@@ -156,20 +156,20 @@ src/resources/docs/adk-cheatsheet.md,sha256=9VZpM5bG3pJq4PbNfym7LOLzgeLZfqkAGA0Y
156
156
  src/resources/idx/idx-template.json,sha256=07OQZCPp45Iqor2O7Tm1e1Gmsdd-AmmUofSvA7y-oRs,793
157
157
  src/resources/idx/idx-template.nix,sha256=sesHGev_PYtVDg0J5tHkg0OO7IR1Bz2iAtl_if3Ar3M,892
158
158
  src/resources/idx/.idx/dev.nix,sha256=XQ4T1xt5I-8SVwnI37v56RFFlxa58Ko-a9G2-oelYAI,1602
159
- src/resources/locks/uv-adk_base-agent_engine.lock,sha256=qFMwabOGCC6xVimE1UxtFuSO-fDyG6Bb1tGFSHTve0k,560006
160
- src/resources/locks/uv-adk_base-cloud_run.lock,sha256=QaNqo7hkJtAI1fEQe3px8kPadYCAM6PTV2w0GPgCtj8,740330
161
- src/resources/locks/uv-agentic_rag-agent_engine.lock,sha256=hysVuh-LMUV0zeEjOy4qN2pwxj6y2TvmudEcLe02hJI,629087
162
- src/resources/locks/uv-agentic_rag-cloud_run.lock,sha256=dK3burkuPD-WbUQ-eb6AVnodYdtIHeEZtettbm5KsXc,833605
163
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock,sha256=GWlR1nTnoFnM3djQ2HJBfPpZVINX8mrM3-sBglONZHo,932027
164
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock,sha256=ZmU5X8qsSFRdIMS1Wjq-QL48EqtEehUhS1RdNINZ4iw,1226879
165
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock,sha256=PPQjq6WOwuKDYo2TtGfFr9HmrOkAXEeKzDGnfhZ3QGY,797526
166
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock,sha256=E3qF-qnLPNfHTH_VajbD1V0nWDB_ePeGUo3fT-J11pY,1055674
167
- src/resources/locks/uv-live_api-cloud_run.lock,sha256=GDYYBrnGgZWBsCZm8dtP3iBNToyT1Wkn7cLeDg1zdkc,962006
159
+ src/resources/locks/uv-adk_base-agent_engine.lock,sha256=3vxRrbyJ0ySW_VqjCL3RLFKAuZpYw4CYcL2CjgJWEVI,567595
160
+ src/resources/locks/uv-adk_base-cloud_run.lock,sha256=2A1nvhxumnphEbs3jhbPPc3yqU7XJn7g01pEygsZQVQ,752779
161
+ src/resources/locks/uv-agentic_rag-agent_engine.lock,sha256=j6GtLqMEjBPrMHLbYBP7Tx8u92Ubq8wm-QfvbvpVnOg,636673
162
+ src/resources/locks/uv-agentic_rag-cloud_run.lock,sha256=NulH9sYfEV3hftBTkPFh0uSr-3Zwl4ojE0SeXiT6_KI,846052
163
+ src/resources/locks/uv-crewai_coding_crew-agent_engine.lock,sha256=fcwOoEXj0AGZxYvI_KFbO9t3Opq6KnaLIn3eCRASKB0,934190
164
+ src/resources/locks/uv-crewai_coding_crew-cloud_run.lock,sha256=iQiheltFkHQtF9tq992RiQyQKUx1hlaYs_qKMckuous,1233908
165
+ src/resources/locks/uv-langgraph_base_react-agent_engine.lock,sha256=qcsSMY-_lHe3Fy2iY9RwJd2lGXBVhx_lJItDZjh2xy0,800009
166
+ src/resources/locks/uv-langgraph_base_react-cloud_run.lock,sha256=WNSVBOeNpPi96j-1D6ONx7fLZaZOpHMsqwkVDTO_lOE,1063023
167
+ src/resources/locks/uv-live_api-cloud_run.lock,sha256=jrcrlnpJfJ6MIyEz1Z7qS_nxy0F035M-6C0D80VWCIo,969381
168
168
  src/utils/generate_locks.py,sha256=6V1B8V2BEuevWnXUsxZVTrLjXwFRII8UfsIGrQqZxVs,4320
169
169
  src/utils/lock_utils.py,sha256=IFOMUWtb-ypm2Y8w8J5y2oI_-MaPuwPF_JOAAlnNudA,2275
170
170
  src/utils/watch_and_rebuild.py,sha256=vP4yIiA7E_lj5sfQdJUl8TXas6V7msDg8XWUutAC05Q,6679
171
- agent_starter_pack-0.15.0.dist-info/METADATA,sha256=LAo7WXIjqDm1zmuvIexkEmVLkD4D56UqBdY3HkSSADE,11482
172
- agent_starter_pack-0.15.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
173
- agent_starter_pack-0.15.0.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
174
- agent_starter_pack-0.15.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
175
- agent_starter_pack-0.15.0.dist-info/RECORD,,
171
+ agent_starter_pack-0.15.2.dist-info/METADATA,sha256=ugrm2WVZ76bwlX4PT7tvySGXcFITiFHzauYm-IQP1Pw,11482
172
+ agent_starter_pack-0.15.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
173
+ agent_starter_pack-0.15.2.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
174
+ agent_starter_pack-0.15.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
175
+ agent_starter_pack-0.15.2.dist-info/RECORD,,
@@ -18,7 +18,7 @@ settings:
18
18
  requires_data_ingestion: false
19
19
  requires_session: true
20
20
  deployment_targets: ["agent_engine", "cloud_run"]
21
- extra_dependencies: ["google-adk~=1.8.0"]
21
+ extra_dependencies: ["google-adk~=1.14.0"]
22
22
  tags: ["adk"]
23
23
  frontend_type: "None"
24
24
 
agents/adk_base/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  A basic agent built using the **[Google Agent Development Kit (ADK)](https://google.github.io/adk-docs/)**. This example demonstrates core ADK concepts like agent creation and tool integration in a minimal setup.
6
6
 
7
- This agent uses the `gemini-2.0-flash` model and is equipped with two simple tools:
7
+ This agent uses the `gemini-2.5-flash` model and is equipped with two simple tools:
8
8
  * `get_weather`: Simulates fetching weather (hardcoded for SF).
9
9
  * `get_current_time`: Simulates fetching the time (hardcoded for SF).
10
10
 
@@ -4,15 +4,12 @@
4
4
  "cell_type": "markdown",
5
5
  "metadata": {},
6
6
  "source": [
7
- "# ADK Application Testing\n",
7
+ "# 🧪 ADK Application Testing\n",
8
8
  "\n",
9
9
  "This notebook demonstrates how to test an ADK (Agent Development Kit) application.\n",
10
10
  "It covers both local and remote testing, both with Agent Engine and Cloud Run.\n",
11
11
  "\n",
12
- "> **Note**: This notebook assumes that the agent files are stored in the `app` folder. If your agent files are located in a different directory, please update all relevant file paths and references accordingly.\n",
13
- "\n",
14
- "<img src=\"https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/adk_logo.png?raw=true\" width=\"400\">\n",
15
- "\n"
12
+ "> **Note**: This notebook assumes that the agent files are stored in the `app` folder. If your agent files are located in a different directory, please update all relevant file paths and references accordingly."
16
13
  ]
17
14
  },
18
15
  {
@@ -92,12 +89,21 @@
92
89
  "metadata": {},
93
90
  "outputs": [],
94
91
  "source": [
95
- "# Replace PROJECT_ID and ENGINE_ID with your values\n",
96
- "AGENT_ENGINE_ID = \"projects/PROJECT_ID/locations/us-central1/reasoningEngines/ENGINE_ID\"\n",
92
+ "# Set to None to auto-detect from ./deployment_metadata.json, or specify manually\n",
93
+ "# \"projects/PROJECT_ID/locations/us-central1/reasoningEngines/ENGINE_ID\"\n",
94
+ "REASONING_ENGINE_ID = None\n",
95
+ "\n",
96
+ "if REASONING_ENGINE_ID is None:\n",
97
+ " try:\n",
98
+ " with open(\"../deployment_metadata.json\") as f:\n",
99
+ " metadata = json.load(f)\n",
100
+ " REASONING_ENGINE_ID = metadata.get(\"remote_agent_engine_id\")\n",
101
+ " except (FileNotFoundError, json.JSONDecodeError):\n",
102
+ " pass\n",
97
103
  "\n",
104
+ "print(f\"Using REASONING_ENGINE_ID: {REASONING_ENGINE_ID}\")\n",
98
105
  "# Get the existing agent engine\n",
99
- "remote_agent_engine = client.agent_engines.get(name=AGENT_ENGINE_ID)\n",
100
- "print(f\"Retrieved agent engine: {remote_agent_engine.api_resource.name}\")"
106
+ "remote_agent_engine = client.agent_engines.get(name=REASONING_ENGINE_ID)"
101
107
  ]
102
108
  },
103
109
  {
@@ -354,7 +360,7 @@
354
360
  ],
355
361
  "metadata": {
356
362
  "kernelspec": {
357
- "display_name": "myagent-1757939450",
363
+ "display_name": "myagent-1758791726",
358
364
  "language": "python",
359
365
  "name": "python3"
360
366
  },
@@ -19,7 +19,7 @@ settings:
19
19
  requires_session: true
20
20
  deployment_targets: ["agent_engine", "cloud_run"]
21
21
  extra_dependencies: [
22
- "google-adk~=1.8.0",
22
+ "google-adk~=1.14.0",
23
23
  "langchain-google-vertexai~=2.0.7",
24
24
  "langchain~=0.3.24",
25
25
  "langchain-core~=0.3.55",
@@ -4,15 +4,12 @@
4
4
  "cell_type": "markdown",
5
5
  "metadata": {},
6
6
  "source": [
7
- "# ADK Application Testing\n",
7
+ "# 🧪 ADK Application Testing\n",
8
8
  "\n",
9
9
  "This notebook demonstrates how to test an ADK (Agent Development Kit) application.\n",
10
10
  "It covers both local and remote testing, both with Agent Engine and Cloud Run.\n",
11
11
  "\n",
12
- "> **Note**: This notebook assumes that the agent files are stored in the `app` folder. If your agent files are located in a different directory, please update all relevant file paths and references accordingly.\n",
13
- "\n",
14
- "<img src=\"https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/adk_logo.png?raw=true\" width=\"400\">\n",
15
- "\n"
12
+ "> **Note**: This notebook assumes that the agent files are stored in the `app` folder. If your agent files are located in a different directory, please update all relevant file paths and references accordingly."
16
13
  ]
17
14
  },
18
15
  {
@@ -92,12 +89,21 @@
92
89
  "metadata": {},
93
90
  "outputs": [],
94
91
  "source": [
95
- "# Replace PROJECT_ID and ENGINE_ID with your values\n",
96
- "AGENT_ENGINE_ID = \"projects/PROJECT_ID/locations/us-central1/reasoningEngines/ENGINE_ID\"\n",
92
+ "# Set to None to auto-detect from ./deployment_metadata.json, or specify manually\n",
93
+ "# \"projects/PROJECT_ID/locations/us-central1/reasoningEngines/ENGINE_ID\"\n",
94
+ "REASONING_ENGINE_ID = None\n",
95
+ "\n",
96
+ "if REASONING_ENGINE_ID is None:\n",
97
+ " try:\n",
98
+ " with open(\"../deployment_metadata.json\") as f:\n",
99
+ " metadata = json.load(f)\n",
100
+ " REASONING_ENGINE_ID = metadata.get(\"remote_agent_engine_id\")\n",
101
+ " except (FileNotFoundError, json.JSONDecodeError):\n",
102
+ " pass\n",
97
103
  "\n",
104
+ "print(f\"Using REASONING_ENGINE_ID: {REASONING_ENGINE_ID}\")\n",
98
105
  "# Get the existing agent engine\n",
99
- "remote_agent_engine = client.agent_engines.get(name=AGENT_ENGINE_ID)\n",
100
- "print(f\"Retrieved agent engine: {remote_agent_engine.api_resource.name}\")"
106
+ "remote_agent_engine = client.agent_engines.get(name=REASONING_ENGINE_ID)"
101
107
  ]
102
108
  },
103
109
  {
@@ -354,7 +360,7 @@
354
360
  ],
355
361
  "metadata": {
356
362
  "kernelspec": {
357
- "display_name": "myagent-1757939450",
363
+ "display_name": "myagent-1758791726",
358
364
  "language": "python",
359
365
  "name": "python3"
360
366
  },
@@ -19,6 +19,6 @@ settings:
19
19
  deployment_targets: ["cloud_run"]
20
20
  extra_dependencies: [
21
21
  "backoff~=2.2.1",
22
- "google-genai~=1.16.0",
22
+ "google-genai>=1.16.0",
23
23
  ]
24
24
  example_question: "What's the weather in San Francisco?"
@@ -16,12 +16,12 @@ dependencies = [
16
16
  {%- endif %}
17
17
  "google-cloud-logging>=3.12.0",
18
18
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
19
- "google-cloud-aiplatform[evaluation]~=1.113.0",
19
+ "google-cloud-aiplatform[evaluation]~=1.116.0",
20
20
  "fastapi~=0.115.8",
21
21
  "uvicorn~=0.34.0",
22
22
  "psycopg2-binary>=2.9.10",
23
23
  {%- elif cookiecutter.deployment_target == 'agent_engine' %}
24
- "google-cloud-aiplatform[evaluation,agent-engines]~=1.113.0"
24
+ "google-cloud-aiplatform[evaluation,agent-engines]~=1.116.0"
25
25
  {%- endif %}
26
26
  ]
27
27
  {% if cookiecutter.deployment_target == 'cloud_run' %}
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import pathlib
16
+ import re
16
17
  import sys
17
18
  from typing import Any
18
19
 
@@ -26,7 +27,7 @@ else:
26
27
  import tomli as tomllib
27
28
 
28
29
  from ..utils.logging import display_welcome_banner, handle_cli_error
29
- from ..utils.template import get_available_agents
30
+ from ..utils.template import get_available_agents, validate_agent_directory_name
30
31
  from .create import (
31
32
  create,
32
33
  get_available_base_templates,
@@ -96,82 +97,110 @@ def display_agent_directory_selection(
96
97
  current_dir: pathlib.Path, detected_directory: str
97
98
  ) -> str:
98
99
  """Display available directories and prompt for agent directory selection."""
99
- console.print()
100
- console.print("📁 [bold]Agent Directory Selection[/bold]")
101
- console.print()
102
- console.print("Choose where your agent code is located:")
103
-
104
- # Get all directories in the current path (excluding hidden and common non-agent dirs)
105
- available_dirs = [
106
- item.name
107
- for item in current_dir.iterdir()
108
- if (
109
- item.is_dir()
110
- and not item.name.startswith(".")
111
- and item.name not in _EXCLUDED_DIRS
112
- )
113
- ]
100
+ while True:
101
+ console.print()
102
+ console.print("📁 [bold]Agent Directory Selection[/bold]")
103
+ console.print()
104
+ console.print("Your project needs an agent directory containing:")
105
+ console.print(" • [cyan]agent.py[/cyan] file with your agent logic")
106
+ console.print(" • [cyan]root_agent[/cyan] variable defined in agent.py")
107
+ console.print()
108
+ console.print("Choose where your agent code is located:")
109
+
110
+ # Get all directories in the current path (excluding hidden and common non-agent dirs)
111
+ available_dirs = [
112
+ item.name
113
+ for item in current_dir.iterdir()
114
+ if (
115
+ item.is_dir()
116
+ and not item.name.startswith(".")
117
+ and item.name not in _EXCLUDED_DIRS
118
+ )
119
+ ]
114
120
 
115
- # Sort directories and create choices
116
- available_dirs.sort()
121
+ # Sort directories and create choices
122
+ available_dirs.sort()
117
123
 
118
- directory_choices = {}
119
- choice_num = 1
120
- default_choice = None
124
+ directory_choices = {}
125
+ choice_num = 1
126
+ default_choice = None
121
127
 
122
- # Only include the detected directory if it actually exists
123
- if detected_directory in available_dirs:
124
- directory_choices[choice_num] = detected_directory
125
- current_indicator = (
126
- " (detected)" if detected_directory != "app" else " (default)"
127
- )
128
- console.print(
129
- f" {choice_num}. [bold]{detected_directory}[/]{current_indicator}"
130
- )
131
- default_choice = choice_num
132
- choice_num += 1
133
- # Remove from available_dirs to avoid duplication
134
- available_dirs.remove(detected_directory)
135
-
136
- # Add other available directories
137
- for dir_name in available_dirs:
138
- directory_choices[choice_num] = dir_name
139
- # Check if this directory might contain agent code
140
- agent_files_exist = any((current_dir / dir_name).glob("*agent*.py"))
141
- hint = " (contains agent*.py)" if agent_files_exist else ""
142
- console.print(f" {choice_num}. [bold]{dir_name}[/]{hint}")
143
- if (
144
- default_choice is None
145
- ): # If no detected directory exists, use first available as default
128
+ # Only include the detected directory if it actually exists
129
+ if detected_directory in available_dirs:
130
+ directory_choices[choice_num] = detected_directory
131
+ current_indicator = (
132
+ " (detected)" if detected_directory != "app" else " (default)"
133
+ )
134
+ console.print(
135
+ f" {choice_num}. [bold]{detected_directory}[/]{current_indicator}"
136
+ )
146
137
  default_choice = choice_num
147
- choice_num += 1
148
-
149
- # Add option for custom directory
150
- custom_choice = choice_num
151
- directory_choices[custom_choice] = "__custom__"
152
- console.print(f" {custom_choice}. [bold]Enter custom directory name[/]")
153
-
154
- # If no directories found and no default set, default to custom option
155
- if default_choice is None:
156
- default_choice = custom_choice
138
+ choice_num += 1
139
+ # Remove from available_dirs to avoid duplication
140
+ available_dirs.remove(detected_directory)
141
+
142
+ # Add other available directories
143
+ for dir_name in available_dirs:
144
+ directory_choices[choice_num] = dir_name
145
+ # Check if this directory might contain agent code
146
+ agent_py_exists = (current_dir / dir_name / "agent.py").exists()
147
+ hint = " (has agent.py)" if agent_py_exists else ""
148
+ console.print(f" {choice_num}. [bold]{dir_name}[/]{hint}")
149
+ if (
150
+ default_choice is None
151
+ ): # If no detected directory exists, use first available as default
152
+ default_choice = choice_num
153
+ choice_num += 1
154
+
155
+ # Add option for custom directory
156
+ custom_choice = choice_num
157
+ directory_choices[custom_choice] = "__custom__"
158
+ console.print(f" {custom_choice}. [bold]Enter custom directory name[/]")
159
+
160
+ # If no directories found and no default set, default to custom option
161
+ if default_choice is None:
162
+ default_choice = custom_choice
157
163
 
158
- console.print()
159
- choice = IntPrompt.ask(
160
- "Select agent directory", default=default_choice, show_default=True
161
- )
164
+ console.print()
165
+ choice = IntPrompt.ask(
166
+ "Select agent directory", default=default_choice, show_default=True
167
+ )
162
168
 
163
- if choice in directory_choices:
164
- selected = directory_choices[choice]
165
- if selected == "__custom__":
166
- console.print()
167
- custom_dir = Prompt.ask(
168
- "Enter custom agent directory name", default=detected_directory
169
- )
170
- return custom_dir
169
+ if choice in directory_choices:
170
+ selected = directory_choices[choice]
171
+ if selected == "__custom__":
172
+ console.print()
173
+ while True:
174
+ custom_dir = Prompt.ask(
175
+ "Enter custom agent directory name", default=detected_directory
176
+ )
177
+ try:
178
+ validate_agent_directory_name(custom_dir)
179
+ return custom_dir
180
+ except ValueError as e:
181
+ console.print(f"[bold red]Error:[/] {e}", style="bold red")
182
+ console.print("Please try again with a valid directory name.")
183
+ else:
184
+ # Validate existing directory selection as well
185
+ try:
186
+ validate_agent_directory_name(selected)
187
+ return selected
188
+ except ValueError as e:
189
+ console.print(f"[bold red]Error:[/] {e}", style="bold red")
190
+ console.print(
191
+ "This directory cannot be used as an agent directory. Please select another option."
192
+ )
193
+ console.print()
194
+ # Continue the loop to re-prompt without recursion
195
+ continue
171
196
  else:
172
- return selected
173
- else:
174
- raise ValueError(f"Invalid agent directory selection: {choice}")
197
+ console.print(
198
+ f"[bold red]Error:[/] Invalid selection: {choice}", style="bold red"
199
+ )
200
+ console.print("Please choose a valid option from the list.")
201
+ console.print()
202
+ # Continue the loop to re-prompt without recursion
203
+ continue
175
204
 
176
205
 
177
206
  @click.command()
@@ -389,11 +418,8 @@ def enhance(
389
418
  )
390
419
  pass # Fall back to default
391
420
 
392
- # Check if detected/default app folder exists before showing interactive selection
393
- app_folder_exists = (current_dir / detected_agent_directory).exists()
394
-
395
- # Interactive agent directory selection if not provided via CLI, no app folder exists, and not auto-approved
396
- if not agent_directory and not app_folder_exists and not auto_approve:
421
+ # Interactive agent directory selection if not provided via CLI and not auto-approved
422
+ if not agent_directory and not auto_approve:
397
423
  selected_agent_directory = display_agent_directory_selection(
398
424
  current_dir, detected_agent_directory
399
425
  )
@@ -464,16 +490,82 @@ def enhance(
464
490
  console.print("✋ [yellow]Enhancement cancelled.[/yellow]")
465
491
  return
466
492
  else:
467
- # Check for common agent files
493
+ # Check for agent.py and validate required object
468
494
  agent_py = agent_folder / "agent.py"
495
+
496
+ # Determine required object outside of if/else blocks to avoid NameError
497
+ is_adk = base_template and "adk" in base_template.lower()
498
+ required_object = "root_agent" if is_adk else "agent"
499
+
469
500
  if agent_py.exists():
470
501
  console.print(
471
- f"Detected existing agent structure with [cyan]/{final_agent_directory}/agent.py[/cyan]"
502
+ f" Found [cyan]/{final_agent_directory}/agent.py[/cyan]"
472
503
  )
504
+
505
+ try:
506
+ content = agent_py.read_text(encoding="utf-8")
507
+
508
+ # Look for the required object definition using static analysis
509
+ patterns = [
510
+ rf"^\s*{required_object}\s*=", # assignment: root_agent = ...
511
+ rf"^\s*def\s+{required_object}", # function: def root_agent(...)
512
+ rf"from\s+.*\s+import\s+.*{required_object}", # import: from ... import root_agent
513
+ ]
514
+
515
+ found = any(
516
+ re.search(pattern, content, re.MULTILINE)
517
+ for pattern in patterns
518
+ )
519
+
520
+ if found:
521
+ console.print(
522
+ f"✅ Found '{required_object}' definition in {final_agent_directory}/agent.py"
523
+ )
524
+ else:
525
+ console.print(
526
+ f"⚠️ [yellow]Missing '{required_object}' variable in {final_agent_directory}/agent.py[/yellow]"
527
+ )
528
+ console.print(
529
+ " This variable should contain your main agent instance for deployment."
530
+ )
531
+ console.print(
532
+ f" Example: [cyan]{required_object} = YourAgentClass()[/cyan]"
533
+ )
534
+ # Show ADK docs link for ADK templates
535
+ if is_adk:
536
+ console.print(
537
+ " 📖 Learn more: [cyan][link=https://google.github.io/adk-docs/get-started/quickstart/#agentpy]ADK agent.py guide[/link][/cyan]"
538
+ )
539
+ console.print()
540
+ if not auto_approve:
541
+ if not click.confirm(
542
+ f"Continue enhancement? (You can add '{required_object}' later)",
543
+ default=True,
544
+ ):
545
+ console.print(
546
+ "✋ [yellow]Enhancement cancelled.[/yellow]"
547
+ )
548
+ return
549
+
550
+ except Exception as e:
551
+ console.print(
552
+ f"⚠️ [yellow]Warning: Could not read {final_agent_directory}/agent.py: {e}[/yellow]"
553
+ )
473
554
  else:
474
555
  console.print(
475
- f"ℹ️ [blue]Found /{final_agent_directory} folder[/blue] - ensure your agent code is properly organized within it, including an agent.py file"
556
+ f"⚠️ [yellow]Warning: {final_agent_directory}/agent.py not found[/yellow]"
476
557
  )
558
+ console.print(
559
+ f" Create {final_agent_directory}/agent.py with your agent logic and define: [cyan]{required_object} = your_agent_instance[/cyan]"
560
+ )
561
+ console.print()
562
+ if not auto_approve:
563
+ if not click.confirm(
564
+ f"Continue enhancement? (An example {final_agent_directory}/agent.py will be created for you)",
565
+ default=True,
566
+ ):
567
+ console.print("✋ [yellow]Enhancement cancelled.[/yellow]")
568
+ return
477
569
 
478
570
  # Prepare CLI overrides to pass to create command
479
571
  final_cli_overrides: dict[str, Any] = {}
src/cli/utils/gcp.py CHANGED
@@ -147,7 +147,7 @@ def get_dummy_request(project_id: str) -> CountTokensRequest:
147
147
  """Creates a simple test request for Gemini."""
148
148
  return CountTokensRequest(
149
149
  contents=[{"role": "user", "parts": [{"text": "Hi"}]}],
150
- endpoint=f"projects/{project_id}/locations/global/publishers/google/models/gemini-2.0-flash",
150
+ endpoint=f"projects/{project_id}/locations/global/publishers/google/models/gemini-2.5-flash",
151
151
  )
152
152
 
153
153
 
src/cli/utils/template.py CHANGED
@@ -35,6 +35,30 @@ from .remote_template import (
35
35
  )
36
36
 
37
37
 
38
+ def validate_agent_directory_name(agent_dir: str) -> None:
39
+ """Validate that an agent directory name is a valid Python identifier.
40
+
41
+ Args:
42
+ agent_dir: The agent directory name to validate
43
+
44
+ Raises:
45
+ ValueError: If the agent directory name is not a valid Python identifier
46
+ """
47
+ if "-" in agent_dir:
48
+ raise ValueError(
49
+ f"Agent directory '{agent_dir}' contains hyphens (-) which are not allowed. "
50
+ "Agent directories must be valid Python identifiers since they're used as module names. "
51
+ "Please use underscores (_) or lowercase letters instead."
52
+ )
53
+
54
+ if not agent_dir.replace("_", "a").isidentifier():
55
+ raise ValueError(
56
+ f"Agent directory '{agent_dir}' is not a valid Python identifier. "
57
+ "Agent directories must be valid Python identifiers since they're used as module names. "
58
+ "Please use only lowercase letters, numbers, and underscores, and don't start with a number."
59
+ )
60
+
61
+
38
62
  @dataclass
39
63
  class TemplateConfig:
40
64
  name: str
@@ -478,13 +502,22 @@ def process_template(
478
502
  template_config: dict[str, Any], cli_overrides: dict[str, Any] | None = None
479
503
  ) -> str:
480
504
  """Get agent directory with CLI override support."""
505
+ agent_dir = None
481
506
  if (
482
507
  cli_overrides
483
508
  and "settings" in cli_overrides
484
509
  and "agent_directory" in cli_overrides["settings"]
485
510
  ):
486
- return cli_overrides["settings"]["agent_directory"]
487
- return template_config.get("settings", {}).get("agent_directory", "app")
511
+ agent_dir = cli_overrides["settings"]["agent_directory"]
512
+ else:
513
+ agent_dir = template_config.get("settings", {}).get(
514
+ "agent_directory", "app"
515
+ )
516
+
517
+ # Validate agent directory is a valid Python identifier
518
+ validate_agent_directory_name(agent_dir)
519
+
520
+ return agent_dir
488
521
 
489
522
  # Handle remote vs local templates
490
523
  is_remote = remote_template_path is not None