Документация Triggo
Интеграция с агентами

Сценарии подтверждения

Закрывайте ответственные действия человеческим подтверждением — просматривайте, подтверждайте и отклоняйте запуски, ожидающие решения, через runtime API или MCP.

Автоперевод — в процессе проверки

Сценарии подтверждения

Подтверждения позволяют workflow приостановиться для решения человека перед дорогостоящим или необратимым шагом — отправкой внешнего сообщения, удалением записи, переводом денег, применением автономного исправления. В workflow можно настроить обязательное подтверждение для конкретных действий или шагов; такие запуски во время работы находятся в состоянии waiting_for_approval, пока человек (или агент с нужными правами) не подтвердит или не отклонит их. Эта страница описывает поверхность принятия решений, доступную агентам: просмотр ожидающих запусков, подтверждение или отклонение через REST или MCP и обработку истечения.

Жизненный цикл

При попадании запуска в точку подтверждения вместе движутся две записи: строка runs, отслеживающая выполнение, и строка approval_requests, хранящая состояние решения, комментарий и аудит-трейл.

У самого запроса на подтверждение четыре конечных состояния:

                         approve_run / POST approve (decision=approved)
                 ┌──────────────────────────────────────────────────────▶ approved

   pending ──────┤
                 │                         POST approve (decision=rejected)
                 ├──────────────────────────────────────────────────────▶ rejected

                 │   TTL 1 ч, воркер approval-expiry
                 └──────────────────────────────────────────────────────▶ expired

Родительский запуск движется синхронно: waiting_for_approvalrunning при подтверждении, cancelled при отклонении, timed_out при истечении. Переход фиксируется только после постановки job'а на возобновление, поэтому сбой Redis не оставит запуск в состоянии running без соответствующего job'а у исполнителя.

Получение запусков, ожидающих решения

GET /api/v1/runtime/runs с needs_approval=true сужает список до запусков, которые сейчас приостановлены в точке подтверждения. Эндпоинт требует право runs:read и принимает такие фильтры — все опциональные:

Query-параметрТипЗначение
needs_approvaltrue | falseПри true возвращает только запуски в waiting_for_approval.
action_slugstringФильтр по одному опубликованному действию.
statusstringЯвный фильтр по статусу (например, waiting_for_approval, failed).
sourcestringaction, replay, scheduler и т. д.
has_incidenttrue | falseЗапуски, связанные с инцидентом или нет.
date_from, date_toISO-8601Ограничение по created_at.
limitinteger, 1–100, по умолчанию 20Размер страницы.
offsetinteger, по умолчанию 0Смещение страницы.
curl -sS 'https://api.triggo.ai/api/v1/runtime/runs?needs_approval=true&limit=20' \
  -H "Authorization: Bearer $TRIGGO_API_KEY"

Ответ содержит по одной строке на запуск:

{
  "runs": [
    {
      "run_id": "3f2e…",
      "action_slug": "send_refund",
      "source": "action",
      "status": "waiting_for_approval",
      "duration_ms": null,
      "created_at": "2026-04-13T09:41:12.004Z"
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}

Чтобы получить полный контекст подтверждения (строку ожидающего approval_requests, разрешённые входы, описание, срок истечения), вызовите GET /api/v1/runtime/runs/:runId для нужного запуска.

Подтверждение или отклонение через REST

Тот же эндпоинт обрабатывает оба решения. Поле decision в теле выбирает исход.

POST /api/v1/runtime/runs/:runId/approve
Authorization: Bearer <key>   (право: approvals:decide)
Content-Type: application/json

{
  "decision": "approved" | "rejected",
  "comment": "опционально, до 1000 символов"
}
curl -sS -X POST https://api.triggo.ai/api/v1/runtime/runs/3f2e…/approve \
  -H "Authorization: Bearer $TRIGGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"decision":"approved","comment":"verified refund with support thread"}'

При успехе вы получаете:

{
  "run_id": "3f2e…",
  "status": "running",
  "decision": "approved",
  "decided_at": "2026-04-13T09:42:03.118Z"
}

Отклонение возвращает "status": "cancelled". comment усекается на сервере до 1000 символов и записывается в строку approval_requests вместе с userId и decided_via: "api", что попадает в аудит-лог (approval.decided).

Подтверждение через MCP

MCP предоставляет ту же операцию как инструмент approve_run. То же право (approvals:decide), та же форма payload'а, тот же результат.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "approve_run",
    "arguments": {
      "run_id": "3f2e…",
      "decision": "approved",
      "comment": "verified refund with support thread"
    }
  }
}

decision должно быть "approved" или "rejected"; comment опционален и ограничен 1000 символами Zod-схемой инструмента. Результат зеркалит REST-ответ.

Истечение

Каждый запрос на подтверждение создаётся с TTL 1 час. При создании планируется BullMQ-job approval-expiry, чей jobId выводится из id подтверждения, поэтому решение, принятое внутри окна, чисто снимает job истечения — нет гонки, когда подтверждённый пользователем запуск через мгновение уходит в expired.

Если TTL истекает без решения, approval-expiry.worker фиксирует запрос как expired, пишет запись аудита approval.decided с decision: "expired", а если подтверждение связано с запуском пайплайна — журналирует ошибку шага APPROVAL_EXPIRED и переводит запуск в timed_out. Пользователю в его канале уведомлений приходит сообщение, что запрос истёк и был автоматически отклонён.

На практике истёкшее подтверждение эквивалентно отклонению с точки зрения запуска: шаг не выполняется, workflow не продолжается. Различие важно для аналитики и разбора инцидентов — expired означает «никто не принял решение вовремя», а не «человек сказал нет».

Ошибки

Эндпоинт и инструмент MCP используют одинаковые коды ошибок. HTTP-статус выводится runtime'ом из каждого кода; MCP возвращает isError: true с той же строкой code.

КодСтатусКогда
UNAUTHORIZED401Отсутствующий, некорректный или отозванный Bearer-ключ.
FORBIDDEN403Ключ валиден, но не имеет approvals:decide.
RUN_NOT_FOUND404В этом рабочем пространстве нет запуска с таким id.
BAD_REQUEST400decision не "approved" и не "rejected"; запуск не в состоянии waiting_for_approval; или подтверждение уже разрешено конкурентным вызовом.
RATE_LIMIT_EXCEEDED429Достигнут лимит скользящего окна — отступите по заголовку retry-after.

Случай «уже разрешено» (BAD_REQUEST с сообщением "Approval already resolved") стоит обработать аккуратно: два агента гонятся за одним запуском или пользователь и агент решают одновременно. Обновление атомарно — UPDATE … WHERE status = 'pending' — поэтому выигрывает ровно один вызывающий. Проигравшие должны заново прочитать запуск и сверить поведение с его новым статусом.

Связанное

On this page