From fa717ad8f09a819240ca4a7b98f44c704d65e71e Mon Sep 17 00:00:00 2001 From: Salman Chishti Date: Wed, 17 Dec 2025 09:37:29 -0800 Subject: [PATCH 1/5] fix: Upgrade GitHub Actions to latest versions Merge https://github.com/google/adk-python/pull/3933 ## Summary Upgrade GitHub Actions to their latest versions for improved features, bug fixes, and security updates. ## Changes | Action | Old Version(s) | New Version | Release | Files | |--------|---------------|-------------|---------|-------| | `google-github-actions/auth` | [`v2`](https://github.com/google-github-actions/auth/releases/tag/v2) | [`v3`](https://github.com/google-github-actions/auth/releases/tag/v3) | [Release](https://github.com/google-github-actions/auth/releases/tag/v3) | discussion_answering.yml, upload-adk-docs-to-vertex-ai-search.yml | ## Why upgrade? Keeping GitHub Actions up to date ensures: - **Security**: Latest security patches and fixes - **Features**: Access to new functionality and improvements - **Compatibility**: Better support for current GitHub features - **Performance**: Optimizations and efficiency improvements ### Security Note Actions that were previously pinned to commit SHAs remain pinned to SHAs (updated to the latest release SHA) to maintain the security benefits of immutable references. ### Testing These changes only affect CI/CD workflow configurations and should not impact application functionality. The workflows should be tested by running them on a branch before merging. Co-authored-by: Xiang (Sean) Zhou COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3933 from salmanmkc:upgrade-github-actions-node24-general 142ef77d94da42b0f75a1fc810e8deeb666684a4 PiperOrigin-RevId: 845804209 --- .github/workflows/discussion_answering.yml | 2 +- .github/workflows/upload-adk-docs-to-vertex-ai-search.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/discussion_answering.yml b/.github/workflows/discussion_answering.yml index d9bfffc361..431ae3db8d 100644 --- a/.github/workflows/discussion_answering.yml +++ b/.github/workflows/discussion_answering.yml @@ -24,7 +24,7 @@ jobs: - name: Authenticate to Google Cloud id: auth - uses: 'google-github-actions/auth@v2' + uses: 'google-github-actions/auth@v3' with: credentials_json: '${{ secrets.ADK_GCP_SA_KEY }}' diff --git a/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml b/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml index bce7598c2f..1529aaaf7a 100644 --- a/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml +++ b/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml @@ -28,7 +28,7 @@ jobs: - name: Authenticate to Google Cloud id: auth - uses: 'google-github-actions/auth@v2' + uses: 'google-github-actions/auth@v3' with: credentials_json: '${{ secrets.ADK_GCP_SA_KEY }}' From 1add41e1609d8d31913d4f73fa97be044fcef2e0 Mon Sep 17 00:00:00 2001 From: Salman Chishti Date: Wed, 17 Dec 2025 10:01:02 -0800 Subject: [PATCH 2/5] fix: Upgrade GitHub Actions for Node 24 compatibility Merge https://github.com/google/adk-python/pull/3932 ## Summary Upgrade GitHub Actions to their latest versions to ensure compatibility with Node 24, as Node 20 will reach end-of-life in April 2026. ## Changes | Action | Old Version(s) | New Version | Release | Files | |--------|---------------|-------------|---------|-------| | `actions/checkout` | [`v5`](https://github.com/actions/checkout/releases/tag/v5) | [`v6`](https://github.com/actions/checkout/releases/tag/v6) | [Release](https://github.com/actions/checkout/releases/tag/v6) | analyze-releases-for-adk-docs-updates.yml, check-file-contents.yml, discussion_answering.yml, isort.yml, pr-triage.yml, pyink.yml, python-unit-tests.yml, stale-bot.yml, triage.yml, upload-adk-docs-to-vertex-ai-search.yml | ## Context Per [GitHub's announcement](https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/), Node 20 is being deprecated and runners will begin using Node 24 by default starting March 4th, 2026. ### Why this matters - **Node 20 EOL**: April 2026 - **Node 24 default**: March 4th, 2026 - **Action**: Update to latest action versions that support Node 24 ### Security Note Actions that were previously pinned to commit SHAs remain pinned to SHAs (updated to the latest release SHA) to maintain the security benefits of immutable references. ### Testing These changes only affect CI/CD workflow configurations and should not impact application functionality. The workflows should be tested by running them on a branch before merging. Co-authored-by: Xiang (Sean) Zhou COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3932 from salmanmkc:upgrade-github-actions-node24 0ffbb0b7b5f63d27583f8c24781f2d3ca92c0c23 PiperOrigin-RevId: 845813166 --- .github/workflows/analyze-releases-for-adk-docs-updates.yml | 2 +- .github/workflows/check-file-contents.yml | 2 +- .github/workflows/discussion_answering.yml | 2 +- .github/workflows/isort.yml | 2 +- .github/workflows/pr-triage.yml | 2 +- .github/workflows/pyink.yml | 2 +- .github/workflows/python-unit-tests.yml | 2 +- .github/workflows/stale-bot.yml | 2 +- .github/workflows/triage.yml | 2 +- .github/workflows/upload-adk-docs-to-vertex-ai-search.yml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/analyze-releases-for-adk-docs-updates.yml b/.github/workflows/analyze-releases-for-adk-docs-updates.yml index 21414ae534..d7016fb702 100644 --- a/.github/workflows/analyze-releases-for-adk-docs-updates.yml +++ b/.github/workflows/analyze-releases-for-adk-docs-updates.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 diff --git a/.github/workflows/check-file-contents.yml b/.github/workflows/check-file-contents.yml index bb575e0f20..6c02d904c7 100644 --- a/.github/workflows/check-file-contents.yml +++ b/.github/workflows/check-file-contents.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 2 diff --git a/.github/workflows/discussion_answering.yml b/.github/workflows/discussion_answering.yml index 431ae3db8d..97116d485e 100644 --- a/.github/workflows/discussion_answering.yml +++ b/.github/workflows/discussion_answering.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 diff --git a/.github/workflows/isort.yml b/.github/workflows/isort.yml index b8b24da5ce..a1967b1f53 100644 --- a/.github/workflows/isort.yml +++ b/.github/workflows/isort.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 2 diff --git a/.github/workflows/pr-triage.yml b/.github/workflows/pr-triage.yml index 55b088b505..6557820f04 100644 --- a/.github/workflows/pr-triage.yml +++ b/.github/workflows/pr-triage.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 diff --git a/.github/workflows/pyink.yml b/.github/workflows/pyink.yml index 0822757fa0..bcd872bda8 100644 --- a/.github/workflows/pyink.yml +++ b/.github/workflows/pyink.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 2 diff --git a/.github/workflows/python-unit-tests.yml b/.github/workflows/python-unit-tests.yml index 3fc6bd943f..a19e893469 100644 --- a/.github/workflows/python-unit-tests.yml +++ b/.github/workflows/python-unit-tests.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml index 6948b56459..2e74e5e51f 100644 --- a/.github/workflows/stale-bot.yml +++ b/.github/workflows/stale-bot.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 46153f413a..d19a0e9197 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 diff --git a/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml b/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml index 1529aaaf7a..e8d94eb9dc 100644 --- a/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml +++ b/.github/workflows/upload-adk-docs-to-vertex-ai-search.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Clone adk-docs repository run: git clone https://github.com/google/adk-docs.git /tmp/adk-docs From c6f389d4bc4d2b91795003a3bd87ed1f1b854493 Mon Sep 17 00:00:00 2001 From: George Weale Date: Wed, 17 Dec 2025 11:25:12 -0800 Subject: [PATCH 3/5] fix: Refine Ollama content flattening and provider checks - Stripping whitespace from custom LLM provider and model names when checking for "ollama_chat". - Enhancing `_flatten_ollama_content` to correctly handle content that is None, a string, a dictionary, or an iterable (like a tuple) of content blocks, not just lists. This aligns with LiteLLM's `OpenAIMessageContent` type being an `Iterable`. Close #3928 Co-authored-by: George Weale PiperOrigin-RevId: 845848017 --- src/google/adk/models/lite_llm.py | 28 ++++++++++++++++++++------ tests/unittests/models/test_litellm.py | 11 ++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/google/adk/models/lite_llm.py b/src/google/adk/models/lite_llm.py index aca230bc57..57c7c93029 100644 --- a/src/google/adk/models/lite_llm.py +++ b/src/google/adk/models/lite_llm.py @@ -628,9 +628,12 @@ def _is_ollama_chat_provider( model: Optional[str], custom_llm_provider: Optional[str] ) -> bool: """Returns True when requests should be normalized for ollama_chat.""" - if custom_llm_provider and custom_llm_provider.lower() == "ollama_chat": + if ( + custom_llm_provider + and custom_llm_provider.strip().lower() == "ollama_chat" + ): return True - if model and model.lower().startswith("ollama_chat"): + if model and model.strip().lower().startswith("ollama_chat"): return True return False @@ -644,11 +647,24 @@ def _flatten_ollama_content( join them with newlines, and fall back to a JSON string for non-text content. If both text and non-text parts are present, only the text parts are kept. """ - if not isinstance(content, list): + if content is None or isinstance(content, str): return content + # `OpenAIMessageContent` is typed as `Iterable[...]` in LiteLLM. Some + # providers or LiteLLM versions may hand back tuples or other iterables. + if isinstance(content, dict): + try: + return json.dumps(content) + except TypeError: + return str(content) + + try: + blocks = list(content) + except TypeError: + return str(content) + text_parts = [] - for block in content: + for block in blocks: if isinstance(block, dict) and block.get("type") == "text": text_value = block.get("text") if text_value: @@ -658,9 +674,9 @@ def _flatten_ollama_content( return _NEW_LINE.join(text_parts) try: - return json.dumps(content) + return json.dumps(blocks) except TypeError: - return str(content) + return str(blocks) def _normalize_ollama_chat_messages( diff --git a/tests/unittests/models/test_litellm.py b/tests/unittests/models/test_litellm.py index 54b0f176f6..a7fe91d0df 100644 --- a/tests/unittests/models/test_litellm.py +++ b/tests/unittests/models/test_litellm.py @@ -1549,6 +1549,17 @@ async def test_generate_content_async_custom_provider_flattens_content( assert "Describe this image." in message_content +def test_flatten_ollama_content_accepts_tuple_blocks(): + from google.adk.models.lite_llm import _flatten_ollama_content + + content = ( + {"type": "text", "text": "first"}, + {"type": "text", "text": "second"}, + ) + flattened = _flatten_ollama_content(content) + assert flattened == "first\nsecond" + + @pytest.mark.asyncio async def test_content_to_message_param_user_message(): content = types.Content( From e3bac1ab8c724454fb433cc7e78416b61efe33ee Mon Sep 17 00:00:00 2001 From: George Weale Date: Wed, 17 Dec 2025 11:35:50 -0800 Subject: [PATCH 4/5] fix: Built-in agents (names starting with "__") now use in-memory session storage instead of creating .adk folders in the agents directory Co-authored-by: George Weale PiperOrigin-RevId: 845852695 --- src/google/adk/cli/utils/local_storage.py | 12 ++++++++++++ tests/unittests/cli/utils/test_local_storage.py | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/google/adk/cli/utils/local_storage.py b/src/google/adk/cli/utils/local_storage.py index 6fb6a83ed0..12207e8070 100644 --- a/src/google/adk/cli/utils/local_storage.py +++ b/src/google/adk/cli/utils/local_storage.py @@ -34,6 +34,8 @@ logger = logging.getLogger("google_adk." + __name__) +_BUILT_IN_SESSION_SERVICE_KEY = "__adk_built_in_session_service__" + def create_local_database_session_service( *, @@ -124,6 +126,16 @@ def __init__( async def _get_service(self, app_name: str) -> BaseSessionService: async with self._service_lock: + if app_name.startswith("__"): + service = self._services.get(_BUILT_IN_SESSION_SERVICE_KEY) + if service is not None: + return service + service = create_local_database_session_service( + base_dir=self._agents_root, + ) + self._services[_BUILT_IN_SESSION_SERVICE_KEY] = service + return service + storage_name = self._app_name_to_dir.get(app_name, app_name) service = self._services.get(storage_name) if service is not None: diff --git a/tests/unittests/cli/utils/test_local_storage.py b/tests/unittests/cli/utils/test_local_storage.py index 39bce7a58b..bb922a5838 100644 --- a/tests/unittests/cli/utils/test_local_storage.py +++ b/tests/unittests/cli/utils/test_local_storage.py @@ -72,6 +72,18 @@ async def test_per_agent_session_service_respects_app_name_alias( assert (tmp_path / folder_name / ".adk" / "session.db").exists() +@pytest.mark.asyncio +async def test_per_agent_session_service_routes_built_in_agents_to_root_dot_adk( + tmp_path: Path, +) -> None: + service = PerAgentDatabaseSessionService(agents_root=tmp_path) + + await service.create_session(app_name="__helper", user_id="user") + + assert not (tmp_path / "__helper").exists() + assert (tmp_path / ".adk" / "session.db").exists() + + def test_create_local_database_session_service_returns_sqlite( tmp_path: Path, ) -> None: From 78c96e99ff82962b9d6b5ab6a0ff25168e55e372 Mon Sep 17 00:00:00 2001 From: Kathy Wu Date: Wed, 17 Dec 2025 12:59:50 -0800 Subject: [PATCH 5/5] fix: update Api Registry Agent prompt to be more specific and give it the gcloud project id Co-authored-by: Kathy Wu PiperOrigin-RevId: 845884290 --- contributing/samples/api_registry_agent/agent.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/contributing/samples/api_registry_agent/agent.py b/contributing/samples/api_registry_agent/agent.py index 6504822092..4a36e907a8 100644 --- a/contributing/samples/api_registry_agent/agent.py +++ b/contributing/samples/api_registry_agent/agent.py @@ -32,8 +32,19 @@ root_agent = LlmAgent( model="gemini-2.0-flash", name="bigquery_assistant", - instruction=""" -Help user access their BigQuery data via API Registry tools. + instruction=f""" +You are a helpful data analyst assistant with access to BigQuery. The project ID is: {PROJECT_ID} + +When users ask about data: +- Use the project ID {PROJECT_ID} when calling BigQuery tools. +- First, explore available datasets and tables to understand what data exists. +- Check table schemas to understand the structure before querying. +- Write clear, efficient SQL queries to answer their questions. +- Explain your findings in simple, non-technical language. + +Mandatory Requirements: +- Always use the BigQuery tools to fetch real data rather than making assumptions. +- For all BigQuery operations, use project_id: {PROJECT_ID}. """, tools=[registry_tools], )