agent-starter-pack 0.2.2__py3-none-any.whl → 0.3.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.

Potentially problematic release.


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

Files changed (72) hide show
  1. {agent_starter_pack-0.2.2.dist-info → agent_starter_pack-0.3.0.dist-info}/METADATA +14 -16
  2. {agent_starter_pack-0.2.2.dist-info → agent_starter_pack-0.3.0.dist-info}/RECORD +69 -54
  3. agents/adk_base/README.md +14 -0
  4. agents/adk_base/app/agent.py +66 -0
  5. agents/adk_base/notebooks/adk_app_testing.ipynb +305 -0
  6. agents/adk_base/template/.templateconfig.yaml +21 -0
  7. agents/adk_base/tests/integration/test_agent.py +58 -0
  8. agents/agentic_rag/README.md +1 -0
  9. agents/agentic_rag/app/agent.py +44 -89
  10. agents/agentic_rag/app/templates.py +0 -25
  11. agents/agentic_rag/notebooks/adk_app_testing.ipynb +305 -0
  12. agents/agentic_rag/template/.templateconfig.yaml +3 -1
  13. agents/agentic_rag/tests/integration/test_agent.py +34 -27
  14. agents/langgraph_base_react/README.md +1 -1
  15. agents/langgraph_base_react/template/.templateconfig.yaml +1 -1
  16. src/base_template/Makefile +15 -4
  17. src/base_template/README.md +8 -2
  18. src/base_template/app/__init__.py +3 -0
  19. src/base_template/app/utils/tracing.py +11 -1
  20. src/base_template/app/utils/typing.py +54 -4
  21. src/base_template/deployment/README.md +4 -1
  22. src/base_template/deployment/cd/deploy-to-prod.yaml +3 -3
  23. src/base_template/deployment/cd/staging.yaml +4 -4
  24. src/base_template/deployment/ci/pr_checks.yaml +1 -1
  25. src/base_template/deployment/terraform/build_triggers.tf +3 -0
  26. src/base_template/deployment/terraform/dev/variables.tf +4 -0
  27. src/base_template/deployment/terraform/dev/vars/env.tfvars +0 -3
  28. src/base_template/deployment/terraform/variables.tf +4 -0
  29. src/base_template/deployment/terraform/vars/env.tfvars +0 -4
  30. src/base_template/pyproject.toml +5 -3
  31. src/{deployment_targets/agent_engine → base_template}/tests/unit/test_dummy.py +2 -1
  32. src/cli/commands/create.py +45 -11
  33. src/cli/commands/setup_cicd.py +25 -6
  34. src/cli/utils/gcp.py +1 -1
  35. src/cli/utils/template.py +27 -25
  36. src/data_ingestion/README.md +37 -50
  37. src/data_ingestion/data_ingestion_pipeline/components/ingest_data.py +2 -1
  38. src/deployment_targets/agent_engine/app/agent_engine_app.py +68 -22
  39. src/deployment_targets/agent_engine/app/utils/gcs.py +1 -1
  40. src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +63 -0
  41. src/deployment_targets/agent_engine/tests/load_test/load_test.py +9 -2
  42. src/deployment_targets/cloud_run/Dockerfile +1 -1
  43. src/deployment_targets/cloud_run/app/server.py +41 -15
  44. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +60 -3
  45. src/deployment_targets/cloud_run/tests/load_test/README.md +1 -1
  46. src/deployment_targets/cloud_run/tests/load_test/load_test.py +57 -24
  47. src/frontends/live_api_react/frontend/package-lock.json +3 -3
  48. src/frontends/streamlit/frontend/utils/stream_handler.py +3 -3
  49. src/frontends/streamlit_adk/frontend/side_bar.py +214 -0
  50. src/frontends/streamlit_adk/frontend/streamlit_app.py +314 -0
  51. src/frontends/streamlit_adk/frontend/style/app_markdown.py +37 -0
  52. src/frontends/streamlit_adk/frontend/utils/chat_utils.py +84 -0
  53. src/frontends/streamlit_adk/frontend/utils/local_chat_history.py +110 -0
  54. src/frontends/streamlit_adk/frontend/utils/message_editing.py +61 -0
  55. src/frontends/streamlit_adk/frontend/utils/multimodal_utils.py +223 -0
  56. src/frontends/streamlit_adk/frontend/utils/stream_handler.py +311 -0
  57. src/frontends/streamlit_adk/frontend/utils/title_summary.py +129 -0
  58. src/resources/locks/uv-adk_base-agent_engine.lock +5335 -0
  59. src/resources/locks/uv-adk_base-cloud_run.lock +5927 -0
  60. src/resources/locks/uv-agentic_rag-agent_engine.lock +939 -732
  61. src/resources/locks/uv-agentic_rag-cloud_run.lock +1087 -907
  62. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +778 -671
  63. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +852 -753
  64. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +665 -591
  65. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +842 -743
  66. src/resources/locks/uv-live_api-cloud_run.lock +830 -731
  67. agents/agentic_rag/notebooks/evaluating_langgraph_agent.ipynb +0 -1561
  68. src/base_template/tests/unit/test_utils/test_tracing_exporter.py +0 -140
  69. src/deployment_targets/cloud_run/tests/unit/test_server.py +0 -124
  70. {agent_starter_pack-0.2.2.dist-info → agent_starter_pack-0.3.0.dist-info}/WHEEL +0 -0
  71. {agent_starter_pack-0.2.2.dist-info → agent_starter_pack-0.3.0.dist-info}/entry_points.txt +0 -0
  72. {agent_starter_pack-0.2.2.dist-info → agent_starter_pack-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,305 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# ADK Application Testing\n",
8
+ "\n",
9
+ "This notebook demonstrates how to test an ADK (Agent Development Kit) application.\n",
10
+ "It covers both local and remote testing, both with Agent Engine and Cloud Run.\n",
11
+ "\n",
12
+ "<img src=\"https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/adk_logo.png?raw=true\" width=\"400\">\n"
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "markdown",
17
+ "metadata": {},
18
+ "source": [
19
+ "### Import libraries"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "execution_count": 1,
25
+ "metadata": {},
26
+ "outputs": [],
27
+ "source": [
28
+ "import json\n",
29
+ "\n",
30
+ "import requests\n",
31
+ "import vertexai.agent_engines"
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "markdown",
36
+ "metadata": {},
37
+ "source": [
38
+ "## If you are using Agent Engine\n",
39
+ "See more documentation at [Agent Engine Overview](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/overview)"
40
+ ]
41
+ },
42
+ {
43
+ "cell_type": "markdown",
44
+ "metadata": {},
45
+ "source": [
46
+ "### Local Testing\n",
47
+ "\n",
48
+ "You can import directly the AgentEngineApp class within your environment. "
49
+ ]
50
+ },
51
+ {
52
+ "cell_type": "code",
53
+ "execution_count": 2,
54
+ "metadata": {},
55
+ "outputs": [],
56
+ "source": [
57
+ "from app.agent import root_agent\n",
58
+ "from app.agent_engine_app import AgentEngineApp\n",
59
+ "\n",
60
+ "agent_engine = AgentEngineApp(agent=root_agent)"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {},
67
+ "outputs": [],
68
+ "source": [
69
+ "for event in agent_engine.stream_query(message=\"hi!\", user_id=\"test\"):\n",
70
+ " print(event)"
71
+ ]
72
+ },
73
+ {
74
+ "cell_type": "markdown",
75
+ "metadata": {},
76
+ "source": [
77
+ "### Remote Testing"
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "execution_count": 4,
83
+ "metadata": {},
84
+ "outputs": [],
85
+ "source": [
86
+ "# Replace with your Agent Engine ID\n",
87
+ "AGENT_ENGINE_ID = \"projects/PROJECT_ID/locations/us-central1/reasoningEngines/ENGINE_ID\""
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": 5,
93
+ "metadata": {},
94
+ "outputs": [],
95
+ "source": [
96
+ "remote_agent_engine = vertexai.agent_engines.get(AGENT_ENGINE_ID)"
97
+ ]
98
+ },
99
+ {
100
+ "cell_type": "code",
101
+ "execution_count": null,
102
+ "metadata": {},
103
+ "outputs": [],
104
+ "source": [
105
+ "for event in remote_agent_engine.stream_query(message=\"hi!\", user_id=\"test\"):\n",
106
+ " print(event)"
107
+ ]
108
+ },
109
+ {
110
+ "cell_type": "markdown",
111
+ "metadata": {},
112
+ "source": [
113
+ "## If you are using Cloud Run"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "markdown",
118
+ "metadata": {},
119
+ "source": [
120
+ "### Local Testing\n",
121
+ "\n",
122
+ "> You can run the application locally via the `make backend` command."
123
+ ]
124
+ },
125
+ {
126
+ "cell_type": "markdown",
127
+ "metadata": {},
128
+ "source": [
129
+ "#### Create a session\n",
130
+ " Create a new session with user preferences and state information\n"
131
+ ]
132
+ },
133
+ {
134
+ "cell_type": "code",
135
+ "execution_count": null,
136
+ "metadata": {},
137
+ "outputs": [],
138
+ "source": [
139
+ "user_id = \"test_user_123\"\n",
140
+ "session_id = \"test_session_456\"\n",
141
+ "session_data = {\"state\": {\"preferred_language\": \"English\", \"visit_count\": 1}}\n",
142
+ "\n",
143
+ "session_url = f\"http://127.0.0.1:8000/apps/app/users/{user_id}/sessions/{session_id}\"\n",
144
+ "headers = {\"Content-Type\": \"application/json\"}\n",
145
+ "\n",
146
+ "session_response = requests.post(session_url, headers=headers, json=session_data)\n",
147
+ "print(f\"Session creation status code: {session_response.status_code}\")"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "markdown",
152
+ "metadata": {},
153
+ "source": [
154
+ "#### Send a message\n",
155
+ "Send a message to the backend service and receive a streaming response\n"
156
+ ]
157
+ },
158
+ {
159
+ "cell_type": "code",
160
+ "execution_count": null,
161
+ "metadata": {},
162
+ "outputs": [],
163
+ "source": [
164
+ "message_data = {\n",
165
+ " \"app_name\": \"app\",\n",
166
+ " \"user_id\": user_id,\n",
167
+ " \"session_id\": session_id,\n",
168
+ " \"new_message\": {\"role\": \"user\", \"parts\": [{\"text\": \"Hello! Weather in New york?\"}]},\n",
169
+ " \"streaming\": True,\n",
170
+ "}\n",
171
+ "\n",
172
+ "message_url = \"http://127.0.0.1:8000/run_sse\"\n",
173
+ "message_response = requests.post(\n",
174
+ " message_url, headers=headers, json=message_data, stream=True\n",
175
+ ")\n",
176
+ "\n",
177
+ "print(f\"Message send status code: {message_response.status_code}\")\n",
178
+ "\n",
179
+ "# Print streamed response\n",
180
+ "for line in message_response.iter_lines():\n",
181
+ " if line:\n",
182
+ " line_str = line.decode(\"utf-8\")\n",
183
+ " if line_str.startswith(\"data: \"):\n",
184
+ " event_json = line_str[6:]\n",
185
+ " event = json.loads(event_json)\n",
186
+ " print(f\"Received event: {event}\")"
187
+ ]
188
+ },
189
+ {
190
+ "cell_type": "markdown",
191
+ "metadata": {},
192
+ "source": [
193
+ "#### Remote Testing\n",
194
+ "\n",
195
+ "For more information about authenticating HTTPS requests to Cloud Run services, see:\n",
196
+ "[Cloud Run Authentication Documentation](https://cloud.google.com/run/docs/triggering/https-request)\n",
197
+ "\n",
198
+ "Remote testing involves using a deployed service URL instead of localhost.\n",
199
+ "\n",
200
+ "Authentication is handled using GCP identity tokens instead of local credentials."
201
+ ]
202
+ },
203
+ {
204
+ "cell_type": "code",
205
+ "execution_count": 20,
206
+ "metadata": {},
207
+ "outputs": [],
208
+ "source": [
209
+ "ID_TOKEN = get_ipython().getoutput(\"gcloud auth print-identity-token -q\")[0]"
210
+ ]
211
+ },
212
+ {
213
+ "cell_type": "code",
214
+ "execution_count": null,
215
+ "metadata": {},
216
+ "outputs": [],
217
+ "source": [
218
+ "SERVICE_URL = \"YOUR_SERVICE_URL_HERE\" # Replace with your Cloud Run service URL"
219
+ ]
220
+ },
221
+ {
222
+ "cell_type": "markdown",
223
+ "metadata": {},
224
+ "source": [
225
+ "You'll need to first create a Session"
226
+ ]
227
+ },
228
+ {
229
+ "cell_type": "code",
230
+ "execution_count": null,
231
+ "metadata": {},
232
+ "outputs": [],
233
+ "source": [
234
+ "user_id = \"test_user_123\"\n",
235
+ "session_id = \"test_session_456\"\n",
236
+ "session_data = {\"state\": {\"preferred_language\": \"English\", \"visit_count\": 1}}\n",
237
+ "\n",
238
+ "session_url = f\"{SERVICE_URL}/apps/app/users/{user_id}/sessions/{session_id}\"\n",
239
+ "headers = {\"Content-Type\": \"application/json\", \"Authorization\": f\"Bearer {ID_TOKEN}\"}\n",
240
+ "\n",
241
+ "session_response = requests.post(session_url, headers=headers, json=session_data)\n",
242
+ "print(f\"Session creation status code: {session_response.status_code}\")"
243
+ ]
244
+ },
245
+ {
246
+ "cell_type": "markdown",
247
+ "metadata": {},
248
+ "source": [
249
+ "Then you will be able to send a message"
250
+ ]
251
+ },
252
+ {
253
+ "cell_type": "code",
254
+ "execution_count": null,
255
+ "metadata": {},
256
+ "outputs": [],
257
+ "source": [
258
+ "message_data = {\n",
259
+ " \"app_name\": \"app\",\n",
260
+ " \"user_id\": user_id,\n",
261
+ " \"session_id\": session_id,\n",
262
+ " \"new_message\": {\"role\": \"user\", \"parts\": [{\"text\": \"Hello! Weather in New york?\"}]},\n",
263
+ " \"streaming\": True,\n",
264
+ "}\n",
265
+ "\n",
266
+ "message_url = f\"{SERVICE_URL}/run_sse\"\n",
267
+ "message_response = requests.post(\n",
268
+ " message_url, headers=headers, json=message_data, stream=True\n",
269
+ ")\n",
270
+ "\n",
271
+ "print(f\"Message send status code: {message_response.status_code}\")\n",
272
+ "\n",
273
+ "# Print streamed response\n",
274
+ "for line in message_response.iter_lines():\n",
275
+ " if line:\n",
276
+ " line_str = line.decode(\"utf-8\")\n",
277
+ " if line_str.startswith(\"data: \"):\n",
278
+ " event_json = line_str[6:]\n",
279
+ " event = json.loads(event_json)\n",
280
+ " print(f\"Received event: {event}\")"
281
+ ]
282
+ }
283
+ ],
284
+ "metadata": {
285
+ "kernelspec": {
286
+ "display_name": ".venv",
287
+ "language": "python",
288
+ "name": "python3"
289
+ },
290
+ "language_info": {
291
+ "codemirror_mode": {
292
+ "name": "ipython",
293
+ "version": 3
294
+ },
295
+ "file_extension": ".py",
296
+ "mimetype": "text/x-python",
297
+ "name": "python",
298
+ "nbconvert_exporter": "python",
299
+ "pygments_lexer": "ipython3",
300
+ "version": "3.12.8"
301
+ }
302
+ },
303
+ "nbformat": 4,
304
+ "nbformat_minor": 2
305
+ }
@@ -17,10 +17,12 @@ settings:
17
17
  requires_data_ingestion: true
18
18
  deployment_targets: ["agent_engine", "cloud_run"]
19
19
  extra_dependencies: [
20
+ "google-adk~=0.1.0",
20
21
  "langchain-google-vertexai~=2.0.7",
21
22
  "langchain~=0.3.14",
22
- "langgraph~=0.3.21",
23
23
  "langchain-community~=0.3.17",
24
24
  "langchain-openai~=0.3.5",
25
25
  "langchain-google-community[vertexaisearch]~=2.0.7",
26
26
  ]
27
+ tags: ["adk"]
28
+ frontend_type: "streamlit_adk"
@@ -15,43 +15,50 @@
15
15
  # mypy: disable-error-code="union-attr"
16
16
  from unittest.mock import MagicMock, patch
17
17
 
18
- from app.agent import agent
18
+ from google.adk.agents.run_config import RunConfig, StreamingMode
19
+ from google.adk.runners import Runner
20
+ from google.adk.sessions import InMemorySessionService
21
+ from google.genai import types
22
+
23
+ from app.agent import root_agent
19
24
 
20
25
 
21
26
  @patch(
22
- "app.agent.retrieve_docs.func",
23
- return_value=("dummy content", [{"page_content": "Test document content"}]),
27
+ "app.agent.retrieve_docs",
28
+ return_value="dummy content",
24
29
  )
25
30
  def test_agent_stream(mock_retrieve: MagicMock) -> None:
26
31
  """
27
32
  Integration test for the agent stream functionality.
28
33
  Tests that the agent returns valid streaming responses.
29
34
  """
30
- input_dict = {
31
- "messages": [
32
- {"type": "human", "content": "Hi"},
33
- {"type": "ai", "content": "Hi there!"},
34
- {
35
- "type": "human",
36
- "content": "How to split a string with pattern 'alphabet/alphabet' and not split 'number/number' in same string",
37
- },
38
- ]
39
- }
40
-
41
- events = [
42
- message for message, _ in agent.stream(input_dict, stream_mode="messages")
43
- ]
44
-
45
- # Verify we get a reasonable number of messages
46
- assert len(events) > 0, "Expected at least one message"
47
35
 
48
- # First message should be an AI message
49
- assert events[0].type == "AIMessageChunk"
36
+ session_service = InMemorySessionService()
37
+
38
+ session = session_service.create_session(user_id="test_user", app_name="test")
39
+ runner = Runner(agent=root_agent, session_service=session_service, app_name="test")
40
+
41
+ message = types.Content(
42
+ role="user", parts=[types.Part.from_text(text="Why is the sky blue?")]
43
+ )
44
+
45
+ events = list(
46
+ runner.run(
47
+ new_message=message,
48
+ user_id="test_user",
49
+ session_id=session.id,
50
+ run_config=RunConfig(streaming_mode=StreamingMode.SSE),
51
+ )
52
+ )
53
+ assert len(events) > 0, "Expected at least one message"
50
54
 
51
- # At least one message should have content
52
- has_content = False
55
+ has_text_content = False
53
56
  for event in events:
54
- if hasattr(event, "content") and event.content:
55
- has_content = True
57
+ if (
58
+ event.content
59
+ and event.content.parts
60
+ and any(part.text for part in event.content.parts)
61
+ ):
62
+ has_text_content = True
56
63
  break
57
- assert has_content, "Expected at least one message with content"
64
+ assert has_text_content, "Expected at least one message with text content"
@@ -1,6 +1,6 @@
1
1
  # LangGraph Base React Agent
2
2
 
3
- A minimal example demonstrating how to build a reactive agent using LangGraph. This agent serves as an excellent starting point for developers looking to implement LangGraph-based solutions.
3
+ A minimal example demonstrating how to build a ReAct agent using LangGraph. This agent serves as an excellent starting point for developers looking to implement LangGraph-based solutions.
4
4
 
5
5
  ## Key Features
6
6
 
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- description: "A agent implementing a base ReAct agent using LangGraph"
15
+ description: "An agent implementing a base ReAct agent using LangGraph"
16
16
  settings:
17
17
  requires_data_ingestion: false
18
18
  deployment_targets: ["agent_engine", "cloud_run"]
@@ -1,11 +1,19 @@
1
1
  install:
2
- @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/install.sh | sh; source ~/.bashrc; }
2
+ @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.6.12/install.sh | sh; source ~/.bashrc; }
3
3
  uv sync --dev {% if cookiecutter.agent_name != 'live_api' %}--extra streamlit{%- endif %} --extra jupyter --frozen{% if cookiecutter.agent_name == 'live_api' %} && npm --prefix frontend install{%- endif %}
4
4
 
5
5
  test:
6
6
  uv run pytest tests/unit && uv run pytest tests/integration
7
7
 
8
8
  playground:
9
+ {%- if "adk" in cookiecutter.tags %}
10
+ @echo "+-----------------------------------------------------------------------------+"
11
+ @echo "| Starting ADK Web Server via 'adk web' command. |"
12
+ @echo "| |"
13
+ @echo "| Please select the app folder to start interacting with your agent. |"
14
+ @echo "+-----------------------------------------------------------------------------+"
15
+ uv run adk web
16
+ {%- else %}
9
17
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
10
18
  uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload &
11
19
  {%- endif %}
@@ -14,12 +22,15 @@ playground:
14
22
  {%- else %}
15
23
  {% if cookiecutter.deployment_target == 'agent_engine' %}PYTHONPATH=. {% endif %}uv run streamlit run frontend/streamlit_app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false
16
24
  {%- endif %}
25
+ {%- endif %}
17
26
 
18
27
  backend:
19
28
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
20
29
  uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload
21
30
  {%- elif cookiecutter.deployment_target == 'agent_engine' %}
22
- uv export --no-hashes --no-sources --no-header --no-emit-project --frozen > .requirements.txt && uv run app/agent_engine_app.py
31
+ # Export dependencies to requirements file using uv export (preferred method), otherwise fall back to uv pip freeze
32
+ uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --frozen > .requirements.txt 2>/dev/null || \
33
+ uv pip freeze --exclude-editable > .requirements.txt && uv run app/agent_engine_app.py
23
34
  {%- endif %}
24
35
 
25
36
  {% if cookiecutter.deployment_target == 'cloud_run' -%}
@@ -34,8 +45,7 @@ ui:
34
45
  setup-dev-env:
35
46
  @if [ -z "$$PROJECT_ID" ]; then echo "Error: PROJECT_ID environment variable is not set"; exit 1; fi
36
47
  (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve)
37
-
38
- {%- if cookiecutter.data_ingestion%}
48
+ {% if cookiecutter.data_ingestion %}
39
49
  data-ingestion:
40
50
  @if [ -z "$$PROJECT_ID" ]; then echo "Error: PROJECT_ID environment variable is not set"; exit 1; fi
41
51
  $(MAKE) install
@@ -48,6 +58,7 @@ data-ingestion:
48
58
  {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
49
59
  --vector-search-index="{{cookiecutter.project_name}}-vector-search" \
50
60
  --vector-search-index-endpoint="{{cookiecutter.project_name}}-vector-search-endpoint" \
61
+ --vector-search-data-bucket-name="$$PROJECT_ID-{{cookiecutter.project_name}}-vs" \
51
62
  {%- endif %}
52
63
  --service-account="{{cookiecutter.project_name}}-rag@$$PROJECT_ID.iam.gserviceaccount.com" \
53
64
  --pipeline-root="gs://$$PROJECT_ID-{{cookiecutter.project_name}}-rag" \
@@ -47,7 +47,7 @@ make install && make playground
47
47
  | -------------------- | ------------------------------------------------------------------------------------------- |
48
48
  | `make install` | Install all required dependencies using uv |
49
49
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
50
- | `make playground` | Launch local development environment with backend and frontend |
50
+ | `make playground` | Launch local development environment with backend and frontend{%- if "adk" in cookiecutter.tags %} - leveraging `adk web` command. {%- endif %}|
51
51
  | `make backend` | Start backend server only |
52
52
  | `make ui` | Launch Streamlit frontend without local backend |
53
53
  {%- elif cookiecutter.deployment_target == 'agent_engine' %}
@@ -56,6 +56,10 @@ make install && make playground
56
56
  {%- endif %}
57
57
  | `make test` | Run unit and integration tests |
58
58
  | `make lint` | Run code quality checks (codespell, ruff, mypy) |
59
+ | `make setup-dev-env` | Set up development environment resources using Terraform |
60
+ {%- if cookiecutter.data_ingestion %}
61
+ | `make data-ingestion`| Run data ingestion pipeline in the Dev environment |
62
+ {%- endif %}
59
63
  | `uv run jupyter lab` | Launch Jupyter notebook |
60
64
 
61
65
  For full command options and usage, refer to the [Makefile](Makefile).
@@ -144,12 +148,14 @@ This template follows a "bring your own agent" approach - you focus on your busi
144
148
  1. **Prototype:** Build your Generative AI Agent using the intro notebooks in `notebooks/` for guidance. Use Vertex AI Evaluation to assess performance.
145
149
  2. **Integrate:** Import your agent into the app by editing `app/agent.py`.
146
150
  3. **Test:** Explore your agent functionality using the Streamlit playground with `make playground`. The playground offers features like chat history, user feedback, and various input types, and automatically reloads your agent on code changes.
147
- 4. **Deploy:** Configure and trigger the CI/CD pipelines, editing tests if needed. See the [deployment section](#deployment) for details.
151
+ 4. **Deploy:** Set up and initiate the CI/CD pipelines, customizing tests as necessary. Refer to the [deployment section](#deployment) for comprehensive instructions. For streamlined infrastructure deployment, simply run `agent-starter-pack setup-cicd`. Check out the [`agent-starter-pack setup-cicd` CLI command](https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/cli/setup_cicd.md). Currently only supporting Github.
148
152
  5. **Monitor:** Track performance and gather insights using Cloud Logging, Tracing, and the Looker Studio dashboard to iterate on your application.
149
153
  {% endif %}
150
154
 
151
155
  ## Deployment
152
156
 
157
+ > **Note:** For a streamlined one-command deployment of the entire CI/CD pipeline and infrastructure using Terraform, you can use the [`agent-starter-pack setup-cicd` CLI command](https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/cli/setup_cicd.md). Currently only supporting Github.
158
+
153
159
  ### Dev Environment
154
160
 
155
161
  {%- if cookiecutter.deployment_target == 'agent_engine' %}
@@ -0,0 +1,3 @@
1
+ from app.agent import root_agent
2
+
3
+ __all__ = ["root_agent"]
@@ -86,8 +86,18 @@ class CloudTraceLoggingSpanExporter(CloudTraceSpanExporter):
86
86
  print(span_dict)
87
87
 
88
88
  # Log the span data to Google Cloud Logging
89
+ {%- if "adk" in cookiecutter.tags %}
90
+ self.logger.log_struct(
91
+ span_dict,
92
+ labels={
93
+ "type": "agent_telemetry",
94
+ "service_name": "{{cookiecutter.project_name}}",
95
+ },
96
+ severity="INFO",
97
+ )
98
+ {%- else %}
89
99
  self.logger.log_struct(span_dict, severity="INFO")
90
-
100
+ {%- endif %}
91
101
  # Export spans to Google Cloud Trace using the parent class method
92
102
  return super().export(spans)
93
103
 
@@ -12,6 +12,29 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ {%- if "adk" in cookiecutter.tags %}
16
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
17
+ import uuid
18
+ from typing import (
19
+ Literal,
20
+ )
21
+
22
+ from google.adk.events.event import Event
23
+ from google.genai.types import Content
24
+ from pydantic import (
25
+ BaseModel,
26
+ Field,
27
+ )
28
+ {%- else %}
29
+ from typing import (
30
+ Literal,
31
+ )
32
+
33
+ from pydantic import (
34
+ BaseModel,
35
+ )
36
+ {%- endif %}
37
+ {%- else %}
15
38
  import json
16
39
  import uuid
17
40
  from typing import (
@@ -31,6 +54,24 @@ from pydantic import (
31
54
  BaseModel,
32
55
  Field,
33
56
  )
57
+ {%- endif %}
58
+
59
+
60
+ {%- if "adk" in cookiecutter.tags %}
61
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
62
+
63
+
64
+ class Request(BaseModel):
65
+ """Represents the input for a chat request with optional configuration."""
66
+
67
+ message: Content
68
+ events: list[Event]
69
+ user_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
70
+ session_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
71
+
72
+ model_config = {"extra": "allow"}
73
+ {%- endif %}
74
+ {%- else %}
34
75
 
35
76
 
36
77
  class InputChat(BaseModel):
@@ -42,7 +83,7 @@ class InputChat(BaseModel):
42
83
  ..., description="The chat messages representing the current conversation."
43
84
  )
44
85
 
45
- {% if cookiecutter.deployment_target == 'cloud_run' %}
86
+
46
87
  class Request(BaseModel):
47
88
  """Represents the input for a chat request with optional configuration.
48
89
 
@@ -54,16 +95,23 @@ class Request(BaseModel):
54
95
  input: InputChat
55
96
  config: RunnableConfig | None = None
56
97
 
57
- {% endif %}
98
+ {%- endif %}
99
+
100
+
58
101
  class Feedback(BaseModel):
59
102
  """Represents feedback for a conversation."""
60
103
 
61
104
  score: int | float
62
105
  text: str | None = ""
106
+ {%- if "adk" in cookiecutter.tags %}
107
+ invocation_id: str
108
+ {%- else %}
63
109
  run_id: str
110
+ {%- endif %}
64
111
  log_type: Literal["feedback"] = "feedback"
65
112
  service_name: Literal["{{cookiecutter.project_name}}"] = "{{cookiecutter.project_name}}"
66
-
113
+ user_id: str = ""
114
+ {% if "adk" not in cookiecutter.tags %}
67
115
 
68
116
  def ensure_valid_config(config: RunnableConfig | None) -> RunnableConfig:
69
117
  """Ensures a valid RunnableConfig by setting defaults for missing fields."""
@@ -99,7 +147,8 @@ def dumps(obj: Any) -> str:
99
147
  JSON string representation of the object
100
148
  """
101
149
  return json.dumps(obj, default=default_serialization)
102
- {% if cookiecutter.deployment_target == 'agent_engine' %}
150
+ {%- if cookiecutter.deployment_target == 'agent_engine' %}
151
+
103
152
 
104
153
  def dumpd(obj: Any) -> Any:
105
154
  """
@@ -113,4 +162,5 @@ def dumpd(obj: Any) -> Any:
113
162
  Dict/list representation of the object that can be JSON serialized
114
163
  """
115
164
  return json.loads(dumps(obj))
165
+ {%- endif %}
116
166
  {% endif %}
@@ -29,6 +29,8 @@ The application leverages [**Terraform**](http://terraform.io) to define and pro
29
29
 
30
30
  ## Setup
31
31
 
32
+ > **Note:** For a streamlined one-command deployment of the entire CI/CD pipeline and infrastructure using Terraform, you can use the [`agent-starter-pack setup-cicd` CLI command](https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/cli/setup_cicd.md). Currently only supporting Github.
33
+
32
34
  **Prerequisites:**
33
35
 
34
36
  1. A set of Google Cloud projects:
@@ -58,6 +60,7 @@ The application leverages [**Terraform**](http://terraform.io) to define and pro
58
60
 
59
61
  | Variable | Description | Required |
60
62
  | ---------------------- | --------------------------------------------------------------- | :------: |
63
+ | project_name | Project name used as a base for resource naming | Yes |
61
64
  | prod_project_id | **Production** Google Cloud Project ID for resource deployment. | Yes |
62
65
  | staging_project_id | **Staging** Google Cloud Project ID for resource deployment. | Yes |
63
66
  | cicd_runner_project_id | Google Cloud Project ID where CI/CD pipelines will execute. | Yes |
@@ -65,7 +68,7 @@ The application leverages [**Terraform**](http://terraform.io) to define and pro
65
68
  | host_connection_name | Name of the host connection you created in Cloud Build | Yes |
66
69
  | repository_name | Name of the repository you added to Cloud Build | Yes |
67
70
 
68
- Other optional variables include: telemetry and feedback BigQuery dataset IDs, log filters, sink names, service account names, bucket name suffixes, artifact registry repository name, and various role assignments.
71
+ Other optional variables may include: telemetry and feedback log filters, service account roles, and for projects requiring data ingestion: pipeline cron schedule, pipeline roles, and datastore-specific configurations.
69
72
 
70
73
  4. **Deploy Infrastructure with Terraform**
71
74