Production AI-контур: очереди, ретраи, идемпотентность и HITL
Надёжный AI-контур в production — это не «модель + webhook», а очередь задач, ретраи с потолком, идемпотентные записи, human-in-the-loop на спорных шагах и мониторинг падений с DLQ: без этого агент один раз отработает красиво и три раза продублирует оплату, статус или сообщение клиенту.
Я собираю контур от потока событий, а не от чата. Ниже — стек принципов и чеклист, которые переживают ночной сбой API, повторную доставку webhook и «зависший» tool call. Без привязки к одному бренду оркестратора: те же правила для self-hosted runner, облачного workflow или кастомного воркера.
Очереди и контракт задачи
Синхронный «запрос → ответ LLM → запись в CRM» ломается на таймаутах. Я кладу работу в очередь с явным контрактом.
| Поле задачи | Зачем |
|---|---|
job_id (UUID) | трассировка end-to-end |
idempotency_key | защита от двойной обработки |
type + payload_version | эволюция схемы без сюрпризов |
attempt / max_attempts | ретраи без бесконечного цикла |
priority / not_before | ночные батчи и VIP-очередь |
trace_id | связка логов, LLM-вызовов, side effects |
Правила очереди:
- Продюсер только ставит задачу, не вызывает LLM inline из HTTP-запроса клиента (кроме лёгкого ack).
- Воркер атомарно берёт job (lease/lock), иначе два воркера обработают одно.
- Успех = side effects применены и job закрыт; иначе — retry или DLQ.
- Длинный LLM-вызов — с heartbeat lease, иначе lock истечёт mid-flight.
Минимальные очереди на старте МСП: inbound (сообщения/webhook), agent (рассуждение + tools), outbound (отправка клиенту), hitl (ожидание человека).
Ретраи, DLQ и идемпотентность
Ретрай без идемпотентности = дубли в CRM и двойные сообщения.
| Слой | Политика | Типичная ошибка |
|---|---|---|
| Транспорт (HTTP 429/502) | exponential backoff + jitter | ретрай 500 без потолка |
| Бизнес-ошибка (валидация) | не ретраить, сразу fail/DLQ | 10 повторов «нет email» |
| LLM timeout | retry 1–2 с тем же idempotency_key | новый key на каждый attempt |
| Side effect (письмо, статус) | только идемпотентный apply | «отправил» без записи receipt |
| Poison message | DLQ + алерт человеку | тихий drop |
Идемпотентность на практике:
- Ключ:
source + entity_id + action(напримерtg:chat:msg_id:replyилиcrm:deal:123:set_stage:NEW). - Хранилище ключей: Redis/DB с TTL ≥ окно возможных повторов доставки.
- Side effect: сначала
INSERT receipt WHERE key=…, потом действие; при конфликте ключа — no-op success. - Ответы клиенту: дедуп по
outbound_key, иначе «бот написал дважды».
DLQ — не помойка. У каждой записи: исходный payload, последняя ошибка, attempt, ссылка на trace. Разбор DLQ — еженедельный ритуал, иначе контур «зелёный», а бизнес копит хвосты.
Human-in-the-loop без остановки всего потока
HITL нужен там, где цена ошибки выше цены задержки: скидка, юр. формулировка, удаление данных, atypical scope.
| Паттерн | Как работает | Когда |
|---|---|---|
| Gate before side effect | агент готовит draft → человек Approve/Edit/Reject → outbound | цена, договор, публичный пост |
| Async park | job в статусе waiting_human, SLA таймер | не блокирует остальные jobs |
| Shadow mode | агент пишет recommendation, человек делает сам | первые 1–2 недели пилота |
| Break-glass | стоп-флаг на skill/tool | инцидент, галлюцинации, жалобы |
Чеклист HITL-карточки:
- Что предлагается сделать (diff, не простыня лога).
- Почему агент так решил (
rule_id/ confidence / citations). - Кнопка Approve / Edit / Reject с обязательным комментарием на Reject.
- Таймаут: escalate владельцу или safe-default (обычно «не делать side effect»).
- Запись решения в audit log с
actor=human.
Мониторинг падений: что алертить
Без метрик «агент работает» = «процесс в cron зелёный».
| Сигнал | Порог старта (ориентир) | Действие |
|---|---|---|
depth очереди agent | > N × avg throughput 15 мин | scale worker / throttle inbound |
| age oldest job | > 2× SLA | page on-call |
| error rate 5xx tools | > 5% / 10 мин | circuit breaker на tool |
| DLQ rate | > 0 стабильно 30 мин | разбор + fix |
| duplicate outbound | любой | стоп outbound + postmortem |
| HITL backlog | > SLA человека | эскалация L2, не «ещё промпт» |
| cost per job (tokens) | > 2× baseline | лимит tools / shorter context |
Логи: structured JSON с job_id, idempotency_key, tool, latency_ms, tokens. Трейсы — хотя бы spans: receive → plan → tool → write → send. Без job_id в каждом span разбор ночи бессмысленен.
Production checklist перед боем
- У каждого внешнего webhook — verify signature + идемпотентный ack.
- Нет LLM-вызова в критическом HTTP path пользователя (только enqueue).
-
max_attemptsи backoff заданы; бизнес-ошибки не ретраятся. - Side effects с
idempotency_keyи receipt store. - DLQ + дашборд + алерт, не только лог файла.
- HITL на денежных/юр. действиях; timeout policy записан.
- Circuit breaker на внешние API (CRM, мессенджер, LLM).
- Feature-flag kill-switch агента по каналу за 1 действие.
- Runbook: «API CRM лежит», «LLM 429», «дубль сообщений».
- Тест: повторная доставка того же webhook 3 раза — один side effect.
- Тест: kill worker mid-job — job не теряется, не дублируется дважды успешно.
- Бюджет токенов и rate limit на tool-calling.
Если пункта нет в чеклисте — это ещё demo, даже если демо impresses собственника.
Часто задаваемые вопросы
Нужна ли «настоящая» брокер-очередь или хватит таблицы в Postgres?
На старте МСП часто хватает jobs в Postgres с FOR UPDATE SKIP LOCKED. Брокер (Redis/NATS/Rabbit) имеет смысл при росте воркеров и latency-требованиях. Принципы те же.
Чем идемпотентность отличается от «просто не ретраить»?
Провайдеры и клиенты сами шлют дубли. Даже при max_attempts=1 без ключа получите двойную запись при retry на их стороне.
HITL не убьёт скорость?
Убьёт, если гейтить всё. Гейчу только high-risk side effects; остальное — авто. Shadow mode на 1–2 недели снимает страх без остановки потока.
Что чинить первым при дублях сообщений?
Outbound idempotency + дедуп ключ на канал, потом продюсер webhook. «Поправить промпт» дубли не лечит.
Читайте также
- Очереди, retry и DLQ в автоматизации заявок
- Observability AI-пайплайнов: логи, трейсы, HITL, SLA
- Eval AI-агента: тесты, red team, SLA, регрессии
Собрать production AI-контур под ваш процесс: raisovich.ru
Какие минимальные очереди нужны AI-контуру на старте?
Обычно четыре: inbound (webhook/сообщения), agent (рассуждение и tools), outbound (отправка клиенту) и hitl (ожидание человека) — с job_id, idempotency_key и max_attempts.
Когда бизнес-ошибку нельзя ретраить?
Ошибки валидации (нет email, неверный payload) сразу fail/DLQ: повтор «нет email» десять раз только засоряет очередь и не чинит данные.
Что обязательно проверить перед выводом AI-агента в production?
Идемпотентный ack webhook, side effects с receipt store, DLQ с алертом, HITL на денежных/юр. шагах, kill-switch по каналу и тесты: тройная доставка webhook и kill worker mid-job.
Подпишитесь на @raisovich_news
Первыми получайте новые статьи об AI-автоматизации, нейросетях для бизнеса и создании сайтов. Без спама — только полезный контент.
Часто задаваемые вопросы
Какие минимальные очереди нужны AI-контуру на старте?
Обычно четыре: inbound (webhook/сообщения), agent (рассуждение и tools), outbound (отправка клиенту) и hitl (ожидание человека) — с job_id, idempotency_key и max_attempts.
Когда бизнес-ошибку нельзя ретраить?
Ошибки валидации (нет email, неверный payload) сразу fail/DLQ: повтор «нет email» десять раз только засоряет очередь и не чинит данные.