Make a Blueprint extending GameInstance and set it for you game as the GameInstance class to use. Put your variables here that you want to remain between levels. The Node GetGameInstance will get the GameInstance from any blueprint, then cast it to whatever you called yours.
The first part of your question doesn’t really make sense. All you need is a reference to the Blueprint that you want and you can call functions, events and set variables on it. There doesn’t have to be “communication”.
You need to decide how to get the reference. This depends on what type of Blueprint it is, if it’s an object in the level that you interact with then use the best method that makes sense, such as if the player bumps into it, shoots it, or a mouse click on it etc. That is up to you to decide.
If it’s an invisible thing that just stores some sort of GameState, honestly you’d be better off extending the GameState class and putting your variable’s and functions there. You can get the GameState at any time with the Node GetGameState, then cast to what you called yours. You need to set your game to use your custom GameState class.
There are hacks you can do, like GetAllActorsOfClass and just use the first one, but that’s sloppy and it’s possible you will have more than one instance and they you will start to get weird bugs.