The only thing there is officially, is the gamescript. It allows for communication from Engine thread to Gui thread with the lua variable "state". This can contain pretty much everything (only standard lua types, no userdata).
The other way, there is the "sendScriptEvent" method from gui to engine (handleEvent).
But indeed it is lacking flexibility.
For example the load function has actually 2 jobs, as it is the only function called by engine thread (1x at startup) AND by gui thread (continously 5x/sec). There is no way to define things that should be done only at loading once, e.g. state initialization.
Second, a scriptEvent from Engine to Gui would be very useful. At the moment you have to do the following:
-write something in state (state.gui.doThis=true)
-in load check the state (if state.gui.doThis then)
-then you need to send an event to the Engine Thread again, because you cannot modify state in gui as it is reseted each time.
-Then in handleEvent, you need to remove the flag (state.gui.doThis=nil)
Sometimes the lack of communication from construction callbacks to gamescript is mentioned.
There need to be more events, e.g. at construction update.
This is also the reason, why Build with Collision does not work for construction upgrades.