@@ -139,6 +139,7 @@ class MockPlugin(BasePlugin):
139139 "Modified user message ON_USER_CALLBACK_MSG from MockPlugin"
140140 )
141141 ON_EVENT_CALLBACK_MSG = "Modified event ON_EVENT_CALLBACK_MSG from MockPlugin"
142+ ON_EVENT_CALLBACK_METADATA = {"plugin_key" : "plugin_value" }
142143
143144 def __init__ (self ):
144145 super ().__init__ (name = "mock_plugin" )
@@ -184,6 +185,7 @@ async def on_event_callback(
184185 ],
185186 role = event .content .role ,
186187 ),
188+ custom_metadata = self .ON_EVENT_CALLBACK_METADATA ,
187189 )
188190
189191
@@ -359,6 +361,60 @@ async def test_run_live_auto_create_session():
359361 assert session is not None
360362
361363
364+ @pytest .mark .asyncio
365+ async def test_run_live_persists_event_callback_modifications ():
366+ """run_live should persist the same event it streams after callback changes."""
367+ session_service = InMemorySessionService ()
368+ artifact_service = InMemoryArtifactService ()
369+ plugin = MockPlugin ()
370+ plugin .enable_event_callback = True
371+ runner = Runner (
372+ app_name = "live_app" ,
373+ agent = MockLiveAgent ("live_agent" ),
374+ session_service = session_service ,
375+ artifact_service = artifact_service ,
376+ plugins = [plugin ],
377+ )
378+ await session_service .create_session (
379+ app_name = "live_app" , user_id = "user" , session_id = "live_session"
380+ )
381+
382+ from google .adk .agents .live_request_queue import LiveRequestQueue
383+
384+ live_queue = LiveRequestQueue ()
385+ agen = runner .run_live (
386+ user_id = "user" ,
387+ session_id = "live_session" ,
388+ live_request_queue = live_queue ,
389+ )
390+
391+ streamed_event = await agen .__anext__ ()
392+ await agen .aclose ()
393+
394+ session = await session_service .get_session (
395+ app_name = "live_app" , user_id = "user" , session_id = "live_session"
396+ )
397+ persisted_event = session .events [0 ]
398+
399+ assert streamed_event .author == "live_agent"
400+ assert streamed_event .invocation_id
401+ assert streamed_event .content .parts [0 ].text == (
402+ MockPlugin .ON_EVENT_CALLBACK_MSG
403+ )
404+ assert streamed_event .custom_metadata == MockPlugin .ON_EVENT_CALLBACK_METADATA
405+
406+ assert persisted_event .id == streamed_event .id
407+ assert persisted_event .timestamp == streamed_event .timestamp
408+ assert persisted_event .author == streamed_event .author
409+ assert persisted_event .invocation_id == streamed_event .invocation_id
410+ assert persisted_event .content .parts [0 ].text == (
411+ MockPlugin .ON_EVENT_CALLBACK_MSG
412+ )
413+ assert (
414+ persisted_event .custom_metadata == MockPlugin .ON_EVENT_CALLBACK_METADATA
415+ )
416+
417+
362418@pytest .mark .asyncio
363419async def test_runner_allows_nested_agent_directories (tmp_path , monkeypatch ):
364420 project_root = tmp_path / "workspace"
@@ -747,6 +803,39 @@ async def test_runner_modifies_event_after_execution(self):
747803
748804 assert modified_event_message == MockPlugin .ON_EVENT_CALLBACK_MSG
749805
806+ @pytest .mark .asyncio
807+ async def test_runner_persists_event_callback_modifications (self ):
808+ """Event callback output should be persisted, not only streamed."""
809+ self .plugin .enable_event_callback = True
810+
811+ events = await self .run_test ()
812+ streamed_event = events [0 ]
813+
814+ session = await self .session_service .get_session (
815+ app_name = TEST_APP_ID , user_id = TEST_USER_ID , session_id = TEST_SESSION_ID
816+ )
817+ persisted_event = session .events [1 ]
818+
819+ assert streamed_event .author == "test_agent"
820+ assert streamed_event .invocation_id
821+ assert streamed_event .content .parts [0 ].text == (
822+ MockPlugin .ON_EVENT_CALLBACK_MSG
823+ )
824+ assert (
825+ streamed_event .custom_metadata == MockPlugin .ON_EVENT_CALLBACK_METADATA
826+ )
827+
828+ assert persisted_event .id == streamed_event .id
829+ assert persisted_event .timestamp == streamed_event .timestamp
830+ assert persisted_event .author == streamed_event .author
831+ assert persisted_event .invocation_id == streamed_event .invocation_id
832+ assert persisted_event .content .parts [0 ].text == (
833+ MockPlugin .ON_EVENT_CALLBACK_MSG
834+ )
835+ assert (
836+ persisted_event .custom_metadata == MockPlugin .ON_EVENT_CALLBACK_METADATA
837+ )
838+
750839 @pytest .mark .asyncio
751840 async def test_runner_close_calls_plugin_close (self ):
752841 """Test that runner.close() calls plugin manager close."""
0 commit comments