From 8ff113c74ef28c3bdd775580961dfe16303b4ad3 Mon Sep 17 00:00:00 2001 From: ejfn <148174+ejfn@users.noreply.github.com> Date: Wed, 1 Oct 2025 19:58:20 +0930 Subject: [PATCH 1/2] fix: Handle App objects in eval and graph endpoints Fixes #3059 - Extract root_agent from App objects in eval execution endpoint - Extract root_agent from App objects in graph visualization endpoint - Both endpoints now handle BaseAgent and App objects correctly --- src/google/adk/cli/adk_web_server.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index b2436d93c7..b200666742 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -966,7 +966,12 @@ async def run_eval( status_code=400, detail=f"Eval set `{eval_set_id}` not found." ) - root_agent = self.agent_loader.load_agent(app_name) + agent_or_app = self.agent_loader.load_agent(app_name) + # Extract root_agent if we loaded an App + if isinstance(agent_or_app, App): + root_agent = agent_or_app.root_agent + else: + root_agent = agent_or_app eval_case_results = [] @@ -1305,7 +1310,12 @@ async def get_event_graph( function_calls = event.get_function_calls() function_responses = event.get_function_responses() - root_agent = self.agent_loader.load_agent(app_name) + agent_or_app = self.agent_loader.load_agent(app_name) + # Extract root_agent if we loaded an App + if isinstance(agent_or_app, App): + root_agent = agent_or_app.root_agent + else: + root_agent = agent_or_app dot_graph = None if function_calls: function_call_highlights = [] From d058a9539d4418ad033d9d147ea3c25072caa77c Mon Sep 17 00:00:00 2001 From: ejfn <148174+ejfn@users.noreply.github.com> Date: Wed, 1 Oct 2025 20:05:41 +0930 Subject: [PATCH 2/2] refactor: Extract _get_root_agent helper method Address code review feedback by refactoring duplicated App object handling logic into a reusable private helper method. - Added _get_root_agent() helper method - Refactored 3 occurrences to use the helper - Improves maintainability and reduces duplication --- src/google/adk/cli/adk_web_server.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index b200666742..492fa96584 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -461,6 +461,12 @@ async def get_runner_async(self, app_name: str) -> Runner: self.runner_dict[app_name] = runner return runner + def _get_root_agent(self, agent_or_app: BaseAgent | App) -> BaseAgent: + """Extract root agent from either a BaseAgent or App object.""" + if isinstance(agent_or_app, App): + return agent_or_app.root_agent + return agent_or_app + def _create_runner(self, agentic_app: App) -> Runner: """Create a runner with common services.""" return Runner( @@ -803,9 +809,8 @@ async def add_session_to_eval_set( # Populate the session with initial session state. agent_or_app = self.agent_loader.load_agent(app_name) - if isinstance(agent_or_app, App): - agent_or_app = agent_or_app.root_agent - initial_session_state = create_empty_state(agent_or_app) + root_agent = self._get_root_agent(agent_or_app) + initial_session_state = create_empty_state(root_agent) new_eval_case = EvalCase( eval_id=req.eval_id, @@ -967,11 +972,7 @@ async def run_eval( ) agent_or_app = self.agent_loader.load_agent(app_name) - # Extract root_agent if we loaded an App - if isinstance(agent_or_app, App): - root_agent = agent_or_app.root_agent - else: - root_agent = agent_or_app + root_agent = self._get_root_agent(agent_or_app) eval_case_results = [] @@ -1311,11 +1312,7 @@ async def get_event_graph( function_calls = event.get_function_calls() function_responses = event.get_function_responses() agent_or_app = self.agent_loader.load_agent(app_name) - # Extract root_agent if we loaded an App - if isinstance(agent_or_app, App): - root_agent = agent_or_app.root_agent - else: - root_agent = agent_or_app + root_agent = self._get_root_agent(agent_or_app) dot_graph = None if function_calls: function_call_highlights = []