Грубо говоря, для асинхронной программы верно одно утверждение: "пока ты выполняешь код, не являющийся await вызовом, остальная программа простаивает".
Каждый await вызов (а также его завершение) - это повод переключиться на другую задачу.
Таким образом, бесконечный цикл - это просто:
while True:
await asyncio.sleep(5) #пока текущая корутина спит, остальной бот работает
do_stuff() #пока do_stuff() работает, остальной бот спит
Вопрос в другом: нужен ли бесконечный цикл?
Я бы посоветовал начать с создания системы сбора статистики.
Например, завести таблицу вида id юзера - имя статы - значение статы.
Скажем "id - число_сообщений - 100500". И в обработчиках соответствующих событий делать UPDATE на эту таблицу. А потом в отдельном модуле периодически проверять статы пользователей, проверять, есть ли у них уже ачивка за эту стату, и если нет - то давать.