Модуль синхронизации установили, в админке агент появился, лог написал "выполнено" - а на следующий день очередь писем пуста. Чаще всего виноват не сервер, а контракт CAgent: метод run() ничего не вернул, и ядро удалило запись из b_agent. Ниже - пошагово: класс в lib/, регистрация через CAgent::AddAgent при установке модуля, обязательный return строки вызова и проверка в списке агентов. Речь про 1С-Битрикс: Управление сайтом (CMS), не про AI-агентов Bitrix24.
Агент в CMS - это PHP-код, который ядро запускает по расписанию при заходах на сайт или через cron. Чтобы запись не исчезла после первого run, метод обязан вернуть строку следующего вызова, например return "\Vendor\Module\Agent::run();". Регистрируйте агента в InstallDB модуля, проверяйте дубли через GetList и снимайте всех агентов модуля через RemoveModuleAgents при удалении.
Если вы уже собрали каркас модуля по гайду создания своего модуля на Битрикс, осталось добавить фоновую задачу: импорт по расписанию, очередь писем, синхронизация с внешним API. В поиске по слову "агенты" часто всплывают статьи про Bitrix24 и CRM-ботов - это другой продукт. Здесь разбираем CAgent API ядра CMS.
На практике типичная сцена: в install/index.php вызвали CAgent::AddAgent("Agent::run();", $this->MODULE_ID, ...) без полного namespace и без return в методе. Агент отработал один раз и пропал из /bitrix/admin/agent_list.php. Исправление занимает меньше часа, если знать контракт.
Выберите, когда нужен CAgent в своём модуле
Делайте: используйте агента, когда задача должна повторяться по времени - раз в час, раз в сутки - и не привязана к действию пользователя на сайте.
Не делайте: не вешайте на CAgent реакцию "сразу после сохранения заказа" - для этого есть обработчики событий OnAfter* (обработчики событий на Битрикс).
| Задача | CAgent в модуле | OnAfter* (B58) | cron_events.php (B25) |
|---|---|---|---|
| Импорт каталога раз в ночь | Да | Нет | Транспорт на production |
| Письмо сразу после оплаты | Нет | Да | Не нужен |
| Запуск без посетителей сайта | Нужен cron | Не подходит | Да, обязателен |
| Логика живёт в пакете модуля | Да, lib/Agent.php | Да, но по событию | Только запуск, не код |
На тестовом стенде агенты часто крутятся "на хитах" - при каждом заходе на сайт. На боевом сервере переводите очередь на cron - подробно в материале как перевести агенты на cron. CAgent регистрирует задачу, cron гарантирует запуск, когда посетителей нет.
Создайте класс Agent в lib/ с обязательным return
Делайте: положите логику в lib/Agent.php с namespace модуля и статическим методом run().
Не делайте: не пишите тяжёлую синхронизацию в init.php - при переносе модуля на другой проект агент не поедет вместе с кодом.
Официальный справочник CAgent::AddAgent прямо указывает: если агент ничего не возвращает, он удаляется. Возвращаемое значение - это PHP-код следующего запуска, обычно та же строка вызова.
namespace Vendor\Sync;
class Agent
{
public static function run()
{
// Ваша логика: очередь, импорт, лог
\Bitrix\Main\Loader::includeModule('vendor.sync');
// ... работа ...
// Обязательно: строка следующего вызова
return "\\Vendor\\Sync\\Agent::run();";
}
}
Чтобы остановить агент навсегда, верните пустую строку return "";. Для ограничения числа итераций используйте счётчик в Option API модуля - паттерн из курса разработчика на dev.1c-bitrix.ru.
Типичные ошибки:
return true;- в таблице b_agent поле NAME превращается в "1", агент ломается (форум dev.1c-bitrix.ru, topic50749).- Нет return вообще - запись исчезает после первого выполнения.
- В AddAgent указали
Agent::run();без ведущего backslash и namespace - Class not found при хите.
Зарегистрируйте CAgent::AddAgent в InstallDB
Делайте: вызывайте регистрацию в InstallDB или отдельном методе installAgents(), который срабатывает при DoInstall после registerModule.
Не делайте: не запускайте тяжёлую логику агента до того, как модуль зарегистрирован и подключён через Loader::includeModule.
- Откройте install/index.php своего модуля.
- В InstallDB добавьте вызов installAgents().
- Перед AddAgent проверьте дубль через CAgent::GetList по полям NAME и MODULE_ID.
- Передайте полный namespace в первом аргументе:
"\\Vendor\\Sync\\Agent::run();". - Укажите MODULE_ID модуля, period "N" (интервал в секундах) или "Y" (точное время), interval - например 3600 для часа.
- Сохраните ID агента или просто убедитесь, что GetList вернул одну запись.
protected function installAgents()
{
$agentName = "\\Vendor\\Sync\\Agent::run();";
$moduleId = $this->MODULE_ID;
$res = \CAgent::GetList(
[],
["NAME" => $agentName, "MODULE_ID" => $moduleId]
);
if (!$res->Fetch()) {
\CAgent::AddAgent(
$agentName,
$moduleId,
"N",
3600,
"",
"Y",
ConvertTimeStamp(time() + 60, "FULL")
);
}
}
Параметр period "N" означает "запускать каждые interval секунд после предыдущего завершения". period "Y" - в фиксированное время суток. Для dedup ориентируйтесь на паттерн ядра: GetList + проверка перед AddAgent, как в модуле sale.
Схема установки:
DoInstall → registerModule → InstallDB → installAgents() → CAgent::AddAgent → запись в b_agent → при хите или cron вызывается Agent::run() → return строки → агент остаётся в очереди
Настройте DoUninstall и RemoveModuleAgents
Делайте: в DoUninstall вызовите CAgent::RemoveModuleAgents($this->MODULE_ID) - так снимаются все агенты модуля одним вызовом.
Не делайте: не оставляйте "висячие" записи в b_agent - при переустановке получите дубли и двойной импорт.
RemoveAgent удаляет одного агента по ID или имени. RemoveModuleAgents чистит весь MODULE_ID - симметрия install/uninstall. После удаления модуля проверьте /bitrix/admin/agent_list.php и при необходимости таблицу b_agent: записей с вашим MODULE_ID быть не должно.
Проверьте агента: отладка и HttpClient для API
Делайте: сначала вызовите Agent::run() вручную из тестового скрипта - результат должен совпадать с запуском через агента.
Не делайте: не держите в агенте HTTP-запрос без таймаута дольше 10 минут - ядро блокирует очередь агентов.
Откройте /bitrix/admin/agent_list.php: смотрите LAST_EXEC, NEXT_EXEC, активность. Для логов используйте Debug::writeToFile - см. гайд по выводу ошибок в settings.php. Если агент тянет внешний API, оберните вызов в HttpClient D7 с socketTimeout и обработкой getError().
Workflow отладки: ручной run() → запись в лог → один хит на сайт или ручной cron_events.php → сверка LAST_EXEC → повтор через interval.
Пройдите чек-лист перед выкладкой на production
После установки модуля вы получите предсказуемую фоновую задачу, если закроете все пункты:
- В agent_list.php одна запись с вашим MODULE_ID и полным namespace в NAME.
- После трёх-пяти запусков агент не исчез, NEXT_EXEC сдвигается.
- Переустановка модуля не плодит дубли - GetList перед AddAgent работает.
- DoUninstall вызывает RemoveModuleAgents, в b_agent нет хвостов.
- На production настроен cron по гайду B25 - иначе ночной импорт встанет без посетителей.
- Длительная синхронизация разбита на батчи; внешний API - через HttpClient с таймаутом.
Если агент "то работает, то пропадает" после деплоя - в 9 случаях из 10 не хватает return строки вызова. Проверьте это раньше, чем копать сервер.
Нужна помощь с модулем синхронизации или переводом агентов на cron на боевом VPS - обсудим задачу. Примеры фоновых интеграций смотрите в портфолио.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: справочник CAgent::AddAgent, класс CAgent, документация Bitrix Framework.
Частые вопросы
Чем свой агент в модуле отличается от системных агентов Битрикс?
Системные агенты ставит ядро и модули Маркетплейса. Ваш агент регистрируете вы через CAgent::AddAgent с MODULE_ID своего модуля, код лежит в lib/Agent.php и удаляется вместе с модулем через RemoveModuleAgents.
Почему агент удаляется после выполнения?
Метод run() не вернул строку следующего вызова. Добавьте return "\Vendor\Module\Agent::run();" в конец метода. Не возвращайте true или число - в NAME попадёт "1" и агент сломается.
CAgent::AddAgent или CAgent::Add - что выбрать?
В новом коде используйте AddAgent: он проще и документирован для модулей. Add - низкоуровневый метод; без опыта легче ошибиться с полями b_agent. Для InstallDB достаточно AddAgent с dedup через GetList.
Как удалить агента при uninstall модуля?
В DoUninstall вызовите CAgent::RemoveModuleAgents($this->MODULE_ID) до удаления таблиц. Проверьте agent_list.php: записей с вашим MODULE_ID не осталось.
Можно ли вызывать HTTP-запрос из агента?
Да, через Bitrix\Main\Web\HttpClient с таймаутом и разбором статуса. Не блокируйте очередь длинным curl без лимита; тяжёлые задачи дробите на шаги и ставьте cron на production.
Где смотреть, что агент реально запускался?
В админке Настройки - Инструменты - Агенты (/bitrix/admin/agent_list.php): поля LAST_EXEC и NEXT_EXEC. Дополнительно пишите лог через Debug::writeToFile и сверяйте с ручным вызовом Agent::run().