
Когда я только начал активно использовать Codex для длительных задач, мне казалось, что главная ценность AI‑агента — возможность работать самостоятельно. Я запускал задачу, переключался на другую работу и ожидал результата.
Но очень быстро заметил странную вещь. Несмотря на то что агент способен самостоятельно работать десятки минут, человек продолжает постоянно контролировать процесс. Через несколько минут появляется мысль: «Интересно, он уже закончил?» Открываешь терминал — нет. Закрываешь, возвращаешься к своим делам, а через несколько минут всё повторяется.
Постепенно я понял, что проблема вовсе не в отсутствии уведомлений. Она гораздо глубже: агент выполняет работу самостоятельно, но инициатива взаимодействия по‑прежнему полностью принадлежит человеку. Пользователь вынужден постоянно спрашивать: «Ты уже закончил?», хотя логичнее было бы наоборот.
Если агент действительно умеет работать автономно, именно он должен сообщать, когда участие человека необходимо. Мне захотелось попробовать такую модель взаимодействия — не просто сделать ещё одну систему уведомлений, а изменить сам принцип общения человека и AI‑агента.
В этой статье я покажу, как реализовал такую модель с помощью мобильных push‑уведомлений через ntfy и встроенных возможностей Codex.
Почему привычный рабочий процесс перестаёт работать
До появления уведомлений мой рабочий процесс выглядел примерно так:

На первый взгляд всё выглядит нормально. Но если присмотреться, почти все действия выполняет человек. Именно пользователь решает, когда проверить состояние, открывает терминал и определяет, можно ли продолжать работу. Сам агент в этой модели остаётся полностью пассивным.
Это кажется естественным, пока задачи выполняются несколько секунд. Но когда агент работает 10, 20 или даже 40 минут, постоянные проверки создают фоновое напряжение. Даже во время других дел часть внимания занята мыслью: «Нужно не забыть проверить Codex».
Самое интересное, что это мешало не только работе, но и отдыху. Мне хотелось добиться противоположного эффекта: после запуска задачи полностью забыть о терминале и возвращаться к нему только тогда, когда без меня действительно нельзя продолжить работу.
Каким должен быть AI‑агент
В какой‑то момент я попробовал посмотреть на ситуацию с другой стороны: что, если перестать воспринимать Codex как обычную программу? В конце концов, мы всё чаще называем подобные системы AI‑агентами.
Агент — это не просто инструмент, который выполняет команды. Он способен самостоятельно планировать действия, выполнять работу и принимать локальные решения. Если посмотреть на взаимодействие с этой точки зрения, возникает простой вопрос: почему именно человек должен постоянно интересоваться состоянием агента, а не наоборот?
Мне кажется, у хорошего AI‑агента должна быть очень простая модель взаимодействия:
Пока моё участие не требуется — не отвлекай меня. Если без меня нельзя продолжить работу — сообщи об этом.
Тогда инициатива взаимодействия естественным образом переходит к агенту, а рабочий процесс становится значительно проще:

Это кажется небольшим изменением, но на самом деле меняется вся модель взаимодействия. Раньше человек постоянно наблюдал за агентом. Теперь агент отслеживает момент, когда действительно нужен человек.
Но возникает следующий вопрос: когда именно агент должен меня отвлекать?
Когда действительно нужно внимание человека
Агент может генерировать десятки внутренних событий: начало работы, окончание отдельного шага, использование инструмента, запуск команды, проверка файлов. Но почти все они человеку неинтересны. Если уведомлять обо всём подряд, быстро возникает обратная проблема: уведомления начинают раздражать, и пользователь перестаёт обращать на них внимание.
Поэтому я сформулировал другое правило:
Агент должен отвлекать человека только тогда, когда это помогает продолжить работу.
В результате получилось всего три действительно важных сценария:
Событие |
Нужно участие человека |
Уведомление |
Работа завершена |
Нет |
Да |
Агент ожидает ответ |
Да |
Да |
Агент запрашивает разрешение |
Да |
Да |
Именно эти три события я решил превратить в push‑уведомления.
Завершение работы
Когда Codex заканчивает очередной ход, мне достаточно понять одну вещь: можно возвращаться.
Codex завершил ход

Агент ждёт ответа
Иногда работа не заканчивается — агент просто не может двигаться дальше без моего решения. Такое уведомление уже не сообщает об окончании работы. Оно говорит: «Я жду тебя».
Codex ждёт ответа

Запрос разрешения
Третий сценарий оказался самым неожиданным. Во время работы Codex может запросить разрешение на выполнение команды. Раньше в этот момент приходилось держать терминал открытым или периодически возвращаться к нему. Теперь телефон просто сообщает, что агент ожидает подтверждения.
Codex запрашивает разрешение

После этого я понял интересную вещь: все три уведомления описывают не столько состояние агента, сколько состояние взаимодействия между человеком и агентом. Именно это и стало основой дальнейшей реализации.
Почему именно мобильные уведомления
Когда я определился с тем, какие события действительно требуют моего внимания, осталось выбрать способ их доставки. Вариантов было много: Telegram, Slack, электронная почта или собственное мобильное приложение.
Но мне хотелось получить решение, которое одновременно:
настраивается за несколько минут;
не требует собственного сервера;
работает практически мгновенно;
не зависит от конкретной платформы;
легко используется в других проектах.
Поэтому выбор остановился на ntfy — небольшом open‑source сервисе push‑уведомлений. Для моего сценария оказалось достаточно установить мобильное приложение, подписаться на собственную тему и отправлять обычный HTTP POST‑запрос: никакой регистрации, API‑ключей или SDK.
В результате вся задача доставки уведомлений свелась к одному небольшому модулю. Но самое интересное оказалось не в этом. Архитектура разделилась на две независимые части: одна отвечает за понимание событий Codex, а другая — только за доставку уведомлений. Это разделение сделало решение намного проще, чем я ожидал.
Архитектура решения
Прежде чем перейти к реализации, сделаю небольшое признание: по профессии я системный аналитик. Для меня привычнее проектировать процессы и модели взаимодействия, чем писать Python‑код, поэтому всю реализацию я создавал совместно с Codex.
Самое интересное, что архитектуру я заранее не проектировал. Мне нужен был рабочий инструмент, и я постепенно решал одну задачу за другой. Только когда всё заработало, я посмотрел на результат и заметил, что решение само разделилось на несколько компонентов с понятными обязанностями.

Получилось четыре небольших компонента:
ntfy_topicхранит тему ntfy. Адрес доставки полностью отделён от программной логики: чтобы сменить тему, достаточно изменить содержимое одного файла.turn_notify.pyполучает событие завершения хода Codex. Он анализирует сообщение агента, определяет, требуется ли участие пользователя, и формирует уведомление.permission_notify.pyобрабатывает запросы разрешений. Это отдельный тип события Codex, который приходит через механизм Hooks, поэтому его обработка вынесена в отдельный компонент. Скрипт не принимает решение за пользователя, а лишь сообщает, что Codex ожидает разрешения.send_ntfy.pyничего не знает о Codex. Он умеет только отправлять push‑уведомления, поэтому его можно повторно использовать в других проектах.
Именно это разделение мне особенно понравилось: компоненты, понимающие события Codex, ничего не знают о способе доставки, а транспортный слой ничего не знает о внутреннем устройстве Codex.
Подключаем уведомления к Codex
После того как архитектура определилась, подключение оказалось довольно простым. Для уведомлений о завершении хода Codex достаточно использовать настройку notify в config.toml:
notify = [ "python3", "/home/<username>/.codex/turn_notify.py" ]
После каждого завершённого хода Codex запускает указанный скрипт и передаёт ему сообщение последнего ответа. Скрипт анализирует текст, определяет тип уведомления и передаёт его транспортному модулю.
С запросами разрешений ситуация немного отличается. Для них Codex предоставляет механизм Hooks. В моём случае конфигурация выглядит так:
[features] hooks = true [[hooks.PermissionRequest]] matcher = "*" [[hooks.PermissionRequest.hooks]] type = "command" command = "/usr/bin/python3 /home/<username>/.codex/permission_notify.py" timeout = 10 statusMessage = "Sending mobile notification"
Когда Codex запрашивает разрешение на выполнение команды, он запускает этот обработчик и передаёт ему описание события через стандартный ввод. Именно поэтому два обработчика получились немного разными.
message = sys.argv[1]
А permission_notify.py читает JSON события из stdin.
event = json.load(sys.stdin)
Дальше оба обработчика работают одинаково — формируют понятное пользователю уведомление и передают его модулю доставки.
Несколько интересных деталей реализации
Во время разработки встретилось несколько моментов, которые показались мне интересными.
Определение типа уведомления
Codex не сообщает напрямую, что ожидает ответ пользователя, поэтому пришлось использовать небольшую эвристику. Если последнее сообщение выглядит как вопрос, отправляется уведомление с более высоким приоритетом:
if looks_like_question(message): title = "Codex ждёт ответа" priority = 4 else: title = "Codex завершил ход" priority = 3
Это не идеальное решение, но на практике оно оказалось достаточно надёжным и позволяет отличать обычное завершение работы от ситуации, когда агент действительно ждёт пользователя.
Отдельный транспортный слой
Все обработчики используют один общий модуль отправки уведомлений. По сути, ему достаточно знать всего четыре параметра:
payload = { "topic": load_topic(), "title": title[:100], "message": message[:1000], "priority": priority, }
После этого остаётся выполнить HTTP POST‑запрос. Благодаря такому разделению при необходимости можно заменить ntfy на любой другой транспорт, не меняя обработчики событий.
Запрос разрешения ничего не решает автоматически
Наверное, это самое важное ограничение. Когда Codex запрашивает разрешение, мой обработчик не отвечает за пользователя. Он лишь отправляет push‑уведомление, а агент продолжает ждать решения в терминале.
Мне кажется, именно такое поведение является правильным: уведомления должны сокращать время ожидания пользователя, а не принимать решения вместо него.
Вместо заключения
Когда я начинал делать это небольшое расширение, мне казалось, что я просто хочу получать push‑уведомления на телефон. Но по мере работы стало понятно: настоящая задача была совсем другой. Мне хотелось перестать постоянно контролировать AI‑агента.
После нескольких дней использования я заметил изменение. Я больше не ловлю себя на мысли: «Надо проверить, что там делает Codex». Я просто запускаю задачу и переключаюсь на другие дела. Если агенту понадобится моё участие, он сам сообщит об этом.
Получилось небольшое изменение в интерфейсе, но ощущается оно как изменение самой модели взаимодействия. Раньше я постоянно следил за агентом. Теперь агент следит за тем моментом, когда действительно требуется моё участие.
Мне кажется, именно так и должна выглядеть работа с автономными AI‑агентами: не человек постоянно спрашивает «Ты уже закончил?», а агент говорит: «Теперь ты нужен мне».
Если вам захочется попробовать такой подход у себя, весь исходный код доступен на GitHub. Буду рад идеям, замечаниям и pull request’ам.
Комментарии (3)

den_rad
24.07.2026 06:35У меня не было необходимости именно подтверждать действия в Codex, скорее сообщать о окончании долгой работы (например нужно сделать скриншоты приложения для разных размеров экрана), я для этого использовал скилл, которые отправляет сообщение в Telegram.

positroid
24.07.2026 06:35Если во время работы codex вы сидите на том же устройстве - может быть полезно включить pet'а - висит в углу экрана и показывает статус текущих тасков:
Скрин

Очевидно, решение не для всех, но мне зашло
Lemko
Вчера только задумался, что постоянно "дергаюсь" туда-сюда