From c9094addf839866cac20b5057b0a883050daeb9c Mon Sep 17 00:00:00 2001 From: sarojrout Date: Thu, 27 Nov 2025 09:42:45 -0800 Subject: [PATCH 1/2] feat(runners): Allow app_name to override app.name when both provided This change enables Agent Engine deployments to use App objects with event compaction and context caching configs while using the Agent Engine resource name for session operations, rather than App.name. - Allow app_name parameter to override app.name when both are provided - Still error when app and agent are both provided (prevents confusion) - Updated tests to reflect new behavior and added test for override case - Updateed documentation to clarify the new usage pattern This fixes the issue where App.name (a simple identifier) conflicts with Agent Engine's requirement for resource names in session creation. Related to issue #3715 --- src/google/adk/runners.py | 33 +++++++++++++++++++-------------- tests/unittests/test_runners.py | 20 ++++++++++++++++---- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/google/adk/runners.py b/src/google/adk/runners.py index db9828f66e..aae1c12819 100644 --- a/src/google/adk/runners.py +++ b/src/google/adk/runners.py @@ -121,15 +121,21 @@ def __init__( """Initializes the Runner. Developers should provide either an `app` instance or both `app_name` and - `agent`. Providing a mix of `app` and `app_name`/`agent` will result in a - `ValueError`. Providing `app` is the recommended way to create a runner. + `agent`. When `app` is provided, `app_name` can optionally override the + app's name (useful for deployment scenarios like Agent Engine where the + resource name differs from the app's identifier). However, `agent` should + not be provided when `app` is provided. Providing `app` is the recommended + way to create a runner. Args: - app: An optional `App` instance. If provided, `app_name` and `agent` - should not be specified. + app: An optional `App` instance. If provided, `agent` should not be + specified. `app_name` can optionally override `app.name`. app_name: The application name of the runner. Required if `app` is not - provided. - agent: The root agent to run. Required if `app` is not provided. + provided. If `app` is provided, this can optionally override `app.name` + (e.g., for deployment scenarios where a resource name differs from the + app identifier). + agent: The root agent to run. Required if `app` is not provided. Should + not be provided when `app` is provided. plugins: Deprecated. A list of plugins for the runner. Please use the `app` argument to provide plugins instead. artifact_service: The artifact service for the runner. @@ -139,8 +145,8 @@ def __init__( plugin_close_timeout: The timeout in seconds for plugin close methods. Raises: - ValueError: If `app` is provided along with `app_name` or `plugins`, or - if `app` is not provided but either `app_name` or `agent` is missing. + ValueError: If `app` is provided along with `agent`, or if `app` is not + provided but either `app_name` or `agent` is missing. """ self.app = app ( @@ -181,7 +187,8 @@ def _validate_runner_params( Args: app: An optional `App` instance. - app_name: The application name of the runner. + app_name: The application name of the runner. Can override app.name when + app is provided. agent: The root agent to run. plugins: A list of plugins for the runner. @@ -193,10 +200,6 @@ def _validate_runner_params( ValueError: If parameters are invalid. """ if app: - if app_name: - raise ValueError( - 'When app is provided, app_name should not be provided.' - ) if agent: raise ValueError('When app is provided, agent should not be provided.') if plugins: @@ -204,7 +207,9 @@ def _validate_runner_params( 'When app is provided, plugins should not be provided and should be' ' provided in the app instead.' ) - app_name = app.name + # Allow app_name to override app.name (useful for deployment scenarios + # like Agent Engine where resource names differ from app identifiers) + app_name = app_name or app.name agent = app.root_agent plugins = app.plugins context_cache_config = app.context_cache_config diff --git a/tests/unittests/test_runners.py b/tests/unittests/test_runners.py index 7c4de3ecce..3ef3bc1d0e 100644 --- a/tests/unittests/test_runners.py +++ b/tests/unittests/test_runners.py @@ -586,20 +586,32 @@ async def test_runner_passes_plugin_close_timeout(self): ) assert runner.plugin_manager._close_timeout == 10.0 - def test_runner_init_raises_error_with_app_and_app_name_and_agent(self): - """Test that ValueError is raised when app, app_name and agent are provided.""" + def test_runner_init_raises_error_with_app_and_agent(self): + """Test that ValueError is raised when app and agent are provided.""" with pytest.raises( ValueError, - match="When app is provided, app_name should not be provided.", + match="When app is provided, agent should not be provided.", ): Runner( app=App(name="test_app", root_agent=self.root_agent), - app_name="test_app", agent=self.root_agent, session_service=self.session_service, artifact_service=self.artifact_service, ) + def test_runner_init_allows_app_name_override_with_app(self): + """Test that app_name can override app.name when both are provided.""" + app = App(name="test_app", root_agent=self.root_agent) + runner = Runner( + app=app, + app_name="override_name", + session_service=self.session_service, + artifact_service=self.artifact_service, + ) + assert runner.app_name == "override_name" + assert runner.agent == self.root_agent + assert runner.app == app + def test_runner_init_raises_error_without_app_and_app_name(self): """Test ValueError is raised when app is not provided and app_name is missing.""" with pytest.raises( From 0e6b7965157dba7fd864778eb9af85a2d090fb0e Mon Sep 17 00:00:00 2001 From: sarojrout Date: Thu, 27 Nov 2025 12:23:09 -0800 Subject: [PATCH 2/2] fix(runners): Update docstring and suppress warnings in tests - Update Raises section in Runner.__init__ docstring to mention plugins validation error when app is provided - Add warning filters to new tests to suppress deprecation warnings from setup_method that uses deprecated plugins parameter --- src/google/adk/runners.py | 4 ++-- tests/unittests/test_runners.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/google/adk/runners.py b/src/google/adk/runners.py index aae1c12819..95e9b94f6d 100644 --- a/src/google/adk/runners.py +++ b/src/google/adk/runners.py @@ -145,8 +145,8 @@ def __init__( plugin_close_timeout: The timeout in seconds for plugin close methods. Raises: - ValueError: If `app` is provided along with `agent`, or if `app` is not - provided but either `app_name` or `agent` is missing. + ValueError: If `app` is provided along with `agent` or `plugins`, or if + `app` is not provided but either `app_name` or `agent` is missing. """ self.app = app ( diff --git a/tests/unittests/test_runners.py b/tests/unittests/test_runners.py index 3ef3bc1d0e..a01fb682c0 100644 --- a/tests/unittests/test_runners.py +++ b/tests/unittests/test_runners.py @@ -586,6 +586,9 @@ async def test_runner_passes_plugin_close_timeout(self): ) assert runner.plugin_manager._close_timeout == 10.0 + @pytest.mark.filterwarnings( + "ignore:The `plugins` argument is deprecated:DeprecationWarning" + ) def test_runner_init_raises_error_with_app_and_agent(self): """Test that ValueError is raised when app and agent are provided.""" with pytest.raises( @@ -599,6 +602,9 @@ def test_runner_init_raises_error_with_app_and_agent(self): artifact_service=self.artifact_service, ) + @pytest.mark.filterwarnings( + "ignore:The `plugins` argument is deprecated:DeprecationWarning" + ) def test_runner_init_allows_app_name_override_with_app(self): """Test that app_name can override app.name when both are provided.""" app = App(name="test_app", root_agent=self.root_agent)