The launchctl subcommands most scripts still use, load and unload, were superseded in OS X 10.11 by a domain-aware interface. They still work in many cases but silently do the wrong thing when the target domain is ambiguous, and they cannot express per-user versus system scope.
The modern equivalents take an explicit domain. 'launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.job.plist' loads an agent into the current GUI session; 'launchctl bootout gui/$(id -u)/com.example.job' unloads it. For a system daemon the domain is 'system' and the command needs root. 'launchctl kickstart -k gui/$(id -u)/com.example.job' restarts a running job, and 'launchctl print gui/$(id -u)/com.example.job' dumps its full state including the last exit status, which is where you look when a job appears to do nothing.
Common causes of a job that never runs: the plist is not owned by root for a LaunchDaemon, the Program path is relative, or the process exits immediately and launchd throttles restarts to once every ten seconds and eventually gives up.