├── tests ├── __init__.py ├── utils │ └── __init__.py ├── cicd │ └── example.env ├── fixtures │ ├── makefile_hashes.json │ └── makefile_snapshots │ │ ├── adk_base_agent_engine_no_data.makefile │ │ ├── agent_with_custom_commands.makefile │ │ ├── langgraph_cloud_run_no_data.makefile │ │ ├── adk_base_cloud_run_no_data.makefile │ │ └── agent_with_agent_garden.makefile ├── cli │ ├── commands │ │ └── test_list.py │ └── utils │ │ └── test_cicd.py ├── integration │ └── utils.py ├── test_frontend │ └── test_utils │ │ ├── test_multimodal_utils.py │ │ └── test_local_chat_history.py └── unit │ └── README_MAKEFILE_TESTS.md ├── agent_starter_pack ├── deployment_targets │ ├── agent_engine │ │ ├── tests │ │ │ └── load_test │ │ │ │ ├── .results │ │ │ │ └── .placeholder │ │ │ │ └── README.md │ │ └── deployment_metadata.json │ └── cloud_run │ │ └── Dockerfile ├── frontends │ ├── adk_live_react │ │ └── frontend │ │ │ ├── public │ │ │ ├── robots.txt │ │ │ ├── favicon.ico │ │ │ └── index.html │ │ │ ├── tsconfig.json │ │ │ ├── src │ │ │ ├── react-app-env.d.ts │ │ │ ├── hooks │ │ │ │ ├── use-media-stream-mux.ts │ │ │ │ ├── use-webcam.ts │ │ │ │ └── use-screen-capture.ts │ │ │ ├── setupTests.ts │ │ │ ├── App.test.tsx │ │ │ ├── index.css │ │ │ ├── reportWebVitals.ts │ │ │ ├── index.tsx │ │ │ ├── utils │ │ │ │ ├── audioworklet-registry.ts │ │ │ │ ├── store-logger.ts │ │ │ │ └── worklets │ │ │ │ │ ├── vol-meter.ts │ │ │ │ │ └── audio-processing.ts │ │ │ ├── contexts │ │ │ │ └── LiveAPIContext.tsx │ │ │ ├── components │ │ │ │ └── audio-pulse │ │ │ │ │ ├── audio-pulse.scss │ │ │ │ │ └── AudioPulse.tsx │ │ │ └── App.tsx │ │ │ └── package.json │ └── streamlit │ │ └── frontend │ │ ├── style │ │ └── app_markdown.py │ │ └── utils │ │ ├── message_editing.py │ │ └── chat_utils.py ├── base_template │ ├── GEMINI.md │ ├── deployment │ │ ├── README.md │ │ └── terraform │ │ │ ├── dev │ │ │ ├── vars │ │ │ │ └── env.tfvars │ │ │ ├── providers.tf │ │ │ ├── apis.tf │ │ │ └── log_sinks.tf │ │ │ ├── providers.tf │ │ │ ├── vars │ │ │ └── env.tfvars │ │ │ ├── apis.tf │ │ │ ├── service_accounts.tf │ │ │ ├── locals.tf │ │ │ ├── {% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} │ │ │ └── log_sinks.tf │ ├── tests │ │ └── unit │ │ │ └── test_dummy.py │ ├── {{cookiecutter.agent_directory}} │ │ └── utils │ │ │ └── gcs.py │ ├── {% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %} │ │ └── pr_checks.yaml │ └── {% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %} │ │ └── workflows │ │ └── pr_checks.yaml ├── resources │ ├── idx │ │ ├── idx-template.json │ │ ├── idx-template.nix │ │ └── .idx │ │ │ └── dev.nix │ └── containers │ │ ├── data_processing │ │ └── Dockerfile │ │ └── e2e-tests │ │ └── Dockerfile ├── agents │ ├── README.md │ ├── langgraph_base_react │ │ ├── README.md │ │ ├── .template │ │ │ └── templateconfig.yaml │ │ ├── app │ │ │ └── agent.py │ │ └── tests │ │ │ └── integration │ │ │ └── test_agent.py │ ├── adk_base │ │ ├── app │ │ │ ├── __init__.py │ │ │ └── agent.py │ │ ├── README.md │ │ ├── .template │ │ │ └── templateconfig.yaml │ │ └── tests │ │ │ └── integration │ │ │ └── test_agent.py │ ├── agentic_rag │ │ ├── app │ │ │ ├── __init__.py │ │ │ └── templates.py │ │ ├── .template │ │ │ └── templateconfig.yaml │ │ ├── README.md │ │ └── tests │ │ │ └── integration │ │ │ └── test_agent.py │ ├── adk_live │ │ ├── .template │ │ │ └── templateconfig.yaml │ │ ├── tests │ │ │ └── unit │ │ │ │ └── test_dummy.py │ │ ├── app │ │ │ └── agent.py │ │ └── README.md │ └── crewai_coding_crew │ │ ├── .template │ │ └── templateconfig.yaml │ │ ├── app │ │ ├── crew │ │ │ ├── config │ │ │ │ ├── agents.yaml │ │ │ │ └── tasks.yaml │ │ │ └── crew.py │ │ └── agent.py │ │ ├── README.md │ │ └── tests │ │ └── integration │ │ └── test_agent.py ├── data_ingestion │ └── pyproject.toml ├── cli │ ├── utils │ │ ├── datastores.py │ │ ├── __init__.py │ │ └── version.py │ └── main.py └── utils │ └── lock_utils.py ├── docs ├── images │ ├── icon.png │ ├── logo.png │ ├── adk_logo.png │ ├── why_sp_edited.png │ ├── prototype_to_prod.png │ ├── why_starter_pack.png │ ├── adk_gemini_fullstack.gif │ ├── ags_high_level_architecture.png │ ├── agent_starter_pack_screenshot.png │ └── adk_gemini_fullstack_architecture.png ├── package.json ├── cli │ ├── index.md │ └── list.md ├── guide │ ├── video-tutorials.md │ ├── community-showcase.md │ ├── observability.md │ ├── troubleshooting.md │ ├── getting-started.md │ └── data-ingestion.md ├── index.md └── remote-templates │ └── index.md ├── .cloudbuild ├── terraform │ ├── backend.tf │ ├── vars │ │ └── env.tfvars │ ├── storage.tf │ ├── apis.tf │ ├── variables.tf │ └── service_account.tf ├── ci │ ├── build_use_wheel.yaml │ ├── test.yaml │ ├── test_makefile.yaml │ ├── test_remote_template.yaml │ ├── test_pipeline_parity.yaml │ ├── lint_templated_agents.yaml │ ├── test_templated_agents.yaml │ └── lint.yaml └── cd │ └── test_e2e.yaml ├── Makefile ├── .github └── workflows │ └── docs.yml └── CODE_OF_CONDUCT.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Empty file to make the directory a package 2 | -------------------------------------------------------------------------------- /tests/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Empty file to make the directory a package 2 | -------------------------------------------------------------------------------- /agent_starter_pack/deployment_targets/agent_engine/tests/load_test/.results/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/icon.png -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/adk_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/adk_logo.png -------------------------------------------------------------------------------- /docs/images/why_sp_edited.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/why_sp_edited.png -------------------------------------------------------------------------------- /docs/images/prototype_to_prod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/prototype_to_prod.png -------------------------------------------------------------------------------- /docs/images/why_starter_pack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/why_starter_pack.png -------------------------------------------------------------------------------- /docs/images/adk_gemini_fullstack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/adk_gemini_fullstack.gif -------------------------------------------------------------------------------- /docs/images/ags_high_level_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/ags_high_level_architecture.png -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /docs/images/agent_starter_pack_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/agent_starter_pack_screenshot.png -------------------------------------------------------------------------------- /agent_starter_pack/deployment_targets/agent_engine/deployment_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "remote_agent_engine_id": "None", 3 | "deployment_timestamp": "None" 4 | } -------------------------------------------------------------------------------- /docs/images/adk_gemini_fullstack_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/docs/images/adk_gemini_fullstack_architecture.png -------------------------------------------------------------------------------- /.cloudbuild/terraform/backend.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "gcs" { 3 | bucket = "agent-starter-pack-cicd-terraform-state" 4 | prefix = "cloudbuild" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/GEMINI.md: -------------------------------------------------------------------------------- 1 | Coding Agent guidance: 2 | {%- if cookiecutter.is_adk %} 3 | {{ cookiecutter.adk_cheatsheet }} 4 | {%- endif %} 5 | {{ cookiecutter.llm_txt }} -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Otutu11/agent-starter-pack/main/agent_starter_pack/frontends/adk_live_react/frontend/public/favicon.ico -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-docs", 3 | "version": "1.0.0", 4 | "description": "Project documentation", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "docs:dev": "vitepress dev", 9 | "docs:build": "vitepress build", 10 | "docs:preview": "vitepress preview" 11 | }, 12 | "devDependencies": { 13 | "vitepress": "^1.6.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.cloudbuild/terraform/vars/env.tfvars: -------------------------------------------------------------------------------- 1 | cicd_runner_project_id = "agent-starter-pack-cicd" 2 | 3 | region = "europe-west4" 4 | 5 | host_connection_name = "git-connection" 6 | 7 | repository_name = "GoogleCloudPlatform-agent-starter-pack" 8 | 9 | e2e_test_project_mapping = { 10 | dev = "agent-starter-pack-e2e-dev" 11 | staging = "agent-starter-pack-e2e-st" 12 | prod = "agent-starter-pack-e2e-pr" 13 | } 14 | -------------------------------------------------------------------------------- /agent_starter_pack/resources/idx/idx-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Agent Starter Pack", 3 | "description": "Production-ready Gen AI Agent templates for Google Cloud. Addressing common challenges (Deployment & Operations, Evaluation, Customization, Observability) in building and deploying GenAI agents.", 4 | "icon": "https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/icon.png?raw=true", 5 | "params": [] 6 | } 7 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/README.md: -------------------------------------------------------------------------------- 1 | # Agent Templates 2 | 3 | This directory contains template implementations for various agents designed to work with the Agent Starter Pack templating system. 4 | Feel free to browse through these folders to preview what each template offers. 5 | Direct cloning of this repository isn't necessary to utilize these templates. 6 | 7 | For setup instructions and getting started, please refer to the main [README](/README.md) which explains how to install and use the Agent Starter Pack. 8 | -------------------------------------------------------------------------------- /agent_starter_pack/data_ingestion/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "data-ingestion-pipeline" 3 | version = "0.1.0" 4 | description = "Data ingestion pipeline for RAG retriever" 5 | readme = "README.md" 6 | requires-python = ">=3.9, <=3.13" 7 | dependencies = [ 8 | "google-cloud-aiplatform>=1.80.0", 9 | "google-cloud-pipeline-components>=2.19.0", 10 | "kfp>=1.4.0", 11 | ] 12 | 13 | [build-system] 14 | requires = ["hatchling"] 15 | build-backend = "hatchling.build" 16 | 17 | [tool.hatch.build.targets.wheel] 18 | packages = ["data_ingestion_pipeline"] -------------------------------------------------------------------------------- /agent_starter_pack/agents/langgraph_base_react/README.md: -------------------------------------------------------------------------------- 1 | # LangGraph Base React Agent 2 | 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 | 5 | ## Key Features 6 | 7 | - **Simple Architecture**: Shows the basic building blocks of a LangGraph agent 8 | - **Streaming Support**: Includes streaming response capability using Vertex AI 9 | - **Sample Tool Integration**: Includes a basic search tool to demonstrate tool usage 10 | -------------------------------------------------------------------------------- /tests/cicd/example.env: -------------------------------------------------------------------------------- 1 | # Example environment variables for E2E testing 2 | # Replace these values with your actual project IDs and credentials 3 | 4 | # GCP Project IDs for different environments 5 | E2E_DEV_PROJECT="your-dev-project-id" 6 | E2E_STAGING_PROJECT="your-staging-project-id" 7 | E2E_PROD_PROJECT="your-prod-project-id" 8 | E2E_CICD_PROJECT="your-cicd-project-id" 9 | 10 | # GitHub credentials 11 | GITHUB_PAT="your-github-personal-access-token" 12 | GITHUB_APP_INSTALLATION_ID="your-github-app-installation-id" 13 | 14 | # Enable E2E tests (set to 1 to run) 15 | RUN_E2E_TESTS=1 -------------------------------------------------------------------------------- /docs/cli/index.md: -------------------------------------------------------------------------------- 1 | # CLI Reference 2 | 3 | The Agent Starter Pack provides a command-line interface (CLI) to create and setup Generative AI Agent templates in Google Cloud. 4 | 5 | ## Available Commands 6 | 7 | - [`create`](create.md) - Create a new generative AI application project 8 | - [`setup-cicd`](setup_cicd.md) - Set up CI/CD pipeline for your project 9 | - [`enhance`](enhance.md) - Add agent-starter-pack capabilities to existing projects without creating a new directory 10 | - [`list`](list.md) - List available agents and templates 11 | 12 | For detailed usage instructions, click on the command links above. 13 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_base/app/__init__.py: -------------------------------------------------------------------------------- 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 | from .agent import root_agent 16 | 17 | __all__ = ["root_agent"] 18 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/agentic_rag/app/__init__.py: -------------------------------------------------------------------------------- 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 | from .agent import root_agent 16 | 17 | __all__ = ["root_agent"] 18 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "preserve" 18 | }, 19 | "include": ["src", "src/**/*"], 20 | "ts-node": { 21 | "compilerOptions": { 22 | "module": "commonjs" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/README.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | 3 | This directory contains the Terraform configurations for provisioning the necessary Google Cloud infrastructure for your agent. 4 | 5 | The recommended way to deploy the infrastructure and set up the CI/CD pipeline is by using the `agent-starter-pack setup-cicd` command from the root of your project. 6 | 7 | However, for a more hands-on approach, you can always apply the Terraform configurations manually for a do-it-yourself setup. 8 | 9 | For detailed information on the deployment process, infrastructure, and CI/CD pipelines, please refer to the official documentation: 10 | 11 | **[Agent Starter Pack Deployment Guide](https://googlecloudplatform.github.io/agent-starter-pack/guide/deployment.html)** -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /// 18 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/dev/vars/env.tfvars: -------------------------------------------------------------------------------- 1 | # Project name used for resource naming 2 | project_name = "{{ cookiecutter.project_name | replace('_', '-') }}" 3 | 4 | # Your Dev Google Cloud project id 5 | dev_project_id = "your-dev-project-id" 6 | 7 | # The Google Cloud region you will use to deploy the infrastructure 8 | region = "us-central1" 9 | 10 | {%- if cookiecutter.data_ingestion %} 11 | {%- if cookiecutter.datastore_type == "vertex_ai_search" %} 12 | # The value can only be one of "global", "us" and "eu". 13 | data_store_region = "us" 14 | {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %} 15 | vector_search_shard_size = "SHARD_SIZE_SMALL" 16 | vector_search_machine_type = "e2-standard-2" 17 | vector_search_min_replica_count = 1 18 | vector_search_max_replica_count = 1 19 | {%- endif %} 20 | {%- endif %} 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | uv run pytest tests 3 | 4 | test-templated-agents: 5 | uv run pytest tests/integration/test_templated_patterns.py 6 | 7 | test-e2e: 8 | set -a && . tests/cicd/.env && set +a && uv run pytest tests/cicd/test_e2e_deployment.py -v 9 | 10 | generate-lock: 11 | uv run python -m agent_starter_pack.utils.generate_locks 12 | 13 | lint: 14 | uv sync --dev --extra lint 15 | uv run ruff check . --config pyproject.toml --diff 16 | uv run ruff format . --check --config pyproject.toml --diff 17 | uv run mypy --config-file pyproject.toml ./agent_starter_pack/cli ./tests ./agent_starter_pack/frontends/streamlit 18 | 19 | lint-templated-agents: 20 | uv run tests/integration/test_template_linting.py 21 | 22 | clean: 23 | rm -rf target/* 24 | 25 | install: 26 | uv sync --dev --extra lint --frozen 27 | 28 | docs-dev: 29 | cd docs && npm install && NODE_OPTIONS="--no-warnings" npm run docs:dev 30 | 31 | 32 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/hooks/use-media-stream-mux.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export type UseMediaStreamResult = { 18 | type: "webcam" | "screen"; 19 | start: () => Promise; 20 | stop: () => void; 21 | isStreaming: boolean; 22 | stream: MediaStream | null; 23 | }; 24 | -------------------------------------------------------------------------------- /agent_starter_pack/resources/idx/idx-template.nix: -------------------------------------------------------------------------------- 1 | 2 | # No user-configurable parameters 3 | # Accept additional arguments to this template corresponding to template 4 | # parameter IDs 5 | { pkgs, agent_name ? "", google_cloud_project_id ? "", ... }: { 6 | # Shell script that produces the final environment 7 | bootstrap = '' 8 | # Copy the folder containing the `idx-template` files to the final 9 | # project folder for the new workspace. ${./.} inserts the directory 10 | # of the checked-out Git folder containing this template. 11 | cp -rf ${./.} "$out" 12 | 13 | # Set some permissions 14 | chmod -R +w "$out" 15 | 16 | # Create .env file with the parameter values 17 | cat > "$out/.env" << EOF 18 | WS_NAME=$WS_NAME 19 | EOF 20 | 21 | # Remove the template files themselves and any connection to the template's 22 | # Git repository 23 | rm -rf "$out/.git" "$out/idx-template".{nix,json} 24 | ''; 25 | } -------------------------------------------------------------------------------- /docs/cli/list.md: -------------------------------------------------------------------------------- 1 | # list 2 | 3 | List available agents and templates. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | uvx agent-starter-pack list [OPTIONS] 9 | ``` 10 | 11 | ## Options 12 | 13 | - `--source URL` - List templates from a specific repository 14 | - `--adk` - List official ADK samples 15 | 16 | ## Examples 17 | 18 | ```bash 19 | # List built-in agents 20 | uvx agent-starter-pack list 21 | 22 | # List ADK samples 23 | uvx agent-starter-pack list --adk 24 | 25 | # List templates from repository 26 | uvx agent-starter-pack list --source https://github.com/user/templates 27 | ``` 28 | 29 | ## Notes 30 | 31 | Only templates with `[tool.agent-starter-pack]` configuration in `pyproject.toml` appear in listings. Templates without this configuration still work with `create` but aren't discoverable. 32 | 33 | ## Related 34 | 35 | - [`create`](./create.md) - Create agents from templates 36 | - [Remote Templates](../remote-templates/) - Template documentation -------------------------------------------------------------------------------- /tests/fixtures/makefile_hashes.json: -------------------------------------------------------------------------------- 1 | { 2 | "adk_base_agent_engine_no_data": "d76c4fc040b90d51d76b2fc9dbd87bb7847aaf20b34ca937ab5e9abfbba919b9", 3 | "adk_base_cloud_run_no_data": "8b0ea9af5af817c5beb4956d9e49340f4886c634f77e0e8eee7bf82bfb8334b1", 4 | "adk_live_agent_engine": "8f06eddcaf097543eb8df6a39e22fd435f9e53ffc007f321add49e25822779f6", 5 | "adk_live_cloud_run": "789fbc07ec267d86f7e779ba4229930b6bc3e243871e5bf3ee32f497503bc552", 6 | "agent_with_agent_garden": "e08b4fd290f1f83828b48a8f663d75e8fa3745a05c2125f9d746b8eea77b7c1f", 7 | "agent_with_custom_commands": "02b5764b75be952a06abfbb8a4e15cdf6a671652f290f9ffb2994dc9aa9382ff", 8 | "agentic_rag_cloud_run_vector_search": "ec10406d7bf56d6dc253cbce8254ee33c923f369d04f406227dc5ca401564aad", 9 | "agentic_rag_cloud_run_vertex_search": "83edd4467bff3418f619c2fcb0b449646a8a5dd2aea85c60075052f8c837e0a6", 10 | "langgraph_cloud_run_no_data": "c690f5792208e6834dd389ab448784819ca97405d01a824b4534ab256e3f1c6a" 11 | } -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_base/README.md: -------------------------------------------------------------------------------- 1 | # ADK: Minimal Agent Example 2 | 3 | 4 | 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 | 7 | This agent uses the `gemini-2.5-flash` model and is equipped with two simple tools: 8 | * `get_weather`: Simulates fetching weather (hardcoded for SF). 9 | * `get_current_time`: Simulates fetching the time (hardcoded for SF). 10 | 11 | ## Additional Resources 12 | 13 | - **ADK Samples**: Explore more examples and use cases in the [official ADK Samples Repository](https://github.com/google/adk-samples) 14 | - **ADK Documentation**: Learn more about ADK concepts and capabilities in the [official documentation](https://google.github.io/adk-docs/) 15 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 18 | // allows you to do things like: 19 | // expect(element).toHaveTextContent(/react/i) 20 | // learn more: https://github.com/testing-library/jest-dom 21 | import "@testing-library/jest-dom"; 22 | -------------------------------------------------------------------------------- /.cloudbuild/terraform/storage.tf: -------------------------------------------------------------------------------- 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 | resource "google_storage_bucket" "logs_data_bucket" { 16 | name = "${var.cicd_runner_project_id}-logs-data" 17 | location = var.region 18 | project = var.cicd_runner_project_id 19 | uniform_bucket_level_access = true 20 | force_destroy = true 21 | } 22 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/tests/unit/test_dummy.py: -------------------------------------------------------------------------------- 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 | You can add your unit tests here. 16 | This is where you test your business logic, including agent functionality, 17 | data processing, and other core components of your application. 18 | """ 19 | 20 | 21 | def test_dummy() -> None: 22 | """Placeholder - replace with real tests.""" 23 | assert 1 == 1 24 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/agentic_rag/app/templates.py: -------------------------------------------------------------------------------- 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 | from langchain_core.prompts import ( 16 | PromptTemplate, 17 | ) 18 | 19 | format_docs = PromptTemplate.from_template( 20 | """## Context provided: 21 | {% for doc in docs%} 22 | 23 | {{ doc.page_content | safe }} 24 | 25 | {% endfor %} 26 | """, 27 | template_format="jinja2", 28 | ) 29 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import { render, screen } from '@testing-library/react'; 19 | import App from './App'; 20 | 21 | test('renders learn react link', () => { 22 | render(); 23 | const linkElement = screen.getByText(/learn react/i); 24 | expect(linkElement).toBeInTheDocument(); 25 | }); 26 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_base/.template/templateconfig.yaml: -------------------------------------------------------------------------------- 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 | description: "A base ReAct agent built with Google's Agent Development Kit (ADK)" 16 | example_question: "What's the weather in San Francisco?" 17 | settings: 18 | requires_data_ingestion: false 19 | requires_session: true 20 | deployment_targets: ["agent_engine", "cloud_run"] 21 | extra_dependencies: ["google-adk>=1.15.0,<2.0.0"] 22 | tags: ["adk"] 23 | frontend_type: "None" 24 | 25 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/dev/providers.tf: -------------------------------------------------------------------------------- 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 | terraform { 16 | required_version = ">= 1.0.0" 17 | required_providers { 18 | google = { 19 | source = "hashicorp/google" 20 | version = "< 7.0.0" 21 | } 22 | } 23 | } 24 | 25 | provider "google" { 26 | alias = "dev_billing_override" 27 | billing_project = var.dev_project_id 28 | region = var.region 29 | user_project_override = true 30 | } 31 | -------------------------------------------------------------------------------- /agent_starter_pack/resources/containers/data_processing/Dockerfile: -------------------------------------------------------------------------------- 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 | FROM python:3.11-slim 16 | 17 | RUN pip install --no-cache-dir \ 18 | "bigframes==1.36.0" \ 19 | "langchain==0.3.18" \ 20 | "markdownify==0.14.1" \ 21 | "swifter==1.4.0" \ 22 | "google-cloud-aiplatform>=1.80.0" \ 23 | "kfp>=1.4.0" \ 24 | "google-cloud-discoveryengine==0.13.6" \ 25 | "backoff==2.2.1" \ 26 | "google-cloud-pipeline-components==2.19.0" \ 27 | "langchain-google-vertexai==2.0.13" 28 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2025 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | body { 18 | margin: 0; 19 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 20 | Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; 21 | -webkit-font-smoothing: antialiased; 22 | -moz-osx-font-smoothing: grayscale; 23 | } 24 | 25 | code { 26 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 27 | monospace; 28 | } 29 | -------------------------------------------------------------------------------- /.cloudbuild/terraform/apis.tf: -------------------------------------------------------------------------------- 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 | # Enable Cloud Resource Manager API for each project in e2e_test_project_mapping 16 | resource "google_project_service" "cloud_resource_manager_api" { 17 | for_each = { 18 | "dev" = var.e2e_test_project_mapping.dev 19 | "staging" = var.e2e_test_project_mapping.staging 20 | "prod" = var.e2e_test_project_mapping.prod 21 | } 22 | 23 | project = each.value 24 | service = "cloudresourcemanager.googleapis.com" 25 | disable_on_destroy = false 26 | } 27 | -------------------------------------------------------------------------------- /.cloudbuild/ci/build_use_wheel.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-use-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv build && pip install dist/*.whl && agent-starter-pack create my-agent-$(date +%s) -a agentic_rag -ds vertex_ai_search -d agent_engine --auto-approve 24 | 25 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 26 | options: 27 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 28 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_live/.template/templateconfig.yaml: -------------------------------------------------------------------------------- 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 | description: "Real-time multimodal agent with ADK and Gemini Live API for low-latency voice and video interaction." 16 | settings: 17 | requires_data_ingestion: false 18 | frontend_type: "adk_live_react" 19 | deployment_targets: ["agent_engine", "cloud_run"] 20 | extra_dependencies: ["google-adk>=1.15.0,<2.0.0", "click>=8.0.0,<9.0.0", "uvicorn>=0.18.0,<1.0.0", "fastapi>=0.75.0,<1.0.0", "backoff>=2.0.0,<3.0.0"] 21 | tags: ["adk", "adk_live"] 22 | example_question: "What's the weather in San Francisco?" 23 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { ReportHandler } from "web-vitals"; 18 | 19 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 20 | if (onPerfEntry && onPerfEntry instanceof Function) { 21 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 22 | getCLS(onPerfEntry); 23 | getFID(onPerfEntry); 24 | getFCP(onPerfEntry); 25 | getLCP(onPerfEntry); 26 | getTTFB(onPerfEntry); 27 | }); 28 | } 29 | }; 30 | 31 | export default reportWebVitals; 32 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/.template/templateconfig.yaml: -------------------------------------------------------------------------------- 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 | description: "A multi-agent system implemented with CrewAI created to support coding activities" 16 | settings: 17 | requires_data_ingestion: false 18 | deployment_targets: ["agent_engine", "cloud_run"] 19 | extra_dependencies: [ 20 | "langchain-google-vertexai~=2.0.22", 21 | "langchain~=0.3.14", 22 | "langchain-community~=0.3.17", 23 | "langchain-openai~=0.3.5", 24 | "langgraph~=0.6.2", 25 | "crewai~=0.152.0" 26 | ] 27 | example_question: "How can I implement a function to sort a list in Python?" 28 | -------------------------------------------------------------------------------- /agent_starter_pack/cli/utils/datastores.py: -------------------------------------------------------------------------------- 1 | """Datastore types and descriptions for data ingestion.""" 2 | 3 | # Dictionary mapping datastore types to their descriptions 4 | DATASTORES = { 5 | "vertex_ai_search": { 6 | "name": "Vertex AI Search", 7 | "description": "Managed, serverless document store that enables Google-quality search and RAG for generative AI.", 8 | }, 9 | "vertex_ai_vector_search": { 10 | "name": "Vertex AI Vector Search", 11 | "description": "Scalable vector search engine for building search, recommendation systems, and generative AI applications. Based on ScaNN algorithm.", 12 | }, 13 | } 14 | 15 | DATASTORE_TYPES = list(DATASTORES.keys()) 16 | 17 | 18 | def get_datastore_info(datastore_type: str) -> dict: 19 | """Get information about a datastore type. 20 | 21 | Args: 22 | datastore_type: The datastore type key 23 | 24 | Returns: 25 | Dictionary with datastore information 26 | 27 | Raises: 28 | ValueError: If the datastore type is not valid 29 | """ 30 | if datastore_type not in DATASTORES: 31 | raise ValueError(f"Invalid datastore type: {datastore_type}") 32 | return DATASTORES[datastore_type] 33 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/langgraph_base_react/.template/templateconfig.yaml: -------------------------------------------------------------------------------- 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 | description: "An agent implementing a base ReAct agent using LangGraph" 16 | settings: 17 | requires_data_ingestion: false 18 | deployment_targets: ["agent_engine", "cloud_run"] 19 | extra_dependencies: [ 20 | "langchain-google-vertexai~=2.0.7", 21 | "langchain~=0.3.14", 22 | "langgraph~=0.6.2", 23 | "langchain-google-vertexai~=2.0.22", 24 | "langchain~=0.3.14", 25 | "langchain-community~=0.3.17", 26 | "langchain-openai~=0.3.5", 27 | ] 28 | example_question: "What's the weather in San Francisco?" 29 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/streamlit/frontend/style/app_markdown.py: -------------------------------------------------------------------------------- 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 | MARKDOWN_STR = """ 16 | 37 | """ 38 | -------------------------------------------------------------------------------- /.cloudbuild/ci/test.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --dev --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: unit-tests 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run pytest tests 33 | 34 | 35 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 36 | options: 37 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 38 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import ReactDOM from 'react-dom/client'; 19 | import './index.css'; 20 | import App from './App'; 21 | import reportWebVitals from './reportWebVitals'; 22 | 23 | const root = ReactDOM.createRoot( 24 | document.getElementById('root') as HTMLElement 25 | ); 26 | root.render( 27 | 28 | 29 | 30 | ); 31 | 32 | // If you want to start measuring performance in your app, pass a function 33 | // to log results (for example: reportWebVitals(console.log)) 34 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 35 | reportWebVitals(); 36 | -------------------------------------------------------------------------------- /.cloudbuild/ci/test_makefile.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: test-templated-agents 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run pytest tests/integration/test_makefile_usability.py 33 | 34 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 35 | options: 36 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 37 | -------------------------------------------------------------------------------- /.cloudbuild/ci/test_remote_template.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: test-templated-agents 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run pytest tests/integration/test_remote_templating.py 33 | 34 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 35 | options: 36 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 37 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/langgraph_base_react/app/agent.py: -------------------------------------------------------------------------------- 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 | # mypy: disable-error-code="union-attr" 16 | from langchain_google_vertexai import ChatVertexAI 17 | from langgraph.prebuilt import create_react_agent 18 | 19 | LOCATION = "global" 20 | LLM = "gemini-2.5-flash" 21 | 22 | llm = ChatVertexAI(model=LLM, location=LOCATION, temperature=0) 23 | 24 | 25 | def get_weather(query: str) -> str: 26 | """Simulates a web search. Use it get information on weather""" 27 | if "sf" in query.lower() or "san francisco" in query.lower(): 28 | return "It's 60 degrees and foggy." 29 | return "It's 90 degrees and sunny." 30 | 31 | 32 | agent = create_react_agent( 33 | model=llm, tools=[get_weather], prompt="You are a helpful assistant" 34 | ) 35 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/app/crew/config/agents.yaml: -------------------------------------------------------------------------------- 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 | senior_engineer_agent: 16 | role: > 17 | Senior Software Engineer 18 | 19 | 20 | goal: > 21 | Create software as needed 22 | 23 | 24 | backstory: > 25 | You are a Senior Software Engineer at a leading tech company. You are an expert Python programmer and do your best to produce perfect code. 26 | 27 | 28 | chief_qa_engineer_agent: 29 | role: > 30 | Chief Software Quality Control Engineer 31 | 32 | 33 | goal: > 34 | Ensure that the code does the job that it is supposed to do and that it is error free. 35 | 36 | 37 | backstory: > 38 | You feel that programmers always do only half the job, so you are super dedicate to make high quality code. 39 | 40 | -------------------------------------------------------------------------------- /.cloudbuild/ci/test_pipeline_parity.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --dev --locked 24 | 25 | # Run pipeline parity tests 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: pipeline-parity-tests 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run pytest tests/integration/test_pipeline_parity.py -v 33 | 34 | 35 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 36 | options: 37 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 38 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multimodal-live-api-web-console", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "classnames": "^2.5.1", 6 | "eventemitter3": "^5.0.1", 7 | "lodash": "^4.17.21", 8 | "react": "^18.3.1", 9 | "react-dom": "^18.3.1", 10 | "react-icons": "^5.3.0", 11 | "react-scripts": "5.0.1", 12 | "react-select": "^5.8.3", 13 | "sass": "^1.80.6", 14 | "web-vitals": "^2.1.4", 15 | "zustand": "^5.0.1" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": {}, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | }, 36 | "devDependencies": { 37 | "@google/generative-ai": "^0.21.0", 38 | "@testing-library/jest-dom": "^5.17.0", 39 | "@testing-library/react": "^13.4.0", 40 | "@types/lodash": "^4.17.13", 41 | "@types/react": "^18.3.12", 42 | "@types/react-dom": "^18.3.1", 43 | "typescript": "^5.6.3" 44 | }, 45 | "overrides": { 46 | "typescript": "^5.6.3" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/providers.tf: -------------------------------------------------------------------------------- 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 | 16 | terraform { 17 | required_version = ">= 1.0.0" 18 | required_providers { 19 | google = { 20 | source = "hashicorp/google" 21 | version = "< 7.0.0" 22 | } 23 | github = { 24 | source = "integrations/github" 25 | version = "~> 6.5.0" 26 | } 27 | } 28 | } 29 | 30 | provider "google" { 31 | alias = "staging_billing_override" 32 | billing_project = var.staging_project_id 33 | region = var.region 34 | user_project_override = true 35 | } 36 | 37 | provider "google" { 38 | alias = "prod_billing_override" 39 | billing_project = var.prod_project_id 40 | region = var.region 41 | user_project_override = true 42 | } 43 | -------------------------------------------------------------------------------- /.cloudbuild/ci/lint_templated_agents.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: lint-templated-agents 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run tests/integration/test_template_linting.py 33 | 34 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 35 | options: 36 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 37 | env: 38 | - "_TEST_AGENT_COMBINATION=${_TEST_AGENT_COMBINATION}" 39 | -------------------------------------------------------------------------------- /.cloudbuild/ci/test_templated_agents.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: test-templated-agents 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | uv run pytest tests/integration/test_templated_patterns.py 33 | 34 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 35 | options: 36 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 37 | env: 38 | - "_TEST_AGENT_COMBINATION=${_TEST_AGENT_COMBINATION}" -------------------------------------------------------------------------------- /agent_starter_pack/agents/agentic_rag/.template/templateconfig.yaml: -------------------------------------------------------------------------------- 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 | description: "ADK RAG agent for document retrieval and Q&A. Includes a data pipeline for ingesting and indexing documents into Vertex AI Search or Vector Search." 16 | example_question: "How to save a pandas dataframe to CSV?" 17 | settings: 18 | requires_data_ingestion: true 19 | requires_session: true 20 | deployment_targets: ["agent_engine", "cloud_run"] 21 | extra_dependencies: [ 22 | "google-adk>=1.15.0,<2.0.0", 23 | "langchain-google-vertexai~=2.0.7", 24 | "langchain~=0.3.24", 25 | "langchain-core~=0.3.55", 26 | "langchain-community~=0.3.17", 27 | "langchain-openai~=0.3.5", 28 | "langchain-google-community[vertexaisearch]~=2.0.7", 29 | "Jinja2~=3.1.6", 30 | ] 31 | tags: ["adk"] 32 | frontend_type: "None" 33 | -------------------------------------------------------------------------------- /agent_starter_pack/cli/utils/__init__.py: -------------------------------------------------------------------------------- 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 | from .datastores import DATASTORE_TYPES, get_datastore_info 16 | from .gcp import verify_credentials 17 | from .logging import handle_cli_error 18 | from .template import ( 19 | get_available_agents, 20 | get_deployment_targets, 21 | get_template_path, 22 | load_template_config, 23 | process_template, 24 | prompt_datastore_selection, 25 | prompt_deployment_target, 26 | ) 27 | from .version import display_update_message 28 | 29 | __all__ = [ 30 | "DATASTORE_TYPES", 31 | "display_update_message", 32 | "get_available_agents", 33 | "get_datastore_info", 34 | "get_deployment_targets", 35 | "get_template_path", 36 | "handle_cli_error", 37 | "load_template_config", 38 | "process_template", 39 | "prompt_datastore_selection", 40 | "prompt_deployment_target", 41 | "verify_credentials", 42 | ] 43 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/utils/audioworklet-registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * A registry to map attached worklets by their audio-context 19 | * any module using `audioContext.audioWorklet.addModule(` should register the worklet here 20 | */ 21 | export type WorkletGraph = { 22 | node?: AudioWorkletNode; 23 | handlers: Array<(this: MessagePort, ev: MessageEvent) => any>; 24 | }; 25 | 26 | export const registeredWorklets: Map< 27 | AudioContext, 28 | Record 29 | > = new Map(); 30 | 31 | export const createWorketFromSrc = ( 32 | workletName: string, 33 | workletSrc: string, 34 | ) => { 35 | const script = new Blob( 36 | [`registerProcessor("${workletName}", ${workletSrc})`], 37 | { 38 | type: "application/javascript", 39 | }, 40 | ); 41 | 42 | return URL.createObjectURL(script); 43 | }; 44 | -------------------------------------------------------------------------------- /.cloudbuild/terraform/variables.tf: -------------------------------------------------------------------------------- 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 | variable "cicd_runner_project_id" { 16 | type = string 17 | description = "Google Cloud Project ID where CI/CD pipelines will execute." 18 | } 19 | 20 | variable "region" { 21 | type = string 22 | description = "Google Cloud region for resource deployment." 23 | default = "us-central1" 24 | } 25 | 26 | variable "host_connection_name" { 27 | description = "Name of the host connection you created in Cloud Build" 28 | type = string 29 | } 30 | 31 | variable "repository_name" { 32 | description = "Name of the repository you'd like to connect to Cloud Build" 33 | type = string 34 | } 35 | 36 | variable "e2e_test_project_mapping" { 37 | description = "Mapping of project IDs for different environments" 38 | type = object({ 39 | dev = string 40 | prod = string 41 | staging = string 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Docs to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - 'docs/**' 8 | - '.github/workflows/docs.yml' 9 | workflow_dispatch: 10 | 11 | permissions: 12 | contents: read 13 | pages: write 14 | id-token: write 15 | 16 | concurrency: 17 | group: "pages" 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup Node.js 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version: 18 31 | cache: 'npm' 32 | cache-dependency-path: docs/package-lock.json 33 | 34 | - name: Install dependencies 35 | working-directory: docs 36 | run: npm ci 37 | 38 | - name: Build VitePress site 39 | working-directory: docs 40 | run: | 41 | npm run docs:build 42 | 43 | - name: Setup Pages 44 | id: pages 45 | uses: actions/configure-pages@v5 46 | 47 | - name: Upload artifact 48 | uses: actions/upload-pages-artifact@v3 49 | with: 50 | path: docs/.vitepress/dist 51 | 52 | deploy: 53 | environment: 54 | name: github-pages 55 | url: ${{ steps.deployment.outputs.page_url }} 56 | runs-on: ubuntu-latest 57 | needs: build 58 | steps: 59 | - name: Deploy to GitHub Pages 60 | id: deployment 61 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.cloudbuild/ci/lint.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --dev --extra lint --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: lint 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | set -e 33 | uv run ruff check . --config pyproject.toml --diff 34 | uv run ruff format . --check --config pyproject.toml --diff 35 | uv run mypy --config-file pyproject.toml ./agent_starter_pack/cli ./tests ./agent_starter_pack/frontends/streamlit 36 | 37 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 38 | options: 39 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 40 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/vars/env.tfvars: -------------------------------------------------------------------------------- 1 | # Project name used for resource naming 2 | project_name = "{{ cookiecutter.project_name | replace('_', '-') }}" 3 | 4 | # Your Production Google Cloud project id 5 | prod_project_id = "your-production-project-id" 6 | 7 | # Your Staging / Test Google Cloud project id 8 | staging_project_id = "your-staging-project-id" 9 | 10 | # Your Google Cloud project ID that will be used to host the Cloud Build pipelines. 11 | cicd_runner_project_id = "your-cicd-project-id" 12 | 13 | {%- if cookiecutter.cicd_runner == "google_cloud_build" %} 14 | # Name of the host connection you created in Cloud Build 15 | host_connection_name = "git-{{cookiecutter.project_name}}" 16 | github_pat_secret_id = "your-github_pat_secret_id" 17 | {%- endif %} 18 | 19 | repository_owner = "Your GitHub organization or username." 20 | 21 | # Name of the repository you added to Cloud Build 22 | repository_name = "{{cookiecutter.project_name}}" 23 | 24 | # The Google Cloud region you will use to deploy the infrastructure 25 | region = "us-central1" 26 | 27 | {%- if cookiecutter.data_ingestion %} 28 | pipeline_cron_schedule = "0 0 * * 0" 29 | 30 | {%- if cookiecutter.datastore_type == "vertex_ai_search" %} 31 | #The value can only be one of "global", "us" and "eu". 32 | data_store_region = "us" 33 | {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %} 34 | vector_search_shard_size = "SHARD_SIZE_SMALL" 35 | vector_search_machine_type = "e2-standard-2" 36 | vector_search_min_replica_count = 1 37 | vector_search_max_replica_count = 1 38 | {%- endif %} 39 | {%- endif %} 40 | -------------------------------------------------------------------------------- /docs/guide/video-tutorials.md: -------------------------------------------------------------------------------- 1 | # Video Tutorials 2 | 3 | ## Exploring Agent Starter Pack (April 2025) 4 | 5 | This comprehensive tutorial demonstrates how to rapidly deploy AI Agents using the Agent Starter Pack. We cover the architecture, detail the templates and their usage, showcase a live demo, and guide you through template-based deployment from start to finish. 6 | 7 | 8 | 9 | ## Kaggle GenAI Intensive Course Introduction (April 2025) 10 | A 6-minute introduction explaining the Agent Starter Pack and demonstrating its key features. Part of the Kaggle GenAI intensive course. 11 | 12 | 13 | 14 | ## Livestream Demo: Building 3 Agents in Under 30 Minutes (March 2025) 15 | A 120-minute livestream demonstration of the `agent-starter-pack` where we build 3 Agents in under 30 minutes! 16 | 17 | 18 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/contexts/LiveAPIContext.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { createContext, FC, ReactNode, useContext } from "react"; 18 | import { useLiveAPI, UseLiveAPIResults } from "../hooks/use-live-api"; 19 | 20 | const LiveAPIContext = createContext(undefined); 21 | 22 | export type LiveAPIProviderProps = { 23 | children: ReactNode; 24 | url?: string; 25 | userId?: string; 26 | }; 27 | 28 | export const LiveAPIProvider: FC = ({ 29 | url, 30 | userId, 31 | children, 32 | }) => { 33 | const liveAPI = useLiveAPI({ url, userId }); 34 | 35 | return ( 36 | 37 | {children} 38 | 39 | ); 40 | }; 41 | 42 | export const useLiveAPIContext = () => { 43 | const context = useContext(LiveAPIContext); 44 | if (!context) { 45 | throw new Error("useLiveAPIContext must be used within a LiveAPIProvider"); 46 | } 47 | return context; 48 | }; 49 | -------------------------------------------------------------------------------- /agent_starter_pack/deployment_targets/cloud_run/Dockerfile: -------------------------------------------------------------------------------- 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 | FROM python:3.11-slim 16 | 17 | RUN pip install --no-cache-dir uv==0.8.13 18 | 19 | {%- if cookiecutter.is_adk_live %} 20 | # Install Node.js for frontend build 21 | RUN apt-get update && apt-get install -y \ 22 | curl \ 23 | && curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ 24 | && apt-get install -y nodejs \ 25 | && apt-get clean \ 26 | && rm -rf /var/lib/apt/lists/* 27 | {%- endif %} 28 | 29 | WORKDIR /code 30 | 31 | COPY ./pyproject.toml ./README.md ./uv.lock* ./ 32 | 33 | COPY ./{{cookiecutter.agent_directory}} ./{{cookiecutter.agent_directory}} 34 | 35 | {%- if cookiecutter.is_adk_live %} 36 | # Copy and build frontend 37 | COPY ./frontend ./frontend 38 | RUN cd frontend && npm ci && npm run build 39 | {%- endif %} 40 | 41 | RUN uv sync --frozen 42 | 43 | ARG COMMIT_SHA="" 44 | ENV COMMIT_SHA=${COMMIT_SHA} 45 | 46 | EXPOSE 8080 47 | 48 | CMD ["uv", "run", "uvicorn", "{{cookiecutter.agent_directory}}.server:app", "--host", "0.0.0.0", "--port", "8080"] -------------------------------------------------------------------------------- /tests/cli/commands/test_list.py: -------------------------------------------------------------------------------- 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 | from click.testing import CliRunner 16 | from pytest_mock import MockerFixture 17 | 18 | from agent_starter_pack.cli.commands.list import list_agents 19 | 20 | 21 | def test_list_agents_local(mocker: MockerFixture) -> None: 22 | """Test the list command with local agents.""" 23 | mock_get_agents = mocker.patch( 24 | "agent_starter_pack.cli.commands.list.get_available_agents", 25 | return_value={ 26 | "agent1": {"name": "Agent One", "description": "Description one"}, 27 | "agent2": {"name": "Agent Two", "description": "Description two"}, 28 | }, 29 | ) 30 | 31 | runner = CliRunner() 32 | result = runner.invoke(list_agents) 33 | 34 | assert result.exit_code == 0 35 | assert "Available built-in agents" in result.output 36 | assert "Agent One" in result.output 37 | assert "Description one" in result.output 38 | assert "Agent Two" in result.output 39 | assert "Description two" in result.output 40 | mock_get_agents.assert_called_once() 41 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_live/tests/unit/test_dummy.py: -------------------------------------------------------------------------------- 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 | You can add your unit tests here. 16 | This is where you test your business logic, including agent functionality, 17 | data processing, and other core components of your application. 18 | """ 19 | 20 | from app.agent import get_weather 21 | 22 | 23 | def test_get_weather_san_francisco() -> None: 24 | """Test get_weather function returns correct weather for San Francisco.""" 25 | result = get_weather("What's the weather in San Francisco?") 26 | assert result == "It's 60 degrees and foggy." 27 | 28 | 29 | def test_get_weather_san_francisco_abbreviation() -> None: 30 | """Test get_weather function returns correct weather for SF abbreviation.""" 31 | result = get_weather("weather in sf") 32 | assert result == "It's 60 degrees and foggy." 33 | 34 | 35 | def test_get_weather_other_location() -> None: 36 | """Test get_weather function returns default weather for other locations.""" 37 | result = get_weather("What's the weather in New York?") 38 | assert result == "It's 90 degrees and sunny." 39 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml: -------------------------------------------------------------------------------- 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 | code_task: 16 | description: > 17 | You are helping writing python code. These are the instructions: 18 | 19 | Instructions ------------ {code_instructions} 20 | 21 | 22 | expected_output: > 23 | Your Final answer must be the full python code, only the python code and nothing else. 24 | 25 | 26 | evaluate_task: 27 | description: > 28 | You are helping writing python code. These are the instructions: 29 | 30 | Instructions ------------ {code_instructions} 31 | 32 | You will look over the code to insure that it is complete and does the job that it is supposed to do. You will also check for logic error, syntax errors, missing imports, variable declarations, mismatched brackets and missing test cases. If you find any issue in the code, ask the Senior Software Engineer to fix it by providing them the code and the instructions. Don't fix it yourself. 33 | 34 | 35 | expected_output: > 36 | Your Final answer must be the full python code, only the python code and nothing else. 37 | 38 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/apis.tf: -------------------------------------------------------------------------------- 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 | resource "google_project_service" "cicd_services" { 16 | count = length(local.cicd_services) 17 | project = var.cicd_runner_project_id 18 | service = local.cicd_services[count.index] 19 | disable_on_destroy = false 20 | } 21 | 22 | resource "google_project_service" "deploy_project_services" { 23 | for_each = { 24 | for pair in setproduct(keys(local.deploy_project_ids), local.deploy_project_services) : 25 | "${pair[0]}_${replace(pair[1], ".", "_")}" => { 26 | project = local.deploy_project_ids[pair[0]] 27 | service = pair[1] 28 | } 29 | } 30 | project = each.value.project 31 | service = each.value.service 32 | disable_on_destroy = false 33 | } 34 | 35 | # Enable Cloud Resource Manager API for the CICD runner project 36 | resource "google_project_service" "cicd_cloud_resource_manager_api" { 37 | project = var.cicd_runner_project_id 38 | service = "cloudresourcemanager.googleapis.com" 39 | disable_on_destroy = false 40 | } 41 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/components/audio-pulse/audio-pulse.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2025 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* stylelint-disable */ 18 | .audioPulse { 19 | display: flex; 20 | width: 24px; 21 | justify-content: space-evenly; 22 | align-items: center; 23 | transition: all 0.5s; 24 | 25 | & > div { 26 | background-color: var(--Neutral-30); 27 | border-radius: 1000px; 28 | width: 4px; 29 | min-height: 4px; 30 | border-radius: 1000px; 31 | transition: height 0.1s; 32 | } 33 | 34 | &.hover > div { 35 | animation: hover 1.4s infinite alternate ease-in-out; 36 | } 37 | 38 | height: 4px; 39 | transition: opacity 0.333s; 40 | 41 | &.active { 42 | opacity: 1; 43 | 44 | & > div { 45 | background-color: var(--Neutral-80); 46 | } 47 | } 48 | } 49 | 50 | @keyframes hover { 51 | from { 52 | transform: translateY(0); 53 | } 54 | 55 | to { 56 | transform: translateY(-3.5px); 57 | } 58 | } 59 | 60 | @keyframes pulse { 61 | from { 62 | scale: 1 1; 63 | } 64 | 65 | to { 66 | scale: 1.2 1.2; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/gcs.py: -------------------------------------------------------------------------------- 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 | import logging 16 | 17 | import google.cloud.storage as storage 18 | from google.api_core import exceptions 19 | 20 | 21 | def create_bucket_if_not_exists(bucket_name: str, project: str, location: str) -> None: 22 | """Creates a new bucket if it doesn't already exist. 23 | 24 | Args: 25 | bucket_name: Name of the bucket to create 26 | project: Google Cloud project ID 27 | location: Location to create the bucket in (defaults to us-central1) 28 | """ 29 | storage_client = storage.Client(project=project) 30 | 31 | if bucket_name.startswith("gs://"): 32 | bucket_name = bucket_name[5:] 33 | try: 34 | storage_client.get_bucket(bucket_name) 35 | logging.info(f"Bucket {bucket_name} already exists") 36 | except exceptions.NotFound: 37 | bucket = storage_client.create_bucket( 38 | bucket_name, 39 | location=location, 40 | project=project, 41 | ) 42 | logging.info(f"Created bucket {bucket.name} in {bucket.location}") 43 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/README.md: -------------------------------------------------------------------------------- 1 | # CrewAI Coding Crew Agent 2 | 3 | This agent combines CrewAI's collaborative AI capabilities with LangGraph to provide an interactive coding assistant that can understand requirements and generate code solutions through conversation. 4 | 5 | ## Architecture 6 | 7 | The agent implements a conversational interface using LangGraph that coordinates with a CrewAI development team. The workflow consists of: 8 | 9 | 1. A conversational agent that: 10 | - Gathers requirements through natural dialogue 11 | - Clarifies ambiguities by asking follow-up questions 12 | - Delegates actual coding work to the CrewAI development team 13 | 14 | 2. A CrewAI development team consisting of: 15 | - Senior Engineer: Responsible for implementing the code solution 16 | - Chief QA Engineer: Evaluates and validates the implemented code 17 | 18 | ## Key Features 19 | 20 | - **Interactive Requirements Gathering**: Uses LangGraph to maintain a natural conversation flow while collecting and clarifying coding requirements 21 | - **Collaborative AI Development**: Leverages CrewAI's multi-agent system to divide work between specialized AI agents 22 | - **Sequential Processing**: Tasks are processed in order, from requirements gathering to implementation to quality assurance 23 | 24 | ## How It Works 25 | 26 | 1. The LangGraph workflow manages the conversation state and determines when to: 27 | - Continue the conversation to gather more requirements 28 | - Delegate work to the CrewAI development team 29 | - Return results to the user 30 | 31 | 2. When coding is needed, the CrewAI team is activated through a custom tool that: 32 | - Passes requirements to the Senior Engineer agent 33 | - Routes the implementation to the QA Engineer for validation 34 | - Returns the final, validated solution 35 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/dev/apis.tf: -------------------------------------------------------------------------------- 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 | locals { 16 | services = [ 17 | "aiplatform.googleapis.com", 18 | "cloudbuild.googleapis.com", 19 | "run.googleapis.com", 20 | "bigquery.googleapis.com", 21 | "discoveryengine.googleapis.com", 22 | "cloudresourcemanager.googleapis.com", 23 | "iam.googleapis.com", 24 | "bigquery.googleapis.com", 25 | "serviceusage.googleapis.com", 26 | "logging.googleapis.com", 27 | "cloudtrace.googleapis.com", 28 | {%- if cookiecutter.is_adk and cookiecutter.session_type == "alloydb" %} 29 | "compute.googleapis.com", 30 | "servicenetworking.googleapis.com", 31 | "alloydb.googleapis.com", 32 | "secretmanager.googleapis.com", 33 | "dns.googleapis.com" 34 | {%- endif %} 35 | ] 36 | } 37 | 38 | resource "google_project_service" "services" { 39 | count = length(local.services) 40 | project = var.dev_project_id 41 | service = local.services[count.index] 42 | disable_on_destroy = false 43 | } 44 | 45 | resource "google_project_service_identity" "vertex_sa" { 46 | provider = google-beta 47 | project = var.dev_project_id 48 | service = "aiplatform.googleapis.com" 49 | } 50 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_live/app/agent.py: -------------------------------------------------------------------------------- 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 | import os 16 | 17 | import google.auth 18 | import vertexai 19 | from google.adk.agents import Agent 20 | 21 | _, project_id = google.auth.default() 22 | os.environ.setdefault("GOOGLE_CLOUD_PROJECT", project_id) 23 | os.environ.setdefault("GOOGLE_CLOUD_LOCATION", "us-central1") 24 | os.environ.setdefault("GOOGLE_GENAI_USE_VERTEXAI", "True") 25 | 26 | vertexai.init(project=project_id, location="us-central1") 27 | 28 | 29 | def get_weather(query: str) -> str: 30 | """Simulates a web search. Use it get information on weather. 31 | 32 | Args: 33 | query: A string containing the location to get weather information for. 34 | 35 | Returns: 36 | A string with the simulated weather information for the queried location. 37 | """ 38 | if "sf" in query.lower() or "san francisco" in query.lower(): 39 | return "It's 60 degrees and foggy." 40 | return "It's 90 degrees and sunny." 41 | 42 | 43 | root_agent = Agent( 44 | name="root_agent", 45 | model="gemini-live-2.5-flash-preview-native-audio-09-2025", 46 | instruction="You are a helpful AI assistant designed to provide accurate and useful information.", 47 | tools=[get_weather], 48 | ) 49 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/pr_checks.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Install uv package manager and sync dependencies 17 | - name: "python:3.11-slim" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | pip install uv==0.8.13 --user && uv sync --locked 24 | env: 25 | - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin' 26 | 27 | # Run unit tests using pytest 28 | - name: "python:3.11-slim" 29 | id: unit-tests 30 | entrypoint: /bin/bash 31 | args: 32 | - "-c" 33 | - | 34 | uv run pytest tests/unit 35 | env: 36 | - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin' 37 | 38 | # Run integration tests 39 | - name: "python:3.11-slim" 40 | id: integration-tests 41 | entrypoint: /bin/bash 42 | args: 43 | - "-c" 44 | - | 45 | uv run pytest tests/integration 46 | env: 47 | - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin' 48 | 49 | logsBucket: gs://${PROJECT_ID}-{{ cookiecutter.project_name | replace('_', '-') }}-logs/build-logs 50 | options: 51 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 52 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py: -------------------------------------------------------------------------------- 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 | # mypy: ignore-errors 16 | from {{cookiecutter.agent_directory}}.agent import agent 17 | 18 | 19 | def test_agent_stream() -> None: 20 | """ 21 | Integration test for the agent stream functionality. 22 | Tests that the agent returns valid streaming responses. 23 | """ 24 | input_dict = { 25 | "messages": [ 26 | {"type": "human", "content": "Hi"}, 27 | {"type": "ai", "content": "Hi there!"}, 28 | {"type": "human", "content": "Write a fibonacci function in python"}, 29 | ] 30 | } 31 | 32 | events = [ 33 | message for message, _ in agent.stream(input_dict, stream_mode="messages") 34 | ] 35 | # Verify we get a reasonable number of messages 36 | assert len(events) > 0, "Expected at least one message" 37 | 38 | # First message should be an AI message 39 | assert events[0].type == "AIMessageChunk" 40 | 41 | # At least one message should have content 42 | has_content = False 43 | for event in events: 44 | if hasattr(event, "content") and event.content: 45 | has_content = True 46 | break 47 | assert has_content, "Expected at least one message with content" 48 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/langgraph_base_react/tests/integration/test_agent.py: -------------------------------------------------------------------------------- 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 | # mypy: ignore-errors 16 | from {{cookiecutter.agent_directory}}.agent import agent 17 | 18 | 19 | def test_agent_stream() -> None: 20 | """ 21 | Integration test for the agent stream functionality. 22 | Tests that the agent returns valid streaming responses. 23 | """ 24 | input_dict = { 25 | "messages": [ 26 | {"type": "human", "content": "Hi"}, 27 | {"type": "ai", "content": "Hi there!"}, 28 | {"type": "human", "content": "What's the weather in NY?"}, 29 | ] 30 | } 31 | 32 | events = [ 33 | message for message, _ in agent.stream(input_dict, stream_mode="messages") 34 | ] 35 | 36 | # Verify we get a reasonable number of messages 37 | assert len(events) > 0, "Expected at least one message" 38 | 39 | # First message should be an AI message 40 | assert events[0].type == "AIMessageChunk" 41 | 42 | # At least one message should have content 43 | has_content = False 44 | for event in events: 45 | if hasattr(event, "content") and event.content: 46 | has_content = True 47 | break 48 | assert has_content, "Expected at least one message with content" 49 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/service_accounts.tf: -------------------------------------------------------------------------------- 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 | resource "google_service_account" "cicd_runner_sa" { 16 | account_id = "${var.project_name}-cb" 17 | display_name = "CICD Runner SA" 18 | project = var.cicd_runner_project_id 19 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 20 | } 21 | # Agent service account 22 | resource "google_service_account" "app_sa" { 23 | for_each = local.deploy_project_ids 24 | 25 | account_id = "${var.project_name}-app" 26 | display_name = "${var.project_name} Agent Service Account" 27 | project = each.value 28 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 29 | } 30 | 31 | {% if cookiecutter.data_ingestion %} 32 | # Service account to run Vertex AI pipeline 33 | resource "google_service_account" "vertexai_pipeline_app_sa" { 34 | for_each = local.deploy_project_ids 35 | 36 | account_id = "${var.project_name}-rag" 37 | display_name = "Vertex AI Pipeline app SA" 38 | project = each.value 39 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 40 | } 41 | {% endif %} 42 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/locals.tf: -------------------------------------------------------------------------------- 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 | locals { 16 | cicd_services = [ 17 | "cloudbuild.googleapis.com", 18 | "discoveryengine.googleapis.com", 19 | "aiplatform.googleapis.com", 20 | "serviceusage.googleapis.com", 21 | "bigquery.googleapis.com", 22 | "cloudresourcemanager.googleapis.com", 23 | "cloudtrace.googleapis.com" 24 | ] 25 | 26 | deploy_project_services = [ 27 | "aiplatform.googleapis.com", 28 | "run.googleapis.com", 29 | "discoveryengine.googleapis.com", 30 | "cloudresourcemanager.googleapis.com", 31 | "iam.googleapis.com", 32 | "bigquery.googleapis.com", 33 | "serviceusage.googleapis.com", 34 | "logging.googleapis.com", 35 | "cloudtrace.googleapis.com", 36 | {%- if cookiecutter.is_adk and cookiecutter.session_type == "alloydb" %} 37 | "compute.googleapis.com", 38 | "servicenetworking.googleapis.com", 39 | "alloydb.googleapis.com", 40 | "secretmanager.googleapis.com", 41 | "dns.googleapis.com" 42 | {%- endif %} 43 | ] 44 | 45 | deploy_project_ids = { 46 | prod = var.prod_project_id 47 | staging = var.staging_project_id 48 | } 49 | 50 | all_project_ids = [ 51 | var.cicd_runner_project_id, 52 | var.prod_project_id, 53 | var.staging_project_id 54 | ] 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /.cloudbuild/cd/test_e2e.yaml: -------------------------------------------------------------------------------- 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 | steps: 16 | # Sync dependencies 17 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 18 | id: install-dependencies 19 | entrypoint: /bin/bash 20 | args: 21 | - "-c" 22 | - | 23 | uv sync --dev --locked 24 | 25 | # Run unit tests using pytest 26 | - name: "europe-west4-docker.pkg.dev/production-ai-template/starter-pack/e2e-tests" 27 | id: e2e-tests 28 | entrypoint: /bin/bash 29 | args: 30 | - "-c" 31 | - | 32 | GH_TOKEN=$$GITHUB_PAT uv run pytest tests/cicd/test_e2e_deployment.py -v 33 | secretEnv: ['GITHUB_PAT', 'GITHUB_APP_INSTALLATION_ID'] 34 | 35 | availableSecrets: 36 | secretManager: 37 | - versionName: projects/$PROJECT_ID/secrets/github-pat/versions/latest 38 | env: 'GITHUB_PAT' 39 | - versionName: projects/$PROJECT_ID/secrets/github-app-installation-id/versions/latest 40 | env: 'GITHUB_APP_INSTALLATION_ID' 41 | logsBucket: gs://${PROJECT_ID}-logs-data/build-logs 42 | options: 43 | defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET 44 | env: 45 | - "_TEST_AGENT_COMBINATION=${_TEST_AGENT_COMBINATION}" 46 | - "E2E_DEV_PROJECT=${_E2E_DEV_PROJECT}" 47 | - "E2E_STAGING_PROJECT=${_E2E_STAGING_PROJECT}" 48 | - "E2E_PROD_PROJECT=${_E2E_PROD_PROJECT}" 49 | - "E2E_CICD_PROJECT=${PROJECT_ID}" 50 | - "RUN_E2E_TESTS=1" 51 | timeout: 43200s 52 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/components/audio-pulse/AudioPulse.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import "./audio-pulse.scss"; 18 | import React from "react"; 19 | import { useEffect, useRef } from "react"; 20 | import c from "classnames"; 21 | 22 | const lineCount = 3; 23 | 24 | export type AudioPulseProps = { 25 | active: boolean; 26 | volume: number; 27 | hover?: boolean; 28 | }; 29 | 30 | export default function AudioPulse({ active, volume, hover }: AudioPulseProps) { 31 | const lines = useRef([]); 32 | 33 | useEffect(() => { 34 | let timeout: number | null = null; 35 | const update = () => { 36 | lines.current.forEach( 37 | (line, i) => 38 | (line.style.height = `${Math.min( 39 | 24, 40 | 4 + volume * (i === 1 ? 400 : 60), 41 | )}px`), 42 | ); 43 | timeout = window.setTimeout(update, 100); 44 | }; 45 | 46 | update(); 47 | 48 | return () => clearTimeout((timeout as number)!); 49 | }, [volume]); 50 | 51 | return ( 52 |
53 | {Array(lineCount) 54 | .fill(null) 55 | .map((_, i) => ( 56 |
(lines.current[i] = el!)} 59 | style={{ animationDelay: `${i * 133}ms` }} 60 | /> 61 | ))} 62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /agent_starter_pack/resources/containers/e2e-tests/Dockerfile: -------------------------------------------------------------------------------- 1 | # Stage 1: Builder - Prepare APT repositories 2 | FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim AS builder 3 | 4 | # Install tools needed to add repositories 5 | RUN apt-get update && \ 6 | apt-get install -y --no-install-recommends \ 7 | ca-certificates \ 8 | curl \ 9 | gnupg && \ 10 | # GitHub CLI 11 | curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ 12 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list && \ 13 | # Google Cloud SDK 14 | curl -sS https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg && \ 15 | echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list && \ 16 | # Terraform 17 | curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg && \ 18 | echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com bookworm main" > /etc/apt/sources.list.d/hashicorp.list && \ 19 | # Clean up builder stage 20 | apt-get clean && \ 21 | rm -rf /var/lib/apt/lists/* 22 | 23 | # Stage 2: Final Image 24 | FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim 25 | 26 | # Copy repository configurations from the builder stage 27 | COPY --from=builder /etc/apt/sources.list.d/ /etc/apt/sources.list.d/ 28 | COPY --from=builder /usr/share/keyrings/ /usr/share/keyrings/ 29 | 30 | # Install the final packages 31 | RUN apt-get update && \ 32 | apt-get install -y --no-install-recommends \ 33 | gh \ 34 | google-cloud-cli \ 35 | terraform \ 36 | make \ 37 | nodejs \ 38 | npm && \ 39 | # Clean up apt cache 40 | apt-get clean && \ 41 | rm -rf /var/lib/apt/lists/* -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/utils/store-logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { create } from "zustand"; 18 | import { StreamingLog } from "../multimodal-live-types"; 19 | 20 | interface StoreLoggerState { 21 | maxLogs: number; 22 | logs: StreamingLog[]; 23 | log: (streamingLog: StreamingLog) => void; 24 | clearLogs: () => void; 25 | } 26 | 27 | export const useLoggerStore = create((set, get) => ({ 28 | maxLogs: 500, 29 | logs: [], //mockLogs, 30 | log: ({ date, type, message }: StreamingLog) => { 31 | set((state) => { 32 | const prevLog = state.logs.at(-1); 33 | if (prevLog && prevLog.type === type && prevLog.message === message) { 34 | return { 35 | logs: [ 36 | ...state.logs.slice(0, -1), 37 | { 38 | date, 39 | type, 40 | message, 41 | count: prevLog.count ? prevLog.count + 1 : 1, 42 | } as StreamingLog, 43 | ], 44 | }; 45 | } 46 | return { 47 | logs: [ 48 | ...state.logs.slice(-(get().maxLogs - 1)), 49 | { 50 | date, 51 | type, 52 | message, 53 | } as StreamingLog, 54 | ], 55 | }; 56 | }); 57 | }, 58 | 59 | clearLogs: () => { 60 | console.log("clear log"); 61 | set({ logs: [] }); 62 | }, 63 | setMaxLogs: (n: number) => set({ maxLogs: n }), 64 | })); 65 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/utils/worklets/vol-meter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const VolMeterWorket = ` 18 | class VolMeter extends AudioWorkletProcessor { 19 | volume 20 | updateIntervalInMS 21 | nextUpdateFrame 22 | 23 | constructor() { 24 | super() 25 | this.volume = 0 26 | this.updateIntervalInMS = 25 27 | this.nextUpdateFrame = this.updateIntervalInMS 28 | this.port.onmessage = event => { 29 | if (event.data.updateIntervalInMS) { 30 | this.updateIntervalInMS = event.data.updateIntervalInMS 31 | } 32 | } 33 | } 34 | 35 | get intervalInFrames() { 36 | return (this.updateIntervalInMS / 1000) * sampleRate 37 | } 38 | 39 | process(inputs) { 40 | const input = inputs[0] 41 | 42 | if (input.length > 0) { 43 | const samples = input[0] 44 | let sum = 0 45 | let rms = 0 46 | 47 | for (let i = 0; i < samples.length; ++i) { 48 | sum += samples[i] * samples[i] 49 | } 50 | 51 | rms = Math.sqrt(sum / samples.length) 52 | this.volume = Math.max(rms, this.volume * 0.7) 53 | 54 | this.nextUpdateFrame -= samples.length 55 | if (this.nextUpdateFrame < 0) { 56 | this.nextUpdateFrame += this.intervalInFrames 57 | this.port.postMessage({volume: this.volume}) 58 | } 59 | } 60 | 61 | return true 62 | } 63 | }`; 64 | 65 | export default VolMeterWorket; 66 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/app/agent.py: -------------------------------------------------------------------------------- 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 | # mypy: disable-error-code="union-attr" 16 | from langchain_google_vertexai import ChatVertexAI 17 | from langgraph.prebuilt import create_react_agent 18 | 19 | from .crew.crew import DevCrew 20 | 21 | LOCATION = "global" 22 | LLM = "gemini-2.5-flash" 23 | 24 | llm = ChatVertexAI(model=LLM, location=LOCATION, temperature=0) 25 | 26 | 27 | def coding_tool(code_instructions: str) -> str: 28 | """Use this tool to write a python program given a set of requirements and or instructions.""" 29 | inputs = {"code_instructions": code_instructions} 30 | return DevCrew().crew().kickoff(inputs=inputs) 31 | 32 | 33 | system_message = ( 34 | "You are an expert Lead Software Engineer Manager.\n" 35 | "Your role is to speak to a user and understand what kind of code they need to " 36 | "build.\n" 37 | "Part of your task is therefore to gather requirements and clarifying ambiguity " 38 | "by asking followup questions. Don't ask all the questions together as the user " 39 | "has a low attention span, rather ask a question at the time.\n" 40 | "Once the problem to solve is clear, you will call your tool for writing the " 41 | "solution.\n" 42 | "Remember, you are an expert in understanding requirements but you cannot code, " 43 | "use your coding tool to generate a solution. Keep the test cases if any, they " 44 | "are useful for the user." 45 | ) 46 | 47 | agent = create_react_agent(model=llm, tools=[coding_tool], prompt=system_message) 48 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, 4 | and in the interest of fostering an open and welcoming community, 5 | we pledge to respect all people who contribute through reporting issues, 6 | posting feature requests, updating documentation, 7 | submitting pull requests or patches, and other activities. 8 | 9 | We are committed to making participation in this project 10 | a harassment-free experience for everyone, 11 | regardless of level of experience, gender, gender identity and expression, 12 | sexual orientation, disability, personal appearance, 13 | body size, race, ethnicity, age, religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | - The use of sexualized language or imagery 18 | - Personal attacks 19 | - Trolling or insulting/derogatory comments 20 | - Public or private harassment 21 | - Publishing other's private information, 22 | such as physical or electronic 23 | addresses, without explicit permission 24 | - Other unethical or unprofessional conduct. 25 | 26 | Project maintainers have the right and responsibility to remove, edit, or reject 27 | comments, commits, code, wiki edits, issues, and other contributions 28 | that are not aligned to this Code of Conduct. 29 | By adopting this Code of Conduct, 30 | project maintainers commit themselves to fairly and consistently 31 | applying these principles to every aspect of managing this project. 32 | Project maintainers who do not follow or enforce the Code of Conduct 33 | may be permanently removed from the project team. 34 | 35 | This code of conduct applies both within project spaces and in public spaces 36 | when an individual is representing the project or its community. 37 | 38 | Instances of abusive, harassing, or otherwise unacceptable behavior 39 | may be reported by opening an issue 40 | or contacting one or more of the project maintainers. 41 | 42 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, 43 | available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) 44 | -------------------------------------------------------------------------------- /docs/guide/community-showcase.md: -------------------------------------------------------------------------------- 1 | # 🌟 Community Showcase 2 | 3 | Welcome to the Agent Starter Pack Community Showcase! This page highlights amazing projects, implementations, and creative uses of the Agent Starter Pack by our community. 4 | 5 | ## 🔍 Explore Community Projects 6 | 7 | **[Browse all community agents on GitHub →](https://github.com/search?q=Agent+generated+with+%5B%60googleCloudPlatform%2Fagent-starter-pack%60%5D&type=code)** 8 | 9 | Discover how developers are using our templates in real-world applications. 10 | 11 | ## Featured Projects 12 | 13 | ### Smart Learning Platform by [tensr](https://tensr.be/) 14 | **Repository:** [jossehuybrechts/smart-learning](https://github.com/jossehuybrechts/smart-learning) 15 | **Blog Post:** [Building a Smart Learning Platform with Google's Agent Starter Pack](https://medium.com/@tensr/9f75876bc618) 16 | 17 | An intelligent learning platform that adapts to individual learning styles and provides personalized educational content. This project demonstrates how to build a production-ready educational AI agent using the Agent Starter Pack's templates and deployment infrastructure. 18 | 19 | ### Production Monitoring Assistant by [norma](https://norma.dev/) 20 | **Repository:** [adilmoumni/prod-monitoring-assistant](https://github.com/adilmoumni/prod-monitoring-assistant) 21 | **Blog Post:** [Building an AI Agent for Production Monitoring at the Agentic Era Hackathon](https://medium.com/norma-dev/building-an-ai-agent-for-production-monitoring-at-the-agentic-era-hackathon-ffa283dd391d) 22 | 23 | An AI-powered production monitoring assistant built for the Agentic Era Hackathon. This agent helps DevOps teams monitor system health, detect anomalies, and provide intelligent insights for maintaining production environments. 24 | 25 | --- 26 | 27 | *This section will be updated regularly as we review and feature outstanding community submissions.* 28 | 29 | ## 📝 Submit Your Project 30 | 31 | Built something amazing with the Agent Starter Pack? **[Create a showcase issue](https://github.com/GoogleCloudPlatform/agent-starter-pack/issues/new?labels=showcase)** with your repository URL, project description, and unique features. 32 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/hooks/use-webcam.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { useState, useEffect } from "react"; 18 | import { UseMediaStreamResult } from "./use-media-stream-mux"; 19 | 20 | export function useWebcam(): UseMediaStreamResult { 21 | const [stream, setStream] = useState(null); 22 | const [isStreaming, setIsStreaming] = useState(false); 23 | 24 | useEffect(() => { 25 | const handleStreamEnded = () => { 26 | setIsStreaming(false); 27 | setStream(null); 28 | }; 29 | if (stream) { 30 | stream 31 | .getTracks() 32 | .forEach((track) => track.addEventListener("ended", handleStreamEnded)); 33 | return () => { 34 | stream 35 | .getTracks() 36 | .forEach((track) => 37 | track.removeEventListener("ended", handleStreamEnded), 38 | ); 39 | }; 40 | } 41 | }, [stream]); 42 | 43 | const start = async () => { 44 | const mediaStream = await navigator.mediaDevices.getUserMedia({ 45 | video: true, 46 | }); 47 | setStream(mediaStream); 48 | setIsStreaming(true); 49 | return mediaStream; 50 | }; 51 | 52 | const stop = () => { 53 | if (stream) { 54 | stream.getTracks().forEach((track) => track.stop()); 55 | setStream(null); 56 | setIsStreaming(false); 57 | } 58 | }; 59 | 60 | const result: UseMediaStreamResult = { 61 | type: "webcam", 62 | start, 63 | stop, 64 | isStreaming, 65 | stream, 66 | }; 67 | 68 | return result; 69 | } 70 | -------------------------------------------------------------------------------- /.cloudbuild/terraform/service_account.tf: -------------------------------------------------------------------------------- 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 | # Define local variables for roles 15 | 16 | 17 | locals { 18 | cicd_runner_roles = [ 19 | "roles/owner", 20 | ] 21 | 22 | e2e_project_roles = [ 23 | "roles/owner", 24 | ] 25 | } 26 | 27 | # Create a service account for CICD runner 28 | resource "google_service_account" "cicd_runner_sa" { 29 | project = var.cicd_runner_project_id 30 | account_id = "cicd-tests-runner-sa" 31 | display_name = "Service Account for CI/CD Pipeline Runner" 32 | description = "Used by Cloud Build to execute CI/CD pipelines" 33 | } 34 | 35 | # Grant necessary roles to the service account 36 | resource "google_project_iam_member" "cicd_runner_roles" { 37 | for_each = toset(local.cicd_runner_roles) 38 | 39 | project = var.cicd_runner_project_id 40 | role = each.key 41 | member = "serviceAccount:${google_service_account.cicd_runner_sa.email}" 42 | } 43 | 44 | # Grant permissions to the service account for each environment project 45 | resource "google_project_iam_member" "cicd_runner_e2e_project_roles" { 46 | for_each = { 47 | for idx, proj_role in flatten([ 48 | for env, project_id in var.e2e_test_project_mapping : [ 49 | for role in local.e2e_project_roles : { 50 | project = project_id 51 | env = env 52 | role = role 53 | } 54 | ] 55 | ]) : "${proj_role.env}-${proj_role.role}" => proj_role 56 | } 57 | 58 | project = each.value.project 59 | role = each.value.role 60 | member = "serviceAccount:${google_service_account.cicd_runner_sa.email}" 61 | } 62 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_live/README.md: -------------------------------------------------------------------------------- 1 | # ADK Live Agent 2 | 3 | Real-time conversational agent built with Google ADK and Gemini's live audio model. Supports audio, video, and text interactions with native tool calling. 4 | 5 | ![adk_live_diagram](https://storage.googleapis.com/github-repo/generative-ai/sample-apps/e2e-gen-ai-app-starter-pack/adk_live_diagram.png) 6 | 7 | **Key components:** 8 | 9 | - **Python Backend** (in `app/` folder): ADK-powered agent using Gemini's live audio model with native tool calling and deployment support for Cloud Run and Agent Engine 10 | 11 | - **React Frontend** (in `frontend/` folder): Web console for interacting with the live agent via audio, video, and text 12 | 13 | ![live api demo](https://storage.googleapis.com/github-repo/generative-ai/sample-apps/e2e-gen-ai-app-starter-pack/adk_live_pattern_demo.gif) 14 | 15 | Once running, click the play button to connect and interact with the agent. Try asking "What's the weather like in San Francisco?" to see tool calling in action. 16 | 17 | ## Additional Resources for Multimodal Live API 18 | 19 | Explore these resources to learn more about the Multimodal Live API and see examples of its usage: 20 | 21 | - [Project Pastra](https://github.com/heiko-hotz/gemini-multimodal-live-dev-guide/tree/main): a comprehensive developer guide for the Gemini Multimodal Live API. 22 | - [Google Cloud Multimodal Live API demos and samples](https://github.com/GoogleCloudPlatform/generative-ai/tree/main/gemini/multimodal-live-api): Collection of code samples and demo applications leveraging multimodal live API in Vertex AI 23 | - [Gemini 2 Cookbook](https://github.com/google-gemini/cookbook/tree/main/gemini-2): Practical examples and tutorials for working with Gemini 2 24 | - [Multimodal Live API Web Console](https://github.com/google-gemini/multimodal-live-api-web-console): Interactive React-based web interface for testing and experimenting with Gemini Multimodal Live API. 25 | 26 | ## Current Status & Future Work 27 | 28 | This pattern is under active development. Key areas planned for future enhancement include: 29 | 30 | * **Observability:** Implementing comprehensive monitoring and tracing features. 31 | * **Load Testing:** Integrating load testing capabilities. 32 | -------------------------------------------------------------------------------- /agent_starter_pack/cli/main.py: -------------------------------------------------------------------------------- 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 | import importlib.metadata 16 | import sys 17 | 18 | import click 19 | from rich.console import Console 20 | 21 | from .commands.create import create 22 | from .commands.enhance import enhance 23 | from .commands.list import list_agents 24 | from .commands.setup_cicd import setup_cicd 25 | from .utils import display_update_message 26 | 27 | console = Console() 28 | 29 | 30 | def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None: 31 | if not value or ctx.resilient_parsing: 32 | return 33 | try: 34 | version_str = importlib.metadata.version("agent-starter-pack") 35 | console.print(f"GCP Agent Starter Pack CLI version: {version_str}") 36 | except importlib.metadata.PackageNotFoundError: 37 | console.print("GCP Agent Starter Pack CLI (development version)") 38 | ctx.exit() 39 | 40 | 41 | @click.group(help="Production-ready Generative AI Agent templates for Google Cloud") 42 | @click.option( 43 | "--version", 44 | "-v", 45 | is_flag=True, 46 | callback=print_version, 47 | expose_value=False, 48 | is_eager=True, 49 | help="Show the version and exit.", 50 | ) 51 | def cli() -> None: 52 | # Check for updates at startup (skip if --agent-garden or -ag is used) 53 | if "--agent-garden" not in sys.argv and "-ag" not in sys.argv: 54 | display_update_message() 55 | 56 | 57 | # Register commands 58 | cli.add_command(create) 59 | cli.add_command(enhance) 60 | cli.add_command(setup_cicd) 61 | cli.add_command(list_agents, name="list") 62 | 63 | 64 | if __name__ == "__main__": 65 | cli() 66 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_base/tests/integration/test_agent.py: -------------------------------------------------------------------------------- 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 | # mypy: disable-error-code="union-attr" 16 | from google.adk.agents.run_config import RunConfig, StreamingMode 17 | from google.adk.runners import Runner 18 | from google.adk.sessions import InMemorySessionService 19 | from google.genai import types 20 | 21 | from {{cookiecutter.agent_directory}}.agent import root_agent 22 | 23 | 24 | def test_agent_stream() -> None: 25 | """ 26 | Integration test for the agent stream functionality. 27 | Tests that the agent returns valid streaming responses. 28 | """ 29 | 30 | session_service = InMemorySessionService() 31 | 32 | session = session_service.create_session_sync(user_id="test_user", app_name="test") 33 | runner = Runner(agent=root_agent, session_service=session_service, app_name="test") 34 | 35 | message = types.Content( 36 | role="user", parts=[types.Part.from_text(text="Why is the sky blue?")] 37 | ) 38 | 39 | events = list( 40 | runner.run( 41 | new_message=message, 42 | user_id="test_user", 43 | session_id=session.id, 44 | run_config=RunConfig(streaming_mode=StreamingMode.SSE), 45 | ) 46 | ) 47 | assert len(events) > 0, "Expected at least one message" 48 | 49 | has_text_content = False 50 | for event in events: 51 | if ( 52 | event.content 53 | and event.content.parts 54 | and any(part.text for part in event.content.parts) 55 | ): 56 | has_text_content = True 57 | break 58 | assert has_text_content, "Expected at least one message with text content" 59 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | title: Home 4 | 5 | hero: 6 | name: Agent Starter Pack 7 | text: Production-Ready Agents on Google Cloud, faster 8 | tagline: Go from idea to deployment faster with pre-built templates & tools. 9 | image: 10 | src: https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/logo.png?raw=true 11 | alt: Agent Starter Pack Logo 12 | actions: 13 | - theme: brand 14 | text: Get Started Guide 15 | link: /guide/getting-started 16 | - theme: alt 17 | text: Development Guide 18 | link: /guide/development-guide 19 | - theme: alt 20 | text: Watch Demo Video 21 | link: https://www.youtube.com/watch?v=9zqwym-N3lg 22 | 23 | features: 24 | - icon: ⚡️ 25 | title: Launch Quickly 26 | details: Start fast with pre-built agent templates (ReAct, RAG, multi-agent, Live Multimodal API) implementing common patterns. 27 | - icon: 🧪 28 | title: Experiment & Evaluate 29 | details: Iterate using integrated Vertex AI evaluation and an interactive testing playground. 30 | - icon: ☁️ 31 | title: Deploy Confidently 32 | details: Ship reliable agents with production-ready infra (Cloud Run / Agent Engine) featuring monitoring, observability, and CI/CD. 33 | - icon: 🛠️ 34 | title: Customize & Extend 35 | details: Adapt and enhance templates for your specific use case, or create your own. 36 | --- 37 | 38 | ::: tip ⭐ Like Agent Starter Pack? 39 | Help us spread the word by giving us a star on GitHub! 40 | 41 | 42 | ![GitHub Stars](https://img.shields.io/github/stars/GoogleCloudPlatform/agent-starter-pack?style=social&color=yellow) 43 | 44 | 45 | ::: 46 | 47 | ## Quick Links 48 | 49 | - **New Users:** [Getting Started Guide](/guide/getting-started) 50 | - **Setup:** [Installation Guide](/guide/installation) 51 | - **Going Live:** [Deployment Guide](/guide/deployment) 52 | - **Explore Templates:** [Agent Templates Overview](/agents/overview) 53 | - **Community:** [Community Showcase](/guide/community-showcase) 54 | - **Command Line:** [CLI Reference](/cli/) -------------------------------------------------------------------------------- /agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py: -------------------------------------------------------------------------------- 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 | # mypy: disable-error-code="attr-defined" 16 | from typing import Any 17 | 18 | from crewai import Agent, Crew, Process, Task 19 | from crewai.project import CrewBase, agent, crew, task 20 | 21 | 22 | @CrewBase 23 | class DevCrew: 24 | """Developer crew""" 25 | 26 | agents_config: dict[str, Any] 27 | tasks_config: dict[str, Any] 28 | 29 | llm = "vertex_ai/gemini-2.0-flash-001" 30 | 31 | @agent 32 | def senior_engineer_agent(self) -> Agent: 33 | return Agent( 34 | config=self.agents_config.get("senior_engineer_agent"), 35 | allow_delegation=False, 36 | verbose=True, 37 | llm=self.llm, 38 | ) 39 | 40 | @agent 41 | def chief_qa_engineer_agent(self) -> Agent: 42 | return Agent( 43 | config=self.agents_config.get("chief_qa_engineer_agent"), 44 | allow_delegation=True, 45 | verbose=True, 46 | llm=self.llm, 47 | ) 48 | 49 | @task 50 | def code_task(self) -> Task: 51 | return Task( 52 | config=self.tasks_config.get("code_task"), 53 | agent=self.senior_engineer_agent(), 54 | ) 55 | 56 | @task 57 | def evaluate_task(self) -> Task: 58 | return Task( 59 | config=self.tasks_config.get("evaluate_task"), 60 | agent=self.chief_qa_engineer_agent(), 61 | ) 62 | 63 | @crew 64 | def crew(self) -> Crew: 65 | """Creates the Dev Crew""" 66 | return Crew( 67 | agents=self.agents, 68 | tasks=self.tasks, 69 | process=Process.sequential, 70 | verbose=True, 71 | ) 72 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/hooks/use-screen-capture.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { useState, useEffect } from "react"; 18 | import { UseMediaStreamResult } from "./use-media-stream-mux"; 19 | 20 | export function useScreenCapture(): UseMediaStreamResult { 21 | const [stream, setStream] = useState(null); 22 | const [isStreaming, setIsStreaming] = useState(false); 23 | 24 | useEffect(() => { 25 | const handleStreamEnded = () => { 26 | setIsStreaming(false); 27 | setStream(null); 28 | }; 29 | if (stream) { 30 | stream 31 | .getTracks() 32 | .forEach((track) => track.addEventListener("ended", handleStreamEnded)); 33 | return () => { 34 | stream 35 | .getTracks() 36 | .forEach((track) => 37 | track.removeEventListener("ended", handleStreamEnded), 38 | ); 39 | }; 40 | } 41 | }, [stream]); 42 | 43 | const start = async () => { 44 | // const controller = new CaptureController(); 45 | // controller.setFocusBehavior("no-focus-change"); 46 | const mediaStream = await navigator.mediaDevices.getDisplayMedia({ 47 | video: true, 48 | // controller 49 | }); 50 | setStream(mediaStream); 51 | setIsStreaming(true); 52 | return mediaStream; 53 | }; 54 | 55 | const stop = () => { 56 | if (stream) { 57 | stream.getTracks().forEach((track) => track.stop()); 58 | setStream(null); 59 | setIsStreaming(false); 60 | } 61 | }; 62 | 63 | const result: UseMediaStreamResult = { 64 | type: "screen", 65 | start, 66 | stop, 67 | isStreaming, 68 | stream, 69 | }; 70 | 71 | return result; 72 | } 73 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/agentic_rag/README.md: -------------------------------------------------------------------------------- 1 | # Agentic RAG 2 | 3 | This agent enhances the Agent Starter Pack with a production-ready data ingestion pipeline, enriching your Retrieval Augmented Generation (RAG) applications. You will be able to ingest, process, and embed custom data, improving the relevance and context of your generated responses. You can choose between different datastore options including Vertex AI Search and Vertex AI Vector Search depending on your specific needs. 4 | 5 | The agent provides the infrastructure to create a Vertex AI Pipeline with your custom code. Because it's built on Vertex AI Pipelines, you benefit from features like scheduled runs, recurring executions, and on-demand triggers. For processing terabyte-scale data, we recommend combining Vertex AI Pipelines with data analytics tools like BigQuery or Dataflow. 6 | 7 | ![search agent demo](https://storage.googleapis.com/github-repo/generative-ai/sample-apps/e2e-gen-ai-app-starter-pack/starter-pack-search-pattern.gif) 8 | 9 | ## Architecture 10 | 11 | The agent implements the following architecture: 12 | 13 | ![architecture diagram](https://storage.googleapis.com/github-repo/generative-ai/sample-apps/e2e-gen-ai-app-starter-pack/agentic_rag_vertex_ai_search_architecture.png) 14 | 15 | ### Key Features 16 | 17 | - **Built on Agent Development Kit (ADK):** ADK is a flexible, modular framework for developing and deploying AI agents. It integrates with the Google ecosystem and Gemini models, supporting various LLMs and open-source AI tools, enabling both simple and complex agent architectures. 18 | - **Flexible Datastore Options:** Choose between Vertex AI Search or Vertex AI Vector Search for efficient data storage and retrieval based on your specific needs. 19 | - **Automated Data Ingestion Pipeline:** Automates the process of ingesting data from input sources. 20 | - **Custom Embeddings:** Generates embeddings using Vertex AI Embeddings and incorporates them into your data for enhanced semantic search. 21 | - **Terraform Deployment:** Ingestion pipeline is instantiated with Terraform alongside the rest of the infrastructure of the starter pack. 22 | - **CI/CD Integration:** Deployment of ingestion pipelines is added to the CD pipelines of the starter pack. 23 | - **Customizable Code:** Easily adapt and customize the code to fit your specific application needs and data sources. 24 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/utils/worklets/audio-processing.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const AudioRecordingWorklet = ` 18 | class AudioProcessingWorklet extends AudioWorkletProcessor { 19 | 20 | // send and clear buffer every 2048 samples, 21 | // which at 16khz is about 8 times a second 22 | buffer = new Int16Array(2048); 23 | 24 | // current write index 25 | bufferWriteIndex = 0; 26 | 27 | constructor() { 28 | super(); 29 | this.hasAudio = false; 30 | } 31 | 32 | /** 33 | * @param inputs Float32Array[][] [input#][channel#][sample#] so to access first inputs 1st channel inputs[0][0] 34 | * @param outputs Float32Array[][] 35 | */ 36 | process(inputs) { 37 | if (inputs[0].length) { 38 | const channel0 = inputs[0][0]; 39 | this.processChunk(channel0); 40 | } 41 | return true; 42 | } 43 | 44 | sendAndClearBuffer(){ 45 | this.port.postMessage({ 46 | event: "chunk", 47 | data: { 48 | int16arrayBuffer: this.buffer.slice(0, this.bufferWriteIndex).buffer, 49 | }, 50 | }); 51 | this.bufferWriteIndex = 0; 52 | } 53 | 54 | processChunk(float32Array) { 55 | const l = float32Array.length; 56 | 57 | for (let i = 0; i < l; i++) { 58 | // convert float32 -1 to 1 to int16 -32768 to 32767 59 | const int16Value = float32Array[i] * 32768; 60 | this.buffer[this.bufferWriteIndex++] = int16Value; 61 | if(this.bufferWriteIndex >= this.buffer.length) { 62 | this.sendAndClearBuffer(); 63 | } 64 | } 65 | 66 | if(this.bufferWriteIndex >= this.buffer.length) { 67 | this.sendAndClearBuffer(); 68 | } 69 | } 70 | } 71 | `; 72 | 73 | export default AudioRecordingWorklet; 74 | -------------------------------------------------------------------------------- /agent_starter_pack/resources/idx/.idx/dev.nix: -------------------------------------------------------------------------------- 1 | 2 | # To learn more about how to use Nix to configure your environment 3 | # see: https://firebase.google.com/docs/studio/customize-workspace 4 | { pkgs, ... }: { 5 | # Which nixpkgs channel to use. 6 | channel = "stable-24.11"; # or "unstable" 7 | 8 | # Use https://search.nixos.org/packages to find packages 9 | packages = [ 10 | pkgs.uv 11 | pkgs.gnumake 12 | pkgs.terraform 13 | pkgs.gh 14 | ]; 15 | # Sets environment variables in the workspace 16 | env = {}; 17 | idx = { 18 | # Search for the extensions you want on https://open-vsx.org/ and use "publisher.id" 19 | extensions = [ 20 | ]; 21 | workspace = { 22 | # Runs when a workspace is first created with this `dev.nix` file 23 | onCreate = { 24 | create-venv = '' 25 | # Load environment variables from .env file if it exists 26 | source .env 27 | 28 | # Beautiful prints for gcloud setup 29 | echo "" 30 | echo "╔════════════════════════════════════════════════════════════╗" 31 | echo "║ 🔐 GCLOUD SETUP REQUIRED ║" 32 | echo "╚════════════════════════════════════════════════════════════╝" 33 | echo "" 34 | echo "📝 Before proceeding, please ensure:" 35 | echo " 1️⃣ You are logged in to gcloud" 36 | echo " 2️⃣ You have selected the correct project" 37 | echo "" 38 | 39 | auth_status=$(gcloud auth list --quiet 2>&1) 40 | 41 | echo "" 42 | echo "⚙️ We will now set the project you want to use..." 43 | gcloud config get project 44 | 45 | echo "" 46 | echo "💡 Need to setup? Run these commands:" 47 | echo " → gcloud auth login" 48 | echo " → gcloud config set project YOUR_PROJECT_ID" 49 | echo "" 50 | 51 | echo "Running agent starter pack creation..." 52 | uvx agent-starter-pack create $WS_NAME 53 | code ~/$WS_NAME/$WS_NAME/README.md 54 | exec bash 55 | ''; 56 | # Open editors for the following files by default, if they exist: 57 | default.openFiles = []; 58 | }; 59 | # To run something each time the workspace is (re)started, use the `onStart` hook 60 | }; 61 | # Enable previews and customize configuration 62 | previews = {}; 63 | }; 64 | } -------------------------------------------------------------------------------- /agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml: -------------------------------------------------------------------------------- 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 | name: PR Checks 16 | 17 | on: 18 | pull_request: 19 | branches: 20 | - main 21 | paths: 22 | - '{{cookiecutter.agent_directory}}/**' 23 | - 'data_ingestion/**' 24 | - 'tests/**' 25 | - 'deployment/**' 26 | - 'uv.lock' 27 | {%- if cookiecutter.data_ingestion %} 28 | - 'data_ingestion/**' 29 | {%- endif %} 30 | 31 | jobs: 32 | test: 33 | runs-on: ubuntu-latest 34 | permissions: 35 | contents: 'read' 36 | id-token: 'write' 37 | steps: 38 | - name: Checkout code 39 | uses: actions/checkout@v4 40 | 41 | - id: 'auth' 42 | name: 'Authenticate to Google Cloud' 43 | uses: 'google-github-actions/auth@v2' 44 | with: 45 | workload_identity_provider: 'projects/{% raw %}${{ vars.GCP_PROJECT_NUMBER }}{% endraw %}/locations/global/workloadIdentityPools/{% raw %}${{ secrets.WIF_POOL_ID }}{% endraw %}/providers/{% raw %}${{ secrets.WIF_PROVIDER_ID }}{% endraw %}' 46 | service_account: '{% raw %}${{ secrets.GCP_SERVICE_ACCOUNT }}{% endraw %}' 47 | create_credentials_file: true 48 | project_id: {% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %} 49 | 50 | 51 | - name: Set up Python 3.11 52 | uses: actions/setup-python@v4 53 | with: 54 | python-version: '3.11' 55 | 56 | - name: Install uv and dependencies 57 | run: | 58 | pip install uv==0.8.13 59 | uv sync --locked 60 | 61 | - name: Run unit tests 62 | run: uv run pytest tests/unit 63 | 64 | - name: Run integration tests 65 | run: uv run pytest tests/integration 66 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/adk_base/app/agent.py: -------------------------------------------------------------------------------- 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 | import datetime 16 | import os 17 | from zoneinfo import ZoneInfo 18 | 19 | import google.auth 20 | from google.adk.agents import Agent 21 | 22 | _, project_id = google.auth.default() 23 | os.environ.setdefault("GOOGLE_CLOUD_PROJECT", project_id) 24 | os.environ.setdefault("GOOGLE_CLOUD_LOCATION", "global") 25 | os.environ.setdefault("GOOGLE_GENAI_USE_VERTEXAI", "True") 26 | 27 | 28 | def get_weather(query: str) -> str: 29 | """Simulates a web search. Use it get information on weather. 30 | 31 | Args: 32 | query: A string containing the location to get weather information for. 33 | 34 | Returns: 35 | A string with the simulated weather information for the queried location. 36 | """ 37 | if "sf" in query.lower() or "san francisco" in query.lower(): 38 | return "It's 60 degrees and foggy." 39 | return "It's 90 degrees and sunny." 40 | 41 | 42 | def get_current_time(query: str) -> str: 43 | """Simulates getting the current time for a city. 44 | 45 | Args: 46 | city: The name of the city to get the current time for. 47 | 48 | Returns: 49 | A string with the current time information. 50 | """ 51 | if "sf" in query.lower() or "san francisco" in query.lower(): 52 | tz_identifier = "America/Los_Angeles" 53 | else: 54 | return f"Sorry, I don't have timezone information for query: {query}." 55 | 56 | tz = ZoneInfo(tz_identifier) 57 | now = datetime.datetime.now(tz) 58 | return f"The current time for query {query} is {now.strftime('%Y-%m-%d %H:%M:%S %Z%z')}" 59 | 60 | 61 | root_agent = Agent( 62 | name="root_agent", 63 | model="gemini-2.5-flash", 64 | instruction="You are a helpful AI assistant designed to provide accurate and useful information.", 65 | tools=[get_weather, get_current_time], 66 | ) 67 | -------------------------------------------------------------------------------- /agent_starter_pack/agents/agentic_rag/tests/integration/test_agent.py: -------------------------------------------------------------------------------- 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 | # mypy: disable-error-code="union-attr" 16 | from unittest.mock import MagicMock, patch 17 | 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 {{cookiecutter.agent_directory}}.agent import root_agent 24 | 25 | 26 | @patch( 27 | "{{cookiecutter.agent_directory}}.agent.retrieve_docs", 28 | return_value="dummy content", 29 | ) 30 | def test_agent_stream(mock_retrieve: MagicMock) -> None: 31 | """ 32 | Integration test for the agent stream functionality. 33 | Tests that the agent returns valid streaming responses. 34 | """ 35 | 36 | session_service = InMemorySessionService() 37 | 38 | session = session_service.create_session_sync(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" 54 | 55 | has_text_content = False 56 | for event in events: 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 63 | break 64 | assert has_text_content, "Expected at least one message with text content" 65 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py: -------------------------------------------------------------------------------- 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 | # fmt: off 16 | 17 | from typing import Any 18 | 19 | 20 | class MessageEditing: 21 | """Provides methods for editing, refreshing, and deleting chat messages.""" 22 | 23 | @staticmethod 24 | def edit_message(st: Any, button_idx: int, message_type: str) -> None: 25 | """Edit a message in the chat history.""" 26 | button_id = f"edit_box_{button_idx}" 27 | if message_type == "human": 28 | messages = st.session_state.user_chats[st.session_state["session_id"]][ 29 | "messages" 30 | ] 31 | st.session_state.user_chats[st.session_state["session_id"]][ 32 | "messages" 33 | ] = messages[:button_idx] 34 | st.session_state.modified_prompt = st.session_state[button_id] 35 | else: 36 | st.session_state.user_chats[st.session_state["session_id"]]["messages"][ 37 | button_idx 38 | ]["content"] = st.session_state[button_id] 39 | 40 | @staticmethod 41 | def refresh_message(st: Any, button_idx: int, content: str) -> None: 42 | """Refresh a message in the chat history.""" 43 | messages = st.session_state.user_chats[st.session_state["session_id"]][ 44 | "messages" 45 | ] 46 | st.session_state.user_chats[st.session_state["session_id"]][ 47 | "messages" 48 | ] = messages[:button_idx] 49 | st.session_state.modified_prompt = content 50 | 51 | @staticmethod 52 | def delete_message(st: Any, button_idx: int) -> None: 53 | """Delete a message from the chat history.""" 54 | messages = st.session_state.user_chats[st.session_state["session_id"]][ 55 | "messages" 56 | ] 57 | st.session_state.user_chats[st.session_state["session_id"]][ 58 | "messages" 59 | ] = messages[:button_idx] 60 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { useRef, useState } from "react"; 18 | import "./App.scss"; 19 | import { LiveAPIProvider } from "./contexts/LiveAPIContext"; 20 | import SidePanel from "./components/side-panel/SidePanel"; 21 | import cn from "classnames"; 22 | 23 | // In development mode (frontend on :8501), connect to backend on :8000 24 | const isDevelopment = window.location.port === '8501'; 25 | const defaultHost = isDevelopment ? `${window.location.hostname}:8000` : window.location.host; 26 | const defaultUri = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${defaultHost}/`; 27 | 28 | function App() { 29 | const videoRef = useRef(null); 30 | const [videoStream, setVideoStream] = useState(null); 31 | const [serverUrl, setServerUrl] = useState(defaultUri); 32 | const [userId, setUserId] = useState("user1"); 33 | 34 | return ( 35 |
36 | 37 |
38 | 47 |
48 |
49 |
58 |
59 |
60 |
61 |
62 | ); 63 | } 64 | 65 | export default App; 66 | -------------------------------------------------------------------------------- /docs/guide/observability.md: -------------------------------------------------------------------------------- 1 | # Monitoring and Observability 2 | 3 | ![monitoring_flow](https://storage.googleapis.com/github-repo/generative-ai/sample-apps/e2e-gen-ai-app-starter-pack/monitoring_flow.png) 4 | 5 | ### Trace and Log Capture 6 | 7 | Templated agents utilize [OpenTelemetry](https://opentelemetry.io/) for comprehensive observability, emitting events to Google Cloud Trace and Google Cloud Logging. Every interaction with the LLM instrumented, enabling detailed tracing of request flows throughout agents built with this framework. 8 | 9 | Leveraging the [CloudTraceSpanExporter](https://cloud.google.com/python/docs/reference/spanner/latest/opentelemetry-tracing), the framework captures and exports tracing data. To address the limitations of Cloud Trace ([256-byte attribute value limit](https://cloud.google.com/trace/docs/quotas#limits_on_spans)) and [Cloud Logging](https://cloud.google.com/logging/quotas) ([256KB log entry size](https://cloud.google.com/logging/quotas)), a custom extension of the CloudTraceSpanExporter is implemented in `app/utils/tracing.py` of the templated project. 10 | 11 | This extension enhances observability by: 12 | 13 | - Creating a corresponding Google Cloud Logging entry for every captured event. 14 | - Automatically storing event data in Google Cloud Storage when the payload exceeds 256KB. 15 | 16 | Logged payloads are associated with the original trace, ensuring seamless access from the Cloud Trace console. 17 | 18 | ### Log Router 19 | 20 | Events are forwarded to BigQuery through a [log router](https://cloud.google.com/logging/docs/routing/overview) for long-term storage and analysis. The deployment of the log router is handled via Terraform code in `deployment/terraform` in the templated project. 21 | 22 | ### Looker Studio Dashboard 23 | 24 | Once the data is written to BigQuery, it can be used to populate a [Looker Studio dashboard](https://lookerstudio.google.com/c/reporting/46b35167-b38b-4e44-bd37-701ef4307418/page/tEnnC). Use [this dashboard](https://lookerstudio.google.com/c/reporting/fa742264-4b4b-4c56-81e6-a667dd0f853f/page/tEnnC) if using non-ADK agents. 25 | 26 | This dashboard template provides a starting point for building custom visualizations on top of the captured data. 27 | 28 | ## Disclaimer 29 | 30 | **Note:** The templated agents are designed to enable *your* use-case observability in your Google Cloud Project. Google Cloud does not log, monitor, or otherwise access any data generated from the deployed resources. See the [Google Cloud Service Terms](https://cloud.google.com/terms/service-terms) for more details. 31 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py: -------------------------------------------------------------------------------- 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 | import os 16 | from pathlib import Path 17 | from typing import Any 18 | 19 | import yaml 20 | 21 | SAVED_CHAT_PATH = str(os.getcwd()) + "/.saved_chats" 22 | 23 | 24 | def clean_text(text: str) -> str: 25 | """Preprocess the input text by removing leading and trailing newlines.""" 26 | if not text: 27 | return text 28 | 29 | if text.startswith("\n"): 30 | text = text[1:] 31 | if text.endswith("\n"): 32 | text = text[:-1] 33 | return text 34 | 35 | 36 | def sanitize_messages( 37 | messages: list[dict[str, str | list[dict[str, str]]]], 38 | ) -> list[dict[str, str | list[dict[str, str]]]]: 39 | """Preprocess and fix the content of messages.""" 40 | for message in messages: 41 | if isinstance(message["content"], list): 42 | for part in message["content"]: 43 | if part["type"] == "text": 44 | part["text"] = clean_text(part["text"]) 45 | else: 46 | message["content"] = clean_text(message["content"]) 47 | return messages 48 | 49 | 50 | def save_chat(st: Any) -> None: 51 | """Save the current chat session to a YAML file.""" 52 | Path(SAVED_CHAT_PATH).mkdir(parents=True, exist_ok=True) 53 | session_id = st.session_state["session_id"] 54 | session = st.session_state.user_chats[session_id] 55 | messages = session.get("messages", []) 56 | if len(messages) > 0: 57 | session["messages"] = sanitize_messages(session["messages"]) 58 | filename = f"{session_id}.yaml" 59 | with open(Path(SAVED_CHAT_PATH) / filename, "w", encoding="utf-8") as file: 60 | yaml.dump( 61 | [session], 62 | file, 63 | allow_unicode=True, 64 | default_flow_style=False, 65 | encoding="utf-8", 66 | ) 67 | st.toast(f"Chat saved to path: ↓ {Path(SAVED_CHAT_PATH) / filename}") 68 | -------------------------------------------------------------------------------- /docs/remote-templates/index.md: -------------------------------------------------------------------------------- 1 | # Remote Templates 2 | 3 | Remote templates turn your agent prototype into a production-ready starter pack. A remote template is a Git repository containing your custom agent logic, dependencies, and infrastructure definitions (Terraform). The `agent-starter-pack` CLI uses it to generate a complete, deployable application by automatically adding production-grade boilerplate for testing and multi-target deployment (e.g., Cloud Run, Agent Engine). 4 | 5 | ## Choose Your Path 6 | 7 | ### 🚀 Using Remote Templates 8 | **For developers who want to use existing templates** 9 | 10 | Use any Git repository as a template to create production-ready agents instantly. Perfect for getting started quickly or using community-created templates. 11 | 12 | **[👉 Go to Using Remote Templates Guide](./using-remote-templates.md)** 13 | 14 | Quick example: 15 | ```bash 16 | uvx agent-starter-pack create my-agent -a adk@gemini-fullstack 17 | ``` 18 | 19 | --- 20 | 21 | ### 🛠️ Creating Remote Templates 22 | **For developers who want to share their own templates** 23 | 24 | Package your custom agent logic, dependencies, and infrastructure into reusable templates that others can use. Perfect for sharing best practices and creating standardized agent patterns. 25 | 26 | **[👉 Go to Creating Remote Templates Guide](./creating-remote-templates.md)** 27 | 28 | Quick example: 29 | ```bash 30 | # After creating your template repository 31 | uvx agent-starter-pack create test-agent -a https://github.com/you/your-template 32 | ``` 33 | 34 | --- 35 | 36 | ## Overview 37 | 38 | Remote templates work by: 39 | 1. **Fetching** template repositories from Git 40 | 2. **Version locking** - automatically uses the exact starter pack version specified by the template for guaranteed compatibility 41 | 3. **Applying** intelligent defaults based on repository structure 42 | 4. **Merging** template files with base agent infrastructure 43 | 5. **Generating** complete, production-ready agent projects 44 | 45 | Any Git repository can become a template - the system handles the complexity automatically. 46 | 47 | ## Related Documentation 48 | 49 | - **[Using Remote Templates](./using-remote-templates.md)** - Complete guide for template users 50 | - **[Creating Remote Templates](./creating-remote-templates.md)** - Complete guide for template authors 51 | - **[Template Config Reference](../guide/template-config-reference.md)** - All available configuration options 52 | - **[create CLI](../cli/create.md)** - Command line reference for creating agents 53 | - **[enhance CLI](../cli/enhance.md)** - Command line reference for enhancing projects -------------------------------------------------------------------------------- /agent_starter_pack/utils/lock_utils.py: -------------------------------------------------------------------------------- 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 | """Utilities for managing uv lock files and dependencies.""" 16 | 17 | import pathlib 18 | from pathlib import Path 19 | from typing import NamedTuple 20 | 21 | import yaml 22 | 23 | 24 | class AgentConfig(NamedTuple): 25 | """Configuration for an agent template.""" 26 | 27 | targets: set[str] 28 | dependencies: list[str] 29 | 30 | 31 | def get_agent_configs( 32 | agents_dir: pathlib.Path = pathlib.Path("agent_starter_pack/agents"), 33 | ) -> dict[str, AgentConfig]: 34 | """Get all agents and their supported deployment targets. 35 | 36 | Args: 37 | agents_dir: Path to the agents directory 38 | 39 | Returns: 40 | Dictionary mapping agent names to their configuration 41 | """ 42 | agent_configs = {} 43 | 44 | for agent_dir in agents_dir.iterdir(): 45 | if not agent_dir.is_dir(): 46 | continue 47 | 48 | config_file = agent_dir / ".template" / "templateconfig.yaml" 49 | if not config_file.exists(): 50 | continue 51 | 52 | with open(config_file, encoding="utf-8") as f: 53 | config = yaml.safe_load(f) 54 | 55 | agent_name = agent_dir.name 56 | settings = config.get("settings", {}) 57 | 58 | agent_configs[agent_name] = settings 59 | 60 | return agent_configs 61 | 62 | 63 | def get_lock_filename(agent_name: str, deployment_target: str) -> str: 64 | """Generate the lock filename for a given agent and deployment target. 65 | 66 | Args: 67 | agent_name: Name of the agent 68 | deployment_target: Target deployment platform 69 | 70 | Returns: 71 | Formatted lock filename 72 | """ 73 | return f"uv-{agent_name}-{deployment_target}.lock" 74 | 75 | 76 | def get_lock_path(agent_name: str, deployment_target: str) -> Path: 77 | """Get the path to the appropriate lock file.""" 78 | lock_filename = get_lock_filename(agent_name, deployment_target) 79 | return Path("agent_starter_pack/resources/locks") / lock_filename 80 | -------------------------------------------------------------------------------- /tests/integration/utils.py: -------------------------------------------------------------------------------- 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 | import pathlib 16 | import subprocess 17 | 18 | from rich.console import Console 19 | 20 | console = Console() 21 | 22 | 23 | def run_command( 24 | cmd: list[str], 25 | cwd: pathlib.Path | None, 26 | message: str, 27 | stream_output: bool = True, 28 | env: dict | None = None, 29 | ) -> subprocess.CompletedProcess: 30 | """Helper function to run commands and stream output""" 31 | console.print(f"\n[bold blue]{message}...[/]") 32 | try: 33 | # Using Popen to stream output 34 | with subprocess.Popen( 35 | cmd, 36 | stdout=subprocess.PIPE, 37 | stderr=subprocess.PIPE, 38 | text=True, 39 | cwd=cwd, 40 | bufsize=1, # Line-buffered 41 | env=env, 42 | encoding="utf-8", 43 | ) as process: 44 | if stream_output: 45 | # Stream stdout 46 | if process.stdout: 47 | for line in process.stdout: 48 | console.print(line.strip()) 49 | 50 | # Stream stderr 51 | if process.stderr: 52 | for line in process.stderr: 53 | console.print("[bold red]" + line.strip()) 54 | else: 55 | # Consume the output but don't print it 56 | if process.stdout: 57 | for _ in process.stdout: 58 | pass 59 | if process.stderr: 60 | for _ in process.stderr: 61 | pass 62 | 63 | # Wait for the process to complete and get the return code 64 | returncode = process.wait() 65 | 66 | if returncode != 0: 67 | raise subprocess.CalledProcessError(returncode, cmd) 68 | 69 | console.print(f"[green]✓[/] {message} completed successfully") 70 | return subprocess.CompletedProcess(cmd, returncode, "", "") 71 | 72 | except subprocess.CalledProcessError: 73 | console.print(f"[bold red]Error: {message}[/]") 74 | raise 75 | -------------------------------------------------------------------------------- /agent_starter_pack/frontends/adk_live_react/frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 32 | 35 | 36 | 45 | Multimodal Live - Console 46 | 47 | 48 | 49 | 50 |
51 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /tests/test_frontend/test_utils/test_multimodal_utils.py: -------------------------------------------------------------------------------- 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 | from unittest.mock import MagicMock, patch 16 | 17 | import pytest 18 | 19 | from frontend.utils.multimodal_utils import ( 20 | format_content, 21 | get_gcs_blob_mime_type, 22 | gs_uri_to_https_url, 23 | ) 24 | 25 | 26 | def test_format_content_text_only() -> None: 27 | """Test formatting plain text content""" 28 | content = "Hello world" 29 | formatted = format_content(content) 30 | assert formatted == "Hello world" 31 | 32 | 33 | def test_format_content_single_image() -> None: 34 | """Test formatting content with a single image""" 35 | content = [{"type": "image_url", "image_url": {"url": "test.jpg"}}] 36 | formatted = format_content(content) 37 | assert ' None: 42 | """Test formatting content with text and images""" 43 | content = [ 44 | {"type": "text", "text": "Here's an image:"}, 45 | {"type": "image_url", "image_url": {"url": "test.jpg"}}, 46 | ] 47 | formatted = format_content(content) 48 | assert "Here's an image:" in formatted 49 | assert ' None: 54 | """Test getting MIME type from GCS blob""" 55 | mock_blob = MagicMock() 56 | mock_blob.content_type = "image/jpeg" 57 | mock_bucket = MagicMock() 58 | mock_bucket.blob.return_value = mock_blob 59 | mock_storage_client.return_value.bucket.return_value = mock_bucket 60 | 61 | mime_type = get_gcs_blob_mime_type("gs://bucket/test.jpg") 62 | assert mime_type == "image/jpeg" 63 | 64 | 65 | def test_gs_uri_to_https_url() -> None: 66 | """Test converting GCS URI to HTTPS URL""" 67 | gs_uri = "gs://bucket/folder/file.jpg" 68 | https_url = gs_uri_to_https_url(gs_uri) 69 | assert https_url == "https://storage.mtls.cloud.google.com/bucket/folder/file.jpg" 70 | 71 | 72 | def test_gs_uri_to_https_url_invalid() -> None: 73 | """Test converting invalid GCS URI""" 74 | with pytest.raises(ValueError): 75 | gs_uri_to_https_url("invalid_uri") 76 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %}: -------------------------------------------------------------------------------- 1 | 2 | data "google_project" "cicd_project" { 3 | project_id = var.cicd_runner_project_id 4 | } 5 | 6 | resource "google_service_account_iam_member" "github_oidc_access" { 7 | service_account_id = resource.google_service_account.cicd_runner_sa.name 8 | role = "roles/iam.workloadIdentityUser" 9 | member = "principalSet://iam.googleapis.com/projects/${data.google_project.cicd_project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.github_pool.workload_identity_pool_id}/attribute.repository/${var.repository_owner}/${var.repository_name}" 10 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 11 | } 12 | 13 | # Allow the GitHub Actions principal to impersonate the CICD runner service account 14 | resource "google_service_account_iam_member" "github_sa_impersonation" { 15 | service_account_id = resource.google_service_account.cicd_runner_sa.name 16 | role = "roles/iam.serviceAccountTokenCreator" 17 | member = "principalSet://iam.googleapis.com/projects/${data.google_project.cicd_project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.github_pool.workload_identity_pool_id}/attribute.repository/${var.repository_owner}/${var.repository_name}" 18 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 19 | } 20 | 21 | resource "google_iam_workload_identity_pool" "github_pool" { 22 | workload_identity_pool_id = "${var.project_name}-pool" 23 | project = var.cicd_runner_project_id 24 | display_name = "GitHub Actions Pool" 25 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 26 | } 27 | 28 | resource "google_iam_workload_identity_pool_provider" "github_provider" { 29 | workload_identity_pool_provider_id = "${var.project_name}-oidc" 30 | project = var.cicd_runner_project_id 31 | workload_identity_pool_id = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id 32 | display_name = "GitHub OIDC Provider" 33 | oidc { 34 | issuer_uri = "https://token.actions.githubusercontent.com" 35 | } 36 | attribute_mapping = { 37 | "google.subject" = "assertion.sub" 38 | "attribute.repository" = "assertion.repository" 39 | "attribute.repository_owner" = "assertion.repository_owner" 40 | } 41 | attribute_condition = "attribute.repository == '${var.repository_owner}/${var.repository_name}'" 42 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 43 | } 44 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf: -------------------------------------------------------------------------------- 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 | resource "google_project_iam_member" "bigquery_data_editor" { 16 | 17 | project = var.dev_project_id 18 | role = "roles/bigquery.dataEditor" 19 | member = module.log_export_to_bigquery.writer_identity 20 | } 21 | 22 | resource "google_bigquery_dataset" "feedback_dataset" { 23 | project = var.dev_project_id 24 | dataset_id = replace("${var.project_name}_feedback", "-", "_") 25 | friendly_name = "${var.project_name}_feedback" 26 | location = var.region 27 | depends_on = [resource.google_project_service.services] 28 | } 29 | 30 | resource "google_bigquery_dataset" "telemetry_logs_dataset" { 31 | project = var.dev_project_id 32 | dataset_id = replace("${var.project_name}_telemetry", "-", "_") 33 | friendly_name = "${var.project_name}_telemetry" 34 | location = var.region 35 | depends_on = [resource.google_project_service.services] 36 | } 37 | 38 | module "feedback_export_to_bigquery" { 39 | source = "terraform-google-modules/log-export/google" 40 | version = "10.0.0" 41 | log_sink_name = "${var.project_name}_feedback" 42 | parent_resource_type = "project" 43 | parent_resource_id = var.dev_project_id 44 | destination_uri = "bigquery.googleapis.com/projects/${var.dev_project_id}/datasets/${google_bigquery_dataset.feedback_dataset.dataset_id}" 45 | filter = var.feedback_logs_filter 46 | bigquery_options = { use_partitioned_tables = true } 47 | unique_writer_identity = true 48 | depends_on = [google_bigquery_dataset.feedback_dataset] 49 | } 50 | 51 | module "log_export_to_bigquery" { 52 | source = "terraform-google-modules/log-export/google" 53 | version = "10.0.0" 54 | 55 | log_sink_name = "${var.project_name}_telemetry" 56 | parent_resource_type = "project" 57 | parent_resource_id = var.dev_project_id 58 | destination_uri = "bigquery.googleapis.com/projects/${var.dev_project_id}/datasets/${google_bigquery_dataset.telemetry_logs_dataset.dataset_id}" 59 | filter = var.telemetry_logs_filter 60 | bigquery_options = { use_partitioned_tables = true } 61 | unique_writer_identity = true 62 | depends_on = [google_bigquery_dataset.telemetry_logs_dataset] 63 | } 64 | -------------------------------------------------------------------------------- /tests/fixtures/makefile_snapshots/adk_base_agent_engine_no_data.makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Installation & Setup 3 | # ============================================================================== 4 | 5 | # Install dependencies using uv package manager 6 | install: 7 | @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.8.13/install.sh | sh; source $HOME/.local/bin/env; } 8 | uv sync --dev 9 | 10 | # ============================================================================== 11 | # Playground Targets 12 | # ============================================================================== 13 | 14 | # Launch local dev playground 15 | playground: 16 | @echo "===============================================================================" 17 | @echo "| 🚀 Starting your agent playground... |" 18 | @echo "| |" 19 | @echo "| 💡 Try asking: What can you help me with?|" 20 | @echo "| |" 21 | @echo "| 🔍 IMPORTANT: Select the 'test_adk_base' folder to interact with your agent. |" 22 | @echo "===============================================================================" 23 | uv run adk web . --port 8501 --reload_agents 24 | 25 | # ============================================================================== 26 | # Backend Deployment Targets 27 | # ============================================================================== 28 | 29 | # Deploy the agent remotely 30 | backend: 31 | # Export dependencies to requirements file using uv export. 32 | uv export --no-hashes --no-header --no-dev --no-emit-project --no-annotate > .requirements.txt 2>/dev/null || \ 33 | uv export --no-hashes --no-header --no-dev --no-emit-project > .requirements.txt && uv run test_adk_base/agent_engine_app.py 34 | 35 | 36 | # ============================================================================== 37 | # Infrastructure Setup 38 | # ============================================================================== 39 | 40 | # Set up development environment resources using Terraform 41 | setup-dev-env: 42 | PROJECT_ID=$$(gcloud config get-value project) && \ 43 | (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve) 44 | 45 | # ============================================================================== 46 | # Testing & Code Quality 47 | # ============================================================================== 48 | 49 | # Run unit and integration tests 50 | test: 51 | uv run pytest tests/unit && uv run pytest tests/integration 52 | 53 | # Run code quality checks (codespell, ruff, mypy) 54 | lint: 55 | uv sync --dev --extra lint 56 | uv run codespell 57 | uv run ruff check . --diff 58 | uv run ruff format . --check --diff 59 | uv run mypy . 60 | -------------------------------------------------------------------------------- /tests/fixtures/makefile_snapshots/agent_with_custom_commands.makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Installation & Setup 3 | # ============================================================================== 4 | 5 | # Install dependencies using uv package manager 6 | install: 7 | @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.8.13/install.sh | sh; source $HOME/.local/bin/env; } 8 | echo 'Custom install command' 9 | 10 | # ============================================================================== 11 | # Playground Targets 12 | # ============================================================================== 13 | 14 | # Launch local dev playground 15 | playground: 16 | echo 'Custom playground' 17 | 18 | # ============================================================================== 19 | # Agent-Specific Commands 20 | # ============================================================================== 21 | 22 | # Run a custom task 23 | custom-task: 24 | echo 'Running custom task' 25 | 26 | # Task with deployment-specific commands 27 | env-specific-task: 28 | echo 'Cloud Run task' 29 | 30 | # ============================================================================== 31 | # Backend Deployment Targets 32 | # ============================================================================== 33 | 34 | # Deploy the agent remotely 35 | # Usage: make backend [IAP=true] [PORT=8080] - Set IAP=true to enable Identity-Aware Proxy, PORT to specify container port 36 | backend: 37 | PROJECT_ID=$$(gcloud config get-value project) && \ 38 | gcloud beta run deploy test-custom \ 39 | --source . \ 40 | --memory "4Gi" \ 41 | --project $$PROJECT_ID \ 42 | --region "us-central1" \ 43 | --no-allow-unauthenticated \ 44 | --no-cpu-throttling \ 45 | --labels "" \ 46 | --set-env-vars \ 47 | "COMMIT_SHA=$(shell git rev-parse HEAD)" \ 48 | $(if $(IAP),--iap) \ 49 | $(if $(PORT),--port=$(PORT)) 50 | 51 | 52 | # ============================================================================== 53 | # Infrastructure Setup 54 | # ============================================================================== 55 | 56 | # Set up development environment resources using Terraform 57 | setup-dev-env: 58 | PROJECT_ID=$$(gcloud config get-value project) && \ 59 | (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve) 60 | 61 | # ============================================================================== 62 | # Testing & Code Quality 63 | # ============================================================================== 64 | 65 | # Run unit and integration tests 66 | test: 67 | uv run pytest tests/unit && uv run pytest tests/integration 68 | 69 | # Run code quality checks (codespell, ruff, mypy) 70 | lint: 71 | uv sync --dev --extra lint 72 | uv run codespell 73 | uv run ruff check . --diff 74 | uv run ruff format . --check --diff 75 | uv run mypy . 76 | -------------------------------------------------------------------------------- /docs/guide/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | This guide helps resolve common issues with the Agent Starter Pack. 4 | 5 | ## Authentication Issues 6 | 7 | For detailed information on authentication with Vertex AI, visit the [official documentation](https://cloud.google.com/vertex-ai/docs/authentication). 8 | 9 | ### "Could not find credentials" or "Could not find project" Error 10 | 11 | **Problem**: Missing credentials error with Vertex AI. 12 | 13 | **Solution**: 14 | 15 | 1. Log in to Google Cloud: `gcloud auth login --update-adc` 16 | 2. Set the correct project: 17 | ```bash 18 | gcloud config set project YOUR_PROJECT_ID 19 | gcloud auth application-default set-quota-project YOUR_PROJECT_ID 20 | ``` 21 | 22 | ### Vertex AI API Not Enabled 23 | 24 | **Problem**: Operations fail because the Vertex AI API is not enabled in your project. 25 | 26 | **Solution**: 27 | 28 | 1. Enable the Vertex AI API: 29 | ```bash 30 | gcloud services enable aiplatform.googleapis.com 31 | ``` 32 | 33 | 2. Verify the API is enabled: 34 | ```bash 35 | gcloud services list --filter=aiplatform.googleapis.com 36 | ``` 37 | 38 | ### Permission Denied Errors 39 | **Problem**: "Permission denied" errors with Google Cloud APIs. 40 | 41 | **Solution**: Ensure your user or service account has the necessary IAM roles. For example, for Vertex AI, you often need `roles/aiplatform.user`. Grant roles using the `gcloud projects add-iam-policy-binding` command or the Cloud Console. 42 | 43 | ### Command Not Found: agent-starter-pack 44 | 45 | **Problem**: "Command not found" error after installation. 46 | 47 | **Solution**: 48 | 49 | 1. Verify installation: 50 | ```bash 51 | pip list | grep agent-starter-pack 52 | ``` 53 | 2. Check PATH: 54 | ```bash 55 | echo $PATH 56 | ``` 57 | 3. Reinstall if needed: 58 | ```bash 59 | pip install --user agent-starter-pack 60 | ``` 61 | 4. For pipx: 62 | ```bash 63 | pipx ensurepath 64 | source ~/.bashrc # or ~/.zshrc 65 | ``` 66 | 67 | ## Project Creation Issues 68 | 69 | ### Project Creation Fails 70 | 71 | **Problem**: `agent-starter-pack create` fails. 72 | 73 | **Solution**: 74 | 75 | 1. **Check Error Messages:** Examine output for clues. 76 | 2. **Write Permissions:** Ensure write access to the directory. 77 | 3. **Project Name:** Use lowercase letters, numbers and hyphens only. 78 | 4. **Debug Mode:** Consider using debug mode to get more detailed error information: 79 | ```bash 80 | agent-starter-pack create my-project-name --debug 81 | ``` 82 | 83 | ### Issues with Agent Engine 84 | 85 | Consider leveraging the [public product documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/troubleshooting/set-up) 86 | 87 | ## Getting More Help 88 | 89 | If issues persist: 90 | 91 | 1. **Check GitHub Issues:** Search for existing Github issues in the `agent-starter-pack` Github repository. 92 | 2. **File a New Issue:** Provide: 93 | 94 | * Problem description. 95 | * Steps to reproduce. 96 | * Error messages (preferably run with `--debug` flag for detailed logs). 97 | * Environment: OS, Python version, `agent-starter-pack` version, installation method, shell. 98 | -------------------------------------------------------------------------------- /tests/test_frontend/test_utils/test_local_chat_history.py: -------------------------------------------------------------------------------- 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 | from pathlib import Path 16 | 17 | import pytest 18 | import yaml 19 | 20 | from frontend.utils.local_chat_history import LocalChatMessageHistory 21 | 22 | 23 | @pytest.fixture 24 | def chat_history(tmp_path: Path) -> LocalChatMessageHistory: 25 | """Create a temporary chat history instance""" 26 | return LocalChatMessageHistory( 27 | user_id="test_user", session_id="test_session", base_dir=str(tmp_path) 28 | ) 29 | 30 | 31 | def test_init_creates_directory(tmp_path: Path) -> None: 32 | """Test directory creation on initialization""" 33 | user_dir = tmp_path / "test_user" 34 | assert not user_dir.exists() 35 | 36 | LocalChatMessageHistory( 37 | user_id="test_user", session_id="test_session", base_dir=str(tmp_path) 38 | ) 39 | 40 | assert user_dir.exists() 41 | 42 | 43 | def test_get_session(chat_history: LocalChatMessageHistory) -> None: 44 | """Test session ID and file path update""" 45 | chat_history.get_session("new_session") 46 | assert chat_history.session_id == "new_session" 47 | assert chat_history.session_file.endswith("new_session.yaml") 48 | 49 | 50 | def test_upsert_session(chat_history: LocalChatMessageHistory) -> None: 51 | """Test session update/insert""" 52 | session = { 53 | "title": "Test Chat", 54 | "messages": [ 55 | {"type": "human", "content": "Hello"}, 56 | {"type": "ai", "content": "Hi there"}, 57 | ], 58 | } 59 | 60 | chat_history.upsert_session(session) 61 | 62 | # Verify file was created 63 | assert Path(chat_history.session_file).exists() 64 | 65 | # Verify content 66 | with open(chat_history.session_file, encoding="utf-8") as f: 67 | saved_data = yaml.safe_load(f) 68 | assert len(saved_data) == 1 69 | assert saved_data[0]["title"] == "Test Chat" 70 | assert len(saved_data[0]["messages"]) == 2 71 | 72 | 73 | def test_get_all_conversations(chat_history: LocalChatMessageHistory) -> None: 74 | """Test retrieving all conversations""" 75 | # Create some test conversations 76 | sessions = { 77 | "session1": {"title": "Chat 1", "messages": []}, 78 | "session2": {"title": "Chat 2", "messages": []}, 79 | } 80 | 81 | for session_id, session in sessions.items(): 82 | chat_history.get_session(session_id) 83 | chat_history.upsert_session(session) 84 | 85 | conversations = chat_history.get_all_conversations() 86 | assert len(conversations) == 2 87 | assert "session1" in conversations 88 | assert "session2" in conversations 89 | -------------------------------------------------------------------------------- /tests/unit/README_MAKEFILE_TESTS.md: -------------------------------------------------------------------------------- 1 | # Makefile Template Test Suite 2 | 3 | Regression tests for `agent-starter-pack/base_template/Makefile` template refactoring. Ensures changes don't alter generated output across agent types, deployment targets, and feature combinations. 4 | 5 | ## Coverage 6 | 7 | Tests 9 configurations: ADK Base/Live (Cloud Run/Agent Engine), Agentic RAG (Vertex AI/Vector Search), LangGraph, Custom Commands, Agent Garden. 8 | 9 | ## Running Tests 10 | 11 | ```bash 12 | # All tests 13 | uv run pytest tests/unit/test_makefile_template.py -v 14 | 15 | # Specific categories (use -k filter) 16 | uv run pytest tests/unit/test_makefile_template.py -v -k "test_makefile_hash" # Fastest 17 | uv run pytest tests/unit/test_makefile_template.py -v -k "test_makefile_snapshot" # With diffs 18 | uv run pytest tests/unit/test_makefile_template.py -v -k "test_adk_live" # Specific feature 19 | ``` 20 | 21 | ## Refactoring Workflow 22 | 23 | 1. Run tests before changes (verify baseline) 24 | 2. Make incremental changes to `agent-starter-pack/base_template/Makefile` 25 | 3. Run tests frequently to catch issues 26 | 4. Verify all tests pass after refactoring 27 | 28 | ## Test Failures 29 | 30 | **Snapshot failure**: Generated Makefile changed. Review diff with `git diff tests/fixtures/makefile_snapshots/.makefile`. If intentional, delete snapshot and rerun. 31 | 32 | **Hash failure**: Content changed. If intentional, delete `tests/fixtures/makefile_hashes.json` and rerun. 33 | 34 | **Feature failure**: Required target missing. Check Jinja2 conditionals in template. 35 | 36 | ## Updating Baselines 37 | 38 | ```bash 39 | # All baselines 40 | rm -rf tests/fixtures/makefile_snapshots/*.makefile tests/fixtures/makefile_hashes.json 41 | uv run pytest tests/unit/test_makefile_template.py -v 42 | 43 | # Specific config 44 | rm tests/fixtures/makefile_snapshots/.makefile 45 | uv run pytest tests/unit/test_makefile_template.py::TestMakefileGeneration::test_makefile_snapshot[] -v 46 | ``` 47 | 48 | ## Test Types 49 | 50 | - **Snapshot**: Full output diffs (`tests/fixtures/makefile_snapshots/`) - for debugging 51 | - **Hash**: SHA256 comparison (`tests/fixtures/makefile_hashes.json`) - for CI/CD speed 52 | - **Feature**: Target presence validation - for functionality verification 53 | 54 | ## Adding Configurations 55 | 56 | 1. Add to `TEST_CONFIGURATIONS` in `test_makefile_template.py` 57 | 2. Run tests to generate baseline: `uv run pytest tests/unit/test_makefile_template.py -v` 58 | 3. Verify snapshot: `cat tests/fixtures/makefile_snapshots/.makefile` 59 | 60 | ## CI/CD 61 | 62 | ```yaml 63 | - name: Test Makefile Template 64 | run: uv run pytest tests/unit/test_makefile_template.py -v 65 | ``` 66 | 67 | ## Refactoring Tips 68 | 69 | - Make small, incremental changes 70 | - Run tests frequently 71 | - Use Jinja2 variables for reusability 72 | - Document complex conditionals 73 | - Group related targets by agent/deployment type 74 | 75 | ## Troubleshooting 76 | 77 | - **Slow tests**: Use hash tests (`-k "test_makefile_hash"`) 78 | - **Need diffs**: Use snapshot tests (`-k "test_makefile_snapshot"`) 79 | - **Jinja2 errors**: Check error message for line number 80 | - **Missing variables**: `StrictUndefined` is already enabled 81 | -------------------------------------------------------------------------------- /agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md: -------------------------------------------------------------------------------- 1 | {%- if cookiecutter.agent_name == "adk_live" %} 2 | # WebSocket Load Testing for Remote Agent Engine 3 | 4 | This directory provides a comprehensive load testing framework for your Agent Engine application using WebSocket connections, leveraging the power of [Locust](http://locust.io), a leading open-source load testing tool. 5 | 6 | The load test simulates realistic user interactions by: 7 | - Establishing WebSocket connections 8 | - Sending audio chunks in the proper `realtimeInput` format 9 | - Sending text messages to complete turns 10 | - Collecting and measuring responses until `turn_complete` 11 | 12 | ## Load Testing with Remote Agent Engine 13 | 14 | **1. Start the Expose App in Remote Mode:** 15 | 16 | Launch the expose app server in a separate terminal, pointing to your deployed agent engine: 17 | 18 | ```bash 19 | uv run python -m app.utils.expose_app --mode remote --remote-id 20 | ``` 21 | 22 | Or if you have `deployment_metadata.json` in your project root: 23 | 24 | ```bash 25 | uv run python -m app.utils.expose_app --mode remote 26 | ``` 27 | 28 | **2. Execute the Load Test:** 29 | 30 | Using another terminal tab, trigger the Locust load test: 31 | 32 | ```bash 33 | uv run --with locust==2.31.1 --with websockets locust -f tests/load_test/load_test.py \ 34 | -H http://127.0.0.1:8000 \ 35 | --headless \ 36 | -t 30s -u 1 -r 1 \ 37 | --csv=tests/load_test/.results/results \ 38 | --html=tests/load_test/.results/report.html 39 | ``` 40 | 41 | This command initiates a 30-second load test with 1 concurrent user. 42 | 43 | **Results:** 44 | 45 | Comprehensive CSV and HTML reports detailing the load test performance will be generated and saved in the `tests/load_test/.results` directory. 46 | {%- else %} 47 | # Robust Load Testing for Generative AI Applications 48 | 49 | This directory provides a comprehensive load testing framework for your Generative AI application, leveraging the power of [Locust](http://locust.io), a leading open-source load testing tool. 50 | 51 | ## Load Testing 52 | 53 | Before running load tests, ensure you have deployed the backend remotely. 54 | 55 | Follow these steps to execute load tests: 56 | 57 | **1. Deploy the Backend Remotely:** 58 | ```bash 59 | gcloud config set project 60 | make backend 61 | ``` 62 | 63 | **2. Create a Virtual Environment for Locust:** 64 | It's recommended to use a separate terminal tab and create a virtual environment for Locust to avoid conflicts with your application's Python environment. 65 | 66 | ```bash 67 | python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1 68 | ``` 69 | 70 | **3. Execute the Load Test:** 71 | Trigger the Locust load test with the following command: 72 | 73 | ```bash 74 | export _AUTH_TOKEN=$(gcloud auth print-access-token -q) 75 | locust -f tests/load_test/load_test.py \ 76 | --headless \ 77 | -t 30s -u 5 -r 2 \ 78 | --csv=tests/load_test/.results/results \ 79 | --html=tests/load_test/.results/report.html 80 | ``` 81 | 82 | This command initiates a 30-second load test, simulating 2 users spawning per second, reaching a maximum of 10 concurrent users. 83 | {%- endif %} 84 | 85 | -------------------------------------------------------------------------------- /tests/fixtures/makefile_snapshots/langgraph_cloud_run_no_data.makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Installation & Setup 3 | # ============================================================================== 4 | 5 | # Install dependencies using uv package manager 6 | install: 7 | @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.8.13/install.sh | sh; source $HOME/.local/bin/env; } 8 | uv sync --dev --extra streamlit 9 | 10 | # ============================================================================== 11 | # Playground Targets 12 | # ============================================================================== 13 | 14 | # Launch local dev playground 15 | playground: 16 | @echo "===============================================================================" 17 | @echo "| 🚀 Starting your agent playground... |" 18 | @echo "| |" 19 | @echo "| 💡 Try asking: How can you help?|" 20 | @echo "===============================================================================" 21 | uv run uvicorn test_langgraph.server:app --host localhost --port 8000 --reload & 22 | uv run streamlit run frontend/streamlit_app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false 23 | 24 | # ============================================================================== 25 | # Backend Deployment Targets 26 | # ============================================================================== 27 | 28 | # Deploy the agent remotely 29 | # Usage: make backend [IAP=true] [PORT=8080] - Set IAP=true to enable Identity-Aware Proxy, PORT to specify container port 30 | backend: 31 | PROJECT_ID=$$(gcloud config get-value project) && \ 32 | gcloud beta run deploy test-langgraph \ 33 | --source . \ 34 | --memory "4Gi" \ 35 | --project $$PROJECT_ID \ 36 | --region "us-central1" \ 37 | --no-allow-unauthenticated \ 38 | --no-cpu-throttling \ 39 | --labels "" \ 40 | --set-env-vars \ 41 | "COMMIT_SHA=$(shell git rev-parse HEAD)" \ 42 | $(if $(IAP),--iap) \ 43 | $(if $(PORT),--port=$(PORT)) 44 | 45 | 46 | # ============================================================================== 47 | # Infrastructure Setup 48 | # ============================================================================== 49 | 50 | # Set up development environment resources using Terraform 51 | setup-dev-env: 52 | PROJECT_ID=$$(gcloud config get-value project) && \ 53 | (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve) 54 | 55 | # ============================================================================== 56 | # Testing & Code Quality 57 | # ============================================================================== 58 | 59 | # Run unit and integration tests 60 | test: 61 | uv run pytest tests/unit && uv run pytest tests/integration 62 | 63 | # Run code quality checks (codespell, ruff, mypy) 64 | lint: 65 | uv sync --dev --extra lint 66 | uv run codespell 67 | uv run ruff check . --diff 68 | uv run ruff format . --check --diff 69 | uv run mypy . 70 | -------------------------------------------------------------------------------- /agent_starter_pack/base_template/deployment/terraform/log_sinks.tf: -------------------------------------------------------------------------------- 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 | resource "google_project_iam_member" "bigquery_data_editor" { 16 | for_each = local.deploy_project_ids 17 | 18 | project = each.value 19 | role = "roles/bigquery.dataEditor" 20 | member = module.log_export_to_bigquery[each.key].writer_identity 21 | } 22 | 23 | resource "google_bigquery_dataset" "feedback_dataset" { 24 | for_each = local.deploy_project_ids 25 | project = each.value 26 | dataset_id = replace("${var.project_name}_feedback", "-", "_") 27 | friendly_name = "${var.project_name}_feedback" 28 | location = var.region 29 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 30 | } 31 | 32 | resource "google_bigquery_dataset" "telemetry_logs_dataset" { 33 | for_each = local.deploy_project_ids 34 | project = each.value 35 | dataset_id = replace("${var.project_name}_telemetry", "-", "_") 36 | friendly_name = "${var.project_name}_telemetry" 37 | location = var.region 38 | depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services] 39 | } 40 | 41 | module "log_export_to_bigquery" { 42 | for_each = local.deploy_project_ids 43 | 44 | source = "terraform-google-modules/log-export/google" 45 | version = "10.0.0" 46 | 47 | log_sink_name = "${var.project_name}_telemetry" 48 | parent_resource_type = "project" 49 | parent_resource_id = each.value 50 | destination_uri = "bigquery.googleapis.com/projects/${each.value}/datasets/${google_bigquery_dataset.telemetry_logs_dataset[each.key].dataset_id}" 51 | filter = var.telemetry_logs_filter 52 | bigquery_options = { use_partitioned_tables = true } 53 | unique_writer_identity = true 54 | depends_on = [google_bigquery_dataset.telemetry_logs_dataset] 55 | } 56 | 57 | module "feedback_export_to_bigquery" { 58 | for_each = local.deploy_project_ids 59 | 60 | source = "terraform-google-modules/log-export/google" 61 | version = "10.0.0" 62 | log_sink_name = "${var.project_name}_feedback" 63 | parent_resource_type = "project" 64 | parent_resource_id = each.value 65 | destination_uri = "bigquery.googleapis.com/projects/${each.value}/datasets/${google_bigquery_dataset.feedback_dataset[each.key].dataset_id}" 66 | filter = var.feedback_logs_filter 67 | bigquery_options = { use_partitioned_tables = true } 68 | unique_writer_identity = true 69 | depends_on = [google_bigquery_dataset.feedback_dataset] 70 | } 71 | -------------------------------------------------------------------------------- /agent_starter_pack/cli/utils/version.py: -------------------------------------------------------------------------------- 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 | """Version checking utilities for the CLI.""" 16 | 17 | import logging 18 | from importlib.metadata import PackageNotFoundError, version 19 | 20 | import requests 21 | from packaging import version as pkg_version 22 | from rich.console import Console 23 | 24 | console = Console() 25 | 26 | PACKAGE_NAME = "agent-starter-pack" 27 | 28 | 29 | def get_current_version() -> str: 30 | """Get the current installed version of the package.""" 31 | try: 32 | return version(PACKAGE_NAME) 33 | except PackageNotFoundError: 34 | # For development environments where package isn't installed 35 | return "0.0.0" # Default if version can't be determined 36 | 37 | 38 | def get_latest_version() -> str: 39 | """Get the latest version available on PyPI.""" 40 | try: 41 | response = requests.get(f"https://pypi.org/pypi/{PACKAGE_NAME}/json", timeout=2) 42 | if response.status_code == 200: 43 | return response.json()["info"]["version"] 44 | return "0.0.0" 45 | except Exception: 46 | return "0.0.0" # Default if PyPI can't be reached 47 | 48 | 49 | def check_for_updates() -> tuple[bool, str, str]: 50 | """Check if a newer version of the package is available. 51 | 52 | Returns: 53 | Tuple of (needs_update, current_version, latest_version) 54 | """ 55 | current = get_current_version() 56 | latest = get_latest_version() 57 | 58 | needs_update = pkg_version.parse(latest) > pkg_version.parse(current) 59 | 60 | return needs_update, current, latest 61 | 62 | 63 | def display_update_message() -> None: 64 | """Check for updates and display a message if an update is available.""" 65 | try: 66 | needs_update, current, latest = check_for_updates() 67 | 68 | if needs_update: 69 | console.print( 70 | f"\n[yellow]⚠️ Update available: {current} → {latest}[/]", 71 | highlight=False, 72 | ) 73 | console.print( 74 | f"[yellow]Run `pip install --upgrade {PACKAGE_NAME}` to update.", 75 | highlight=False, 76 | ) 77 | console.print( 78 | f"[yellow]Or, if you used pipx: `pipx upgrade {PACKAGE_NAME}`", 79 | highlight=False, 80 | ) 81 | console.print( 82 | f"[yellow]Or, if you used uv: `uv pip install --upgrade {PACKAGE_NAME}`", 83 | highlight=False, 84 | ) 85 | except Exception as e: 86 | # Don't let version checking errors affect the CLI 87 | logging.debug(f"Error checking for updates: {e}") 88 | -------------------------------------------------------------------------------- /tests/fixtures/makefile_snapshots/adk_base_cloud_run_no_data.makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Installation & Setup 3 | # ============================================================================== 4 | 5 | # Install dependencies using uv package manager 6 | install: 7 | @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.8.13/install.sh | sh; source $HOME/.local/bin/env; } 8 | uv sync --dev 9 | 10 | # ============================================================================== 11 | # Playground Targets 12 | # ============================================================================== 13 | 14 | # Launch local dev playground 15 | playground: 16 | @echo "===============================================================================" 17 | @echo "| 🚀 Starting your agent playground... |" 18 | @echo "| |" 19 | @echo "| 💡 Try asking: What can you help me with?|" 20 | @echo "| |" 21 | @echo "| 🔍 IMPORTANT: Select the 'test_adk_base' folder to interact with your agent. |" 22 | @echo "===============================================================================" 23 | uv run adk web . --port 8501 --reload_agents 24 | 25 | # ============================================================================== 26 | # Backend Deployment Targets 27 | # ============================================================================== 28 | 29 | # Deploy the agent remotely 30 | # Usage: make backend [IAP=true] [PORT=8080] - Set IAP=true to enable Identity-Aware Proxy, PORT to specify container port 31 | backend: 32 | PROJECT_ID=$$(gcloud config get-value project) && \ 33 | gcloud beta run deploy test-adk-base \ 34 | --source . \ 35 | --memory "4Gi" \ 36 | --project $$PROJECT_ID \ 37 | --region "us-central1" \ 38 | --no-allow-unauthenticated \ 39 | --no-cpu-throttling \ 40 | --labels "created-by=adk" \ 41 | --set-env-vars \ 42 | "COMMIT_SHA=$(shell git rev-parse HEAD)" \ 43 | $(if $(IAP),--iap) \ 44 | $(if $(PORT),--port=$(PORT)) 45 | 46 | 47 | # ============================================================================== 48 | # Infrastructure Setup 49 | # ============================================================================== 50 | 51 | # Set up development environment resources using Terraform 52 | setup-dev-env: 53 | PROJECT_ID=$$(gcloud config get-value project) && \ 54 | (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve) 55 | 56 | # ============================================================================== 57 | # Testing & Code Quality 58 | # ============================================================================== 59 | 60 | # Run unit and integration tests 61 | test: 62 | uv run pytest tests/unit && uv run pytest tests/integration 63 | 64 | # Run code quality checks (codespell, ruff, mypy) 65 | lint: 66 | uv sync --dev --extra lint 67 | uv run codespell 68 | uv run ruff check . --diff 69 | uv run ruff format . --check --diff 70 | uv run mypy . 71 | -------------------------------------------------------------------------------- /tests/cli/utils/test_cicd.py: -------------------------------------------------------------------------------- 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 | """Tests for CI/CD utility functions.""" 16 | 17 | from unittest.mock import MagicMock, patch 18 | 19 | import pytest 20 | from cli.utils.cicd import ProjectConfig, print_cicd_summary, run_command 21 | 22 | 23 | @pytest.fixture 24 | def mock_console() -> MagicMock: 25 | """Mock console for testing output""" 26 | with patch("cli.utils.cicd.console") as mock: 27 | yield mock 28 | 29 | 30 | @pytest.fixture 31 | def mock_run_command() -> MagicMock: 32 | """Mock run_command function""" 33 | with patch("agent_starter_pack.cli.utils.cicd.run_command") as mock: 34 | yield mock 35 | 36 | 37 | def test_project_config() -> None: 38 | """Test ProjectConfig initialization with minimal required fields""" 39 | config = ProjectConfig( 40 | staging_project_id="test-staging", 41 | prod_project_id="test-prod", 42 | cicd_project_id="test-cicd", 43 | agent="test-agent", 44 | deployment_target="cloud-run", 45 | repository_name="test-repo", 46 | repository_owner="test-owner", 47 | dev_project_id="test-dev", 48 | ) 49 | 50 | assert config.dev_project_id == "test-dev" 51 | assert config.region == "us-central1" # default value 52 | assert config.git_provider == "github" # default value 53 | 54 | 55 | def test_print_cicd_summary(mock_console: MagicMock) -> None: 56 | """Test CICD summary printing""" 57 | config = ProjectConfig( 58 | staging_project_id="test-staging", 59 | prod_project_id="test-prod", 60 | cicd_project_id="test-cicd", 61 | agent="test-agent", 62 | deployment_target="cloud-run", 63 | repository_name="test-repo", 64 | repository_owner="test-owner", 65 | dev_project_id="test-dev", 66 | ) 67 | 68 | print_cicd_summary( 69 | config=config, 70 | github_username="test-user", 71 | repo_url="https://github.com/test-user/test-repo", 72 | cloud_build_url="https://console.cloud.google.com/cloud-build/builds?project=test-cicd", 73 | ) 74 | 75 | # Verify specific expected messages were printed 76 | assert mock_console.print.call_count > 0 77 | 78 | 79 | def test_run_command(capsys: pytest.CaptureFixture) -> None: 80 | """Test run_command output formatting""" 81 | with patch("subprocess.run") as mock_run: 82 | mock_run.return_value = MagicMock(returncode=0, stdout="test output", stderr="") 83 | 84 | result = run_command(["test", "command"], capture_output=True) 85 | 86 | captured = capsys.readouterr() 87 | assert "🔄 Running command: test command" in captured.out 88 | assert result.stdout == "test output" 89 | -------------------------------------------------------------------------------- /docs/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # 🚀 Getting Started 2 | 3 | This guide quickly walks you through setting up your first agent project. 4 | 5 | **Want zero setup?** 👉 [Try in Firebase Studio](https://studio.firebase.google.com/new?template=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fagent-starter-pack%2Ftree%2Fmain%2Fsrc%2Fresources%2Fidx) or in [Cloud Shell](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Feliasecchig%2Fasp-open-in-cloud-shell&cloudshell_print=open-in-cs) 6 | 7 | ### Prerequisites 8 | 9 | **Python 3.10+** | **Google Cloud SDK** [Install Guide](https://cloud.google.com/sdk/docs/install) | **Terraform** [Install Guide](https://developer.hashicorp.com/terraform/downloads) | **`uv` (Optional, Recommended)** [Install Guide](https://docs.astral.sh/uv/getting-started/installation/) 10 | 11 | ### 1. Create Your Agent Project 12 | 13 | You can use the `pip` workflow for a traditional setup, or `uvx` to create a project in a single command without a permanent install. Choose your preferred method below. 14 | 15 | ::: code-group 16 | 17 | ```bash [pip] 18 | # 1. Create and activate a virtual environment 19 | python -m venv .venv 20 | source .venv/bin/activate 21 | 22 | # 2. Install the package 23 | pip install agent-starter-pack 24 | 25 | # 3. Run the create command 26 | agent-starter-pack create my-awesome-agent 27 | ``` 28 | 29 | ```bash [⚡ uvx] 30 | # This single command downloads and runs the latest version 31 | uvx agent-starter-pack create my-awesome-agent 32 | ``` 33 | 34 | ::: 35 | 36 | No matter which method you choose, the `create` command will: 37 | * Let you choose an agent template (e.g., `adk_base`, `agentic_rag`). 38 | * Let you select a deployment target (e.g., `cloud_run`, `agent_engine`). 39 | * Generate a complete project structure (backend, optional frontend, deployment infra). 40 | 41 | **Examples:** 42 | 43 | ```bash 44 | # You can also pass flags to skip the prompts 45 | agent-starter-pack create my-adk-agent -a adk_base -d agent_engine 46 | ``` 47 | 48 | ### 2. Explore and Run Locally 49 | 50 | Now, navigate into your new project and run its setup commands. 51 | 52 | ```bash 53 | cd my-awesome-agent && make install && make playground 54 | ``` 55 | 56 | Inside your new project directory (`my-awesome-agent`), you'll find: 57 | 58 | * `app/`: Backend agent code (or custom directory name if configured). 59 | * `deployment/`: Terraform infrastructure code. 60 | * `tests/`: Unit and integration tests for your agent. 61 | * `notebooks/`: Jupyter notebooks for getting started with evaluation. 62 | * `frontend/`: (If applicable) Web UI for interacting with your agent. 63 | * `README.md`: **Project-specific instructions for running locally and deploying.** 64 | 65 | ➡️ **Follow the instructions in *your new project's* `README.md` to run it locally.** 66 | 67 | ### Next Steps 68 | 69 | You're ready to go! See the [Development Guide](/guide/development-guide) for detailed instructions on extending, customizing and deploying your agent. 70 | 71 | - **Add Data (RAG):** Configure [Data Ingestion](/guide/data-ingestion) for knowledge-based agents. 72 | - **Monitor Performance:** Explore [Observability](/guide/observability) features for production monitoring. 73 | - **Deploy to Production:** Follow the [Deployment Guide](/guide/deployment) to deploy your agent to Google Cloud. -------------------------------------------------------------------------------- /docs/guide/data-ingestion.md: -------------------------------------------------------------------------------- 1 | # Data Ingestion Pipeline for RAG 2 | 3 | The Agent Starter Pack simplifies incorporating data ingestion into your agent projects. This is especially useful for agents requiring document processing and retrieval, such as Retrieval Augmented Generation (RAG) applications. 4 | 5 | ## Overview 6 | 7 | Data ingestion automates: 8 | 9 | - Loading data from various sources. 10 | - Processing and chunking documents. 11 | - Generating embeddings with Vertex AI. 12 | - Storing processed data and embeddings in **Vertex AI Search** or **Vertex AI Vector Search**. 13 | - Scheduling periodic data updates. 14 | 15 | ## When to Include Data Ingestion 16 | 17 | Consider data ingestion if: 18 | 19 | - Your agent needs to search or reference extensive documentation. 20 | - You're developing a RAG-based application. 21 | - Your agent's knowledge base requires periodic updates. 22 | - You want to keep your agent's content fresh and searchable. 23 | 24 | ## Usage 25 | 26 | ### Project Creation 27 | 28 | Include data ingestion during project creation in two ways: 29 | 30 | 1. **Automatic Inclusion**: Some agents (e.g., those designed for RAG like `agentic_rag`) automatically include it due to their nature. You will be prompted to select a datastore (`vertex_ai_search` or `vertex_ai_vector_search`) if not specified. 31 | 32 | 2. **Optional Inclusion**: For other agents, add it using the `--include-data-ingestion` flag and specify the desired datastore with `--datastore` (or `-ds`): 33 | 34 | ```bash 35 | # Using Vertex AI Search 36 | agent-starter-pack create my-agent-project --include-data-ingestion -ds vertex_ai_search 37 | 38 | # Using Vertex AI Vector Search 39 | agent-starter-pack create my-agent-project --include-data-ingestion -ds vertex_ai_vector_search 40 | ``` 41 | If `--datastore` is omitted when `--include-data-ingestion` is used, you will be prompted to choose one. 42 | 43 | ### Infrastructure Setup 44 | 45 | The Terraform IaC configures the necessary infrastructure based on your chosen datastore: 46 | 47 | - **Vertex AI Search**: Datastores. 48 | - **Vertex AI Vector Search**: Indexes, Index Endpoints, and Buckets for staging data. 49 | - Necessary service accounts and permissions. 50 | - Storage buckets for pipeline artifacts. 51 | - BigQuery datasets (if applicable). 52 | 53 | ## Getting Started 54 | 55 | 1. Create your project with data ingestion, specifying your datastore: 56 | 57 | ```bash 58 | # Example with Vertex AI Search 59 | agent-starter-pack create my-project -ds vertex_ai_search 60 | 61 | # Example with Vertex AI Vector Search 62 | agent-starter-pack create my-project -ds vertex_ai_vector_search 63 | ``` 64 | 65 | 2. Follow the setup instructions in the generated `data_ingestion/README.md`. Deploy the Terraform infrastructure (at least in your development project) before running the data pipeline. 66 | 67 | ## Learn More 68 | 69 | - [Vertex AI Pipelines](https://cloud.google.com/vertex-ai/docs/pipelines/introduction) for pipeline management. 70 | - [Vertex AI Search documentation](https://cloud.google.com/generative-ai-app-builder/docs/enterprise-search-introduction) for search capabilities. 71 | - [Vertex AI Vector Search documentation](https://cloud.google.com/vertex-ai/docs/vector-search/overview) for vector database capabilities. 72 | -------------------------------------------------------------------------------- /tests/fixtures/makefile_snapshots/agent_with_agent_garden.makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # Installation & Setup 3 | # ============================================================================== 4 | 5 | # Install dependencies using uv package manager 6 | install: 7 | @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.8.13/install.sh | sh; source $HOME/.local/bin/env; } 8 | uv sync --dev 9 | 10 | # ============================================================================== 11 | # Playground Targets 12 | # ============================================================================== 13 | 14 | # Launch local dev playground 15 | playground: 16 | @echo "===============================================================================" 17 | @echo "| 🚀 Starting your agent playground... |" 18 | @echo "| |" 19 | @echo "| 💡 Try asking: Agent garden question|" 20 | @echo "| |" 21 | @echo "| 🔍 IMPORTANT: Select the 'test_garden' folder to interact with your agent. |" 22 | @echo "===============================================================================" 23 | uv run adk web . --port 8501 --reload_agents 24 | 25 | # ============================================================================== 26 | # Backend Deployment Targets 27 | # ============================================================================== 28 | 29 | # Deploy the agent remotely 30 | # Usage: make backend [IAP=true] [PORT=8080] - Set IAP=true to enable Identity-Aware Proxy, PORT to specify container port 31 | backend: 32 | PROJECT_ID=$$(gcloud config get-value project) && \ 33 | gcloud beta run deploy test-garden \ 34 | --source . \ 35 | --memory "4Gi" \ 36 | --project $$PROJECT_ID \ 37 | --region "us-central1" \ 38 | --no-allow-unauthenticated \ 39 | --no-cpu-throttling \ 40 | --labels "created-by=adk,deployed-with=agent-garden,vertex-agent-sample-id=sample-123,vertex-agent-sample-publisher=google" \ 41 | --set-env-vars \ 42 | "COMMIT_SHA=$(shell git rev-parse HEAD)" \ 43 | $(if $(IAP),--iap) \ 44 | $(if $(PORT),--port=$(PORT)) 45 | 46 | 47 | # ============================================================================== 48 | # Infrastructure Setup 49 | # ============================================================================== 50 | 51 | # Set up development environment resources using Terraform 52 | setup-dev-env: 53 | PROJECT_ID=$$(gcloud config get-value project) && \ 54 | (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve) 55 | 56 | # ============================================================================== 57 | # Testing & Code Quality 58 | # ============================================================================== 59 | 60 | # Run unit and integration tests 61 | test: 62 | uv run pytest tests/unit && uv run pytest tests/integration 63 | 64 | # Run code quality checks (codespell, ruff, mypy) 65 | lint: 66 | uv sync --dev --extra lint 67 | uv run codespell 68 | uv run ruff check . --diff 69 | uv run ruff format . --check --diff 70 | uv run mypy . 71 | --------------------------------------------------------------------------------