Автопилоты
Настройте автоматический запуск агентов по cron-расписанию, входящему вебхуку или вручную через UI или CLI.
Автопилоты позволяют агентам начинать работу автоматически по расписанию — настройте cron-выражение и часовой пояс, и AACWorkflow самостоятельно создаст task, без вашего участия. Это подходит для периодических проверок, повторяющихся отчётов и ночных задач очистки — работа в формате «постоянного поручения». В отличие от трёх других способов запуска (назначение, @-упоминание и чат, где инициатором выступаете вы), главное отличие автопилотов — они управляются временем.
Настройка автопилота
Создайте новый автопилот на странице Автопилот рабочего пространства. Вы задаёте:
- Название — отображаемое имя
- Агент — кому направляется запуск
- Приоритет — наследуется создаваемым
task(та же семантика, что у приоритета задач) - Описание / промпт — описание работы, которое агент получает при каждом запуске
- Режим выполнения — см. ниже
- Триггеры — минимум один
schedule(cron + часовой пояс) илиwebhook
Выбор режима выполнения
У автопилота два режима. Начните с режима «создать задачу».
- Режим создания задачи (
create_issue) — по умолчанию, рекомендуется. Каждый запуск сначала создаёт задачу в рабочем пространстве (заголовок в данный момент поддерживает единственный плейсхолдер:{{date}}, который заменяется на дату UTC в форматеYYYY-MM-DD; любые другие токены{{...}}отклоняются при создании, так что опечатка не может незаметно оказаться буквальной строкой в заголовках ваших задач), затем назначает задачу агенту через обычный поток назначения. Вся работа попадает на доску задач с той же историей, комментариями и статусом, что и у задачи, назначенной вручную. - Режим «только выполнить» (
run_only) — пропускает создание задачи и ставитtaskв очередь напрямую. Запуск невидим на доске — вы можете увидеть его только в истории запусков автопилота.
Запуск по расписанию
Каждому автопилоту нужен минимум один триггер schedule. Cron использует стандартный 5-польный формат (минута час день месяц день_недели), с минимальной гранулярностью 1 минута (без секунд). Часовой пояс — в формате IANA (например, Asia/Shanghai) и определяет, в каком часовом поясе интерпретируется cron-выражение.
Несколько примеров:
0 9 * * 1-5,Asia/Shanghai— 9:00 по пекинскому времени в будни*/30 * * * *,UTC— каждые 30 минут0 3 * * *,UTC— каждый день в 3:00 UTC
Сервер AACWorkflow проверяет триггеры каждые 30 секунд — фактическое время запуска может отставать до 30 секунд, а не срабатывать с точностью до секунды. Если сервер перезапускается во время пропущенного срабатывания, он навёрстывает пропущенные триггеры при старте (ничего не теряется, но они срабатывают сразу).
Ручной запуск
Чтобы не ждать cron при отладке автопилота, запустите его вручную:
- UI: нажмите «Запустить сейчас» на странице автопилота
- CLI:
aacworkflow autopilot trigger <autopilot-id>Ручной запуск проходит через тот же поток выполнения, что и триггер schedule — только поле source в записи запуска помечается как manual.
Запуск через вебхук
Автопилоты также могут срабатывать по входящим HTTP-вебхукам. Добавьте триггер Webhook на странице автопилота; AACWorkflow сгенерирует уникальный URL вида:
https://<your-aacworkflow-host>/api/webhooks/autopilots/awt_…Отправьте POST-запрос с любым JSON на этот URL — AACWorkflow запишет запуск с source = webhook,
сохранит тело запроса как trigger_payload этого запуска и отправит агента
ровно так же, как это сделал бы триггер по расписанию.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"event":"demo.received","eventPayload":{"message":"hello"}}'В режиме создания задачи входящая полезная нагрузка добавляется в описание новой задачи, чтобы агент мог прочитать её непосредственно. В режиме «только выполнить» полезная нагрузка является частью контекста запуска, который демон передаёт агенту.
Формат полезной нагрузки
Вы можете отправить собственную обёртку:
{ "event": "github.pull_request.opened", "eventPayload": { } }…или любой JSON-объект/массив. AACWorkflow нормализует его во внутреннюю обёртку:
{
"event": "<inferred>",
"eventPayload": <your body>,
"request": { "receivedAt": "<rfc3339>", "contentType": "application/json" }
}Когда вы не передаёте поле event, AACWorkflow определяет его из распространённых
заголовков и полей тела (X-GitHub-Event + поле action тела,
X-Gitlab-Event, X-Event-Type, поля тела event/type/action). Если
ничего не совпало, событием будет webhook.received.
При настройке GitHub или аналогичных источников установите тип содержимого
application/json — вебхуки в form-encoded формате не принимаются.
Фильтры событий
Новый вебхук-триггер срабатывает на каждый входящий POST-запрос, что нормально для
одноцелевого URL, но создаёт много шума для источников с множеством типов событий
(GitHub — очевидный пример: один вебхук репозитория может доставлять
push, pull_request, workflow_run, check_suite и другие). Раздел
Фильтры событий на триггере вебхука позволяет ограничить, какие
события фактически запускают выполнение; всё остальное записывается в историю доставки
со статусом status = ignored и reason = event_filtered, и никакой
запуск или задача не создаётся.
Каждая строка — это одно правило: имя события и опциональный список действий через запятую. AACWorkflow разрешает вебхук, если любая строка совпадает; оставьте раздел пустым, чтобы принимать всё (поведение до применения фильтра).
Примеры:
| Имя события | Действия | Совпадение |
|---|---|---|
workflow_run | completed, failed | События workflow_run с action: completed или action: failed только |
workflow_run | (пусто) | Все события workflow_run, независимо от действия |
push | (пусто) | Все события push |
Откуда берутся имя события и действие
AACWorkflow определяет имя event и action из входящего запроса
в следующем порядке — первое совпадение побеждает.
1. Обёртка тела запроса. Если тело запроса — JSON-объект со строковым
полем event, это значение становится именем события напрямую. Затем из
необязательного объекта eventPayload извлекаются кандидаты действия
из полей action / state / conclusion / status.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"event":"trigger","eventPayload":{"action":"true"}}'
# inferred: event = trigger, action candidate = true2. Заголовки. Когда обёртка тела отсутствует, AACWorkflow считывает следующие известные заголовки провайдеров:
X-GitHub-Event: <event>— комбинируется с полемactionверхнего уровня тела (при его наличии) для формированияgithub.<event>.<action>.X-Gitlab-Event: <event>— становитсяgitlab.<event>.X-Event-Type: <event>— передаётся дословно.
# GitHub-style: header gives the event name, body gives the action.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'X-GitHub-Event: workflow_run' \
-H 'Content-Type: application/json' \
-d '{"action":"completed"}'
# inferred: event = github.workflow_run.completed
# → matches a filter row of workflow_run / completed
# Generic event-type header — no body fields needed.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'X-Event-Type: trigger.true' \
-H 'Content-Type: application/json' \
-d '{}'
# inferred: event = trigger.true → matches trigger / true3. Резервный вариант по телу запроса. Если нет ни обёртки тела, ни известного
заголовка, AACWorkflow обращается к строковым полям верхнего уровня тела в следующем
порядке: event → type → action.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"type":"trigger","action":"true"}'
# inferred: event = trigger (from `type`), action candidate = true4. Значение по умолчанию. Если ничто из перечисленного не совпало, событием
становится webhook.received и кандидатов действия нет.
Кандидаты действия — полный список. После определения события AACWorkflow рассматривает каждое из следующих значений как возможное совпадение действия:
- Суффикс имени события, когда событие имеет форму
provider.event.<action>(например,github.workflow_run.completed→completed). - Поля тела
action,state,conclusionиstatus— только если они являются JSON-строками. Логическое значение ({"action": true}) или число не подходят, поэтому фильтр, ожидающийevent=trigger, action=true, никогда не совпадёт с телом{"trigger": true}, потому чтоtrue— это bool, а не строка.
Частая ловушка. Строка фильтра вида Event name: trigger /
Actions: true не означает «срабатывать, когда в теле есть
trigger: true» — фильтры событий сопоставляют определённые события и
действия, а не произвольные поля тела. Отправьте trigger.true через
X-Event-Type (или используйте обёртку тела, показанную выше), чтобы попасть в фильтр.
Окружающие пробелы в сохранённых строках фильтра (" workflow_run ")
сохраняются как есть и никогда не совпадут — обрезайте пробелы перед сохранением.
Быстрая проверка
После настройки фильтра вы можете проверить обе ветки с помощью curl:
# Allowed — header drives event=workflow_run, body drives action=completed
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'X-GitHub-Event: workflow_run' \
-H 'Content-Type: application/json' \
-d '{"action":"completed"}'
# → 200 {"status":"accepted", ...}
# Filtered — same event, action not in allowlist
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'X-GitHub-Event: workflow_run' \
-H 'Content-Type: application/json' \
-d '{"action":"in_progress"}'
# → 200 {"status":"ignored","reason":"event_filtered"}Примеры провайдеров
Вебхук-триггер не зависит от провайдера: он принимает любое JSON-тело,
поэтому один и тот же URL подходит для GitHub, трекеров ошибок, событий
биллинга, CI/CD, мониторинга доступности и RSS-мостов. В каждом примере
ниже показаны входящий payload, строки фильтра событий (оставьте
пустыми, чтобы принимать всё) и то, что агент получает в
trigger_payload.
GitHub — открыт pull request
GitHub передаёт тип события в заголовке X-GitHub-Event, а подсобытие — в
поле action тела, поэтому выведенное событие — github.<event>.<action>.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'X-GitHub-Event: pull_request' \
-H 'Content-Type: application/json' \
-d '{"action":"opened","pull_request":{"number":42,"title":"Add billing webhook"}}'
# выведено: event = github.pull_request.opened| Имя события | Действия | Срабатывает на |
|---|---|---|
pull_request | opened | только новые PR (не правки/закрытия) |
check_suite | completed | завершении CI-прогона на PR |
Используйте режим создания issue, чтобы каждый открытый PR становился issue, которую проверяет агент.
Sentry — алерт по ошибке
Вебхуки алертов Sentry не несут заголовка провайдера, поэтому добавьте
конверт event (или положитесь на запасной webhook.received). Направьте
действие алерта Sentry на URL автопилота.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{
"event": "sentry.issue_alert",
"eventPayload": {
"action": "triggered",
"data": { "issue": { "title": "TypeError: cannot read x", "culprit": "api/handler.go" } }
}
}'
# выведено: event = sentry.issue_alert, кандидат действия = triggered| Имя события | Действия | Срабатывает на |
|---|---|---|
sentry.issue_alert | triggered | только новые алерты |
Агент получает заголовок стек-трейса и culprit в payload — в паре с режимом создания issue баг заводится автоматически.
Stripe / Lago — событие биллинга
Stripe кладёт имя события в поле type тела; Lago использует
webhook_type. Для Stripe запасной разбор тела берёт событие из type.
Для Lago оберните его в конверт, чтобы имя события было явным.
# Stripe — запасной разбор тела читает `type`
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"type":"invoice.payment_failed","data":{"object":{"customer":"cus_123"}}}'
# выведено: event = invoice.payment_failed
# Lago — явный конверт
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"event":"lago.invoice.payment_failure","eventPayload":{"status":"failed"}}'
# выведено: event = lago.invoice.payment_failure, кандидат действия = failed| Имя события | Действия | Срабатывает на |
|---|---|---|
invoice.payment_failed | (пусто) | каждый сбой оплаты в Stripe |
lago.invoice.payment_failure | failed | сбои оплаты в Lago |
Деплой упал — CI/CD-пайплайн
Большинство CI-провайдеров могут отправить произвольное JSON-тело при
завершении пайплайна. Используйте конверт event + eventPayload.status,
чтобы фильтровать успех и неудачу.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{
"event": "deploy",
"eventPayload": { "status": "failed", "environment": "production", "commit": "1a2b3c" }
}'
# выведено: event = deploy, кандидат действия = failed| Имя события | Действия | Срабатывает на |
|---|---|---|
deploy | failed | только упавшие деплои (не ok) |
Алерт доступности — монитор недоступен
Сервисы мониторинга (UptimeRobot, Better Stack, Pingdom) отправляют
небольшое JSON-тело. Добавьте конверт event и фильтруйте по состоянию.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"event":"uptime","eventPayload":{"status":"down","monitor":"api.example.com"}}'
# выведено: event = uptime, кандидат действия = down| Имя события | Действия | Срабатывает на |
|---|---|---|
uptime | down | только алерты «down» |
В паре с режимом только запуска агент расследует проблему, не заводя дублирующий инцидент при каждом мигании.
RSS-монитор — новая запись
Нативной поддержки RSS нет, но крошечная плановая задача (cron, GitHub Action или шаг Zapier/n8n) может опрашивать ленту и отправлять каждую новую запись на URL вебхука.
curl -X POST "$AACWORKFLOW_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{
"event": "rss.item",
"eventPayload": { "title": "v2.0 released", "link": "https://example.com/blog/v2", "published": "2026-06-20T09:00:00Z" }
}'
# выведено: event = rss.item| Имя события | Действия | Срабатывает на |
|---|---|---|
rss.item | (пусто) | каждую опубликованную запись |
Используйте режим создания issue, чтобы превращать каждую запись ленты в отслеживаемую issue.
URL является bearer-секретом
Сгенерированный URL и есть учётные данные. Любой, у кого он есть, может запустить автопилот. Относитесь к нему как к токену:
- Не вставляйте его в публичные обсуждения задач, скриншоты или историю чата.
- Смените URL при утечке — нажмите «Сменить URL» в строке триггера или выполните
aacworkflow autopilot trigger-rotate-url <autopilot-id> <trigger-id>. Старый URL перестаёт работать немедленно. - Для источников, требующих строгой аутентификации, ожидайте проверку HMAC-подписи для каждого триггера; эта v1 URL использует только bearer-аутентификацию.
- Участники рабочего пространства, которые могут просматривать автопилот, пока что могут читать его вебхук-URL — более строгая видимость секретов по ролям появится позднее.
Семантика кодов состояния
AACWorkflow возвращает 200 OK с полем status для обычных сценариев без ошибок, чтобы
механизм повторных попыток вашего провайдера не продолжал долбить URL:
{"status":"accepted","run_id":"…","autopilot_id":"…","trigger_id":"…"}— запуск отправлен.{"status":"skipped","run_id":"…","reason":"agent runtime is offline at dispatch time"}— среда выполнения назначенного агента отключена; записано как запуск со статусомskipped.{"status":"ignored","reason":"trigger_disabled"}— триггер отключён.{"status":"ignored","reason":"autopilot_paused"}— автопилот приостановлен.{"status":"ignored","reason":"autopilot_archived"}— автопилот архивирован.
Ответы не 2xx охватывают реальные ошибки:
400— неверный JSON, скалярное тело или пустое тело.404— неизвестный токен ({"error":"webhook not found"}).413— полезная нагрузка превышает 256 КБ.429— превышение лимита запросов для токена (по умолчанию 60 запр/мин).
Откуда берётся webhook URL
В AACWorkflow Cloud ответ триггера всегда включает абсолютный webhook_url
(построенный на основе https://aacworkflow.com), а UI показывает
URL, готовый к копированию. AACWorkflow намеренно
не выводит публичный хост из заголовков Host / X-Forwarded-Host, поэтому
подделанный запрос не сможет обманом заставить сервер создать
вебхук-URL, указывающий на хост, контролируемый злоумышленником.
Просмотр истории запусков
Каждый триггер создаёт запись запуска, видимую на вкладке «История» на странице автопилота:
- Источник триггера (
schedule/manual/webhook) - Время начала, время завершения
- Статус (
issue_created/running/completed/failed/skipped) - Связанная задача (режим создания задачи) или
task(режим «только выполнить») - Причина сбоя (если failed или skipped)
Что происходит при сбое автопилота
Сбои автопилотов не повторяются автоматически и не отправляют уведомления в папку «Входящие». При сбое в истории запусков остаётся запись со статусом failed — нет системного повторного помещения в очередь, как при назначении или @-упоминании, и никаких уведомлений. Если автопилот периодический, следующий cron-запуск вызовет новое выполнение, но работа, завершившаяся сбоем, автоматически не перезапускается.
Если автопилот важен, спроектируйте собственный мониторинг — например, пусть агент публикует комментарий при успехе, а вы отслеживаете сбои по отсутствию ожидаемых комментариев.
Почему нет автоматического повтора: автопилоты и так периодические, поэтому добавление системных повторов накладывается на следующий запланированный запуск и создаёт дублирующиеся выполнения. Оставляя расписание полностью на усмотрение cron, мы сохраняем чистоту схемы.
Что пока недоступно
Триггеры типа API не подключены. Схема триггеров резервирует тип
api, но ни один входящий маршрут его не запускает; UI показывает значок «Устарело» для
существующих строк и не предлагает возможностей копирования/смены. Проверка HMAC-подписи
для каждого триггера, списки разрешённых IP и предустановки событий для конкретных провайдеров
запланированы на будущее; v1 URL работают только с bearer-аутентификацией.
Далее
- Назначение задач агентам — одноразовая передача задачи агенту
- @-упоминание агентов в комментариях — привлечение агента из комментария
- Чат — индивидуальная беседа вне рамок задачи