diff --git a/src/google/adk/cli/cli_tools_click.py b/src/google/adk/cli/cli_tools_click.py index 07ccc15892..a41de4ef72 100644 --- a/src/google/adk/cli/cli_tools_click.py +++ b/src/google/adk/cli/cli_tools_click.py @@ -1632,8 +1632,12 @@ def cli_web( ): """Starts a FastAPI server with Web UI for agents. - AGENTS_DIR: The directory of agents, where each subdirectory is a single - agent, containing at least `__init__.py` and `agent.py` files. + AGENTS_DIR: The directory of agents. Each subdirectory (or file) can contain an agent + loaded via multiple formats: + - `{agent_name}/agent.py` (module with `root_agent`) + - `{agent_name}.py` (module with `root_agent`) + - `{agent_name}/__init__.py` (package with `root_agent` or `app`) + - `{agent_name}/root_agent.yaml` (YAML config folder) Example: @@ -1745,8 +1749,12 @@ def cli_api_server( ): """Starts a FastAPI server for agents. - AGENTS_DIR: The directory of agents, where each subdirectory is a single - agent, containing at least `__init__.py` and `agent.py` files. + AGENTS_DIR: The directory of agents. Each subdirectory (or file) can contain an agent + loaded via multiple formats: + - `{agent_name}/agent.py` (module with `root_agent`) + - `{agent_name}.py` (module with `root_agent`) + - `{agent_name}/__init__.py` (package with `root_agent` or `app`) + - `{agent_name}/root_agent.yaml` (YAML config folder) Example: diff --git a/src/google/adk/runners.py b/src/google/adk/runners.py index 8e352794a4..75833f83c5 100644 --- a/src/google/adk/runners.py +++ b/src/google/adk/runners.py @@ -825,12 +825,26 @@ async def _exec_with_plugin( _apply_run_config_custom_metadata( early_exit_event, invocation_context.run_config ) - if self._should_append_event(early_exit_event, is_live_call): + # Step 3: Run the on_event callbacks to optionally modify the event. + # This MUST run before append_event so modifications are persisted. + modified_early_exit_event = await plugin_manager.run_on_event_callback( + invocation_context=invocation_context, event=early_exit_event + ) + if modified_early_exit_event: + _apply_run_config_custom_metadata( + modified_early_exit_event, invocation_context.run_config + ) + event_to_append = modified_early_exit_event + else: + event_to_append = early_exit_event + # Step 4: Append the (possibly modified) event to the database. + if self._should_append_event(event_to_append, is_live_call): await self.session_service.append_event( session=session, - event=early_exit_event, + event=event_to_append, ) - yield early_exit_event + # Step 5: Yield the modified event to the client. + yield modified_early_exit_event if modified_early_exit_event else early_exit_event else: # Step 2: Otherwise continue with normal execution # Note for live/bidi: @@ -868,6 +882,17 @@ async def _exec_with_plugin( # non-partial event; event.partial=True is considered as partial # event. if event.partial is not True: + # Step 3: Run the on_event callbacks to optionally modify the event. + # This MUST run before append_event so modifications are persisted. + modified_event = await plugin_manager.run_on_event_callback( + invocation_context=invocation_context, event=event + ) + if modified_event: + _apply_run_config_custom_metadata( + modified_event, invocation_context.run_config + ) + event = modified_event # Use modified event for appending + if _is_transcription(event) and ( _has_non_empty_transcription_text(event.input_transcription) or _has_non_empty_transcription_text( @@ -899,22 +924,25 @@ async def _exec_with_plugin( await self.session_service.append_event( session=session, event=event ) + # Step 5: Yield the event to the caller. + yield event else: + # Step 3: Run the on_event callbacks to optionally modify the event. + # This MUST run before append_event so modifications are persisted. + modified_event = await plugin_manager.run_on_event_callback( + invocation_context=invocation_context, event=event + ) + if modified_event: + _apply_run_config_custom_metadata( + modified_event, invocation_context.run_config + ) + event = modified_event # Use modified event for appending and yielding + # Step 4: Append the event to the database (after on_event_callback). if event.partial is not True: await self.session_service.append_event( session=session, event=event ) - - # Step 3: Run the on_event callbacks to optionally modify the event. - modified_event = await plugin_manager.run_on_event_callback( - invocation_context=invocation_context, event=event - ) - if modified_event: - _apply_run_config_custom_metadata( - modified_event, invocation_context.run_config - ) - yield modified_event - else: + # Step 5: Yield the event to the caller. yield event # Step 4: Run the after_run callbacks to perform global cleanup tasks or