@@ -1375,6 +1375,67 @@ def test_llm_request_without_metadata(self):
13751375
13761376 assert llm_request .metadata is None
13771377
1378+ @pytest .mark .asyncio
1379+ async def test_metadata_shallow_copy_isolation (self ):
1380+ """Test that shallow copy isolates top-level changes but shares nested objects."""
1381+ # Track modifications made in callback
1382+ callback_received_metadata = None
1383+
1384+ def before_model_callback (callback_context , llm_request ):
1385+ nonlocal callback_received_metadata
1386+ callback_received_metadata = llm_request .metadata
1387+ # Modify top-level key (should NOT affect original due to shallow copy)
1388+ llm_request .metadata ["top_level_key" ] = "modified_in_callback"
1389+ # Modify nested object (WILL affect original due to shallow copy)
1390+ llm_request .metadata ["nested" ]["inner_key" ] = "modified_nested"
1391+ return LlmResponse (
1392+ content = types .Content (
1393+ role = "model" , parts = [types .Part (text = "Test response" )]
1394+ )
1395+ )
1396+
1397+ agent_with_callback = LlmAgent (
1398+ name = "callback_agent" ,
1399+ model = "gemini-2.0-flash" ,
1400+ before_model_callback = before_model_callback ,
1401+ )
1402+
1403+ runner_with_callback = Runner (
1404+ app_name = "test_app" ,
1405+ agent = agent_with_callback ,
1406+ session_service = self .session_service ,
1407+ artifact_service = self .artifact_service ,
1408+ )
1409+
1410+ await self .session_service .create_session (
1411+ app_name = TEST_APP_ID , user_id = TEST_USER_ID , session_id = TEST_SESSION_ID
1412+ )
1413+
1414+ # Original metadata with nested mutable object
1415+ original_metadata = {
1416+ "top_level_key" : "original_value" ,
1417+ "nested" : {"inner_key" : "original_nested" },
1418+ }
1419+
1420+ async for event in runner_with_callback .run_async (
1421+ user_id = TEST_USER_ID ,
1422+ session_id = TEST_SESSION_ID ,
1423+ new_message = types .Content (
1424+ role = "user" , parts = [types .Part (text = "Hello" )]
1425+ ),
1426+ metadata = original_metadata ,
1427+ ):
1428+ pass
1429+
1430+ # Verify callback received metadata
1431+ assert callback_received_metadata is not None
1432+
1433+ # Top-level changes in callback should NOT affect original (shallow copy)
1434+ assert original_metadata ["top_level_key" ] == "original_value"
1435+
1436+ # Nested object changes in callback WILL affect original (shallow copy behavior)
1437+ assert original_metadata ["nested" ]["inner_key" ] == "modified_nested"
1438+
13781439
13791440if __name__ == "__main__" :
13801441 pytest .main ([__file__ ])
0 commit comments