Runs the agent. Answer to the requests made by the Backend.
        May raise an asyncio.CancelledError, in which case the agent should clean itself and restart completely.

async def run(self):
        """
        Runs the agent. Answer to the requests made by the Backend.
        May raise an asyncio.CancelledError, in which case the agent should clean itself and restart completely.
        """
        self._logger.info("Agent started")
        self.__backend_socket.connect(self.__backend_addr)

        # Tell the backend we are up and have `concurrency` threads available
        self._logger.info("Saying hello to the backend")
        await ZMQUtils.send(self.__backend_socket, AgentHello(self.__friendly_name, self.__concurrency, self.environments))
        self.__last_ping = time.time()

        run_listen = self._loop.create_task(self.__run_listen())

        self._loop.call_later(1, self._create_safe_task, self.__check_last_ping(run_listen))

        await run_listen