Inside Mathics you load them with the Mathics LoadModule function, e.g. LoadModule["pymathics.hello"]
As said above, you would write them pretty much the same way you'd write a Mathics Builtin. ( am hoping one day we will write a guilde for how to write built-ins and PyMathics modules. But for now, the source code for hello gives the basic skeleton.
There were servial reasons we did this.
First, there was the problem that something that loading modules can be slow, especially for the Natural-Langauge processing. Since that is rather specialized, there might be a lot of people that don't need/want this and would not like to spend the time loading it up on startup every time.
Lazy loading or autoload as in Emacs Lisp would be an alternative too. But then there is another problem: Natural Language function need NLTK and possibly not everyone has that installed, or wants that installed.
And Ii order to use this you also need a word corpus which can be somewhat large. So even if natlang (as it is called internally) is autoloaded, it will still be taking up space on your disk. In do development, it makes the build time longer and takes longer for tests.
Finally, there is that desire that we'd like to allow for a less monolithic and more distributed development processe. With LoadModule, people can create their own Pymathics libraries and control and hook it into Mathics, the same as happens for the existing built-ins.