Workflow-движок, который не различает людей и агентов

← All posts

У большинства workflow-движков две модели выполнения: одна для автоматических шагов (вызвать API, запустить скрипт) и другая для человеческих (отправить уведомление, ждать подтверждения). Автоматический путь быстрый и типизированный. Человеческий — специальный случай, прикрученный через вебхуки и поллинг.

В воркфлоу KB Labs нет этого различия. Подтверждение человека и решение агента — оба шаги: одинаковый тип, одинаковая модель выполнения, одинаковая машина состояний. Мы называем это «same rails».

Как выглядит воркфлоу

# deploy-review.yml
name: Deploy Review
version: 1
on:
  event: deploy.requested
jobs:
  review:
    runs_on: local
    steps:
      - id: ai_review
        uses: plugin:@kb-labs/review/analyze
        with:
          scope: changed-files
      - id: approval
        uses: builtin:approval
        if: ${{ steps.ai_review.outputs.risk > 'medium' }}
      - id: deploy
        uses: plugin:@kb-labs/deploy/execute
        if: ${{ steps.approval.outputs.approved }}
        with:
          environment: staging

Три шага: ИИ-агент анализирует изменения, человек подтверждает если риск выше среднего, деплой выполняется если подтверждено. Все три — объекты StepSpec с uses, with, if и id. Движок не знает, какой из них предполагает участие человека.

Как «same rails» работает технически

Интерфейс Runner

Каждый шаг выполняется через единый интерфейс:

interface Runner {
  execute(request: StepExecutionRequest): Promise<StepExecutionResult>;
}

SandboxRunner обрабатывает плагин-хендлеры (в изолированном процессе). LocalRunner — встроенные функции (в процессе демона). Оба реализуют Runner. Планировщик не знает, какой из них запустит конкретный шаг.

Подтверждение как шаг, а не особый случай

Хендлер builtin:approval приостанавливает выполнение, возвращая status: 'waiting_approval'. Workflow-движок воспринимает это как любое другое состояние ожидания — шаг не завершён, значит, последующие не запускаются.

Когда человек разрешает подтверждение (через REST API), шаг завершается с ApprovalOutput — включающим approved: boolean, выполненное действие и опциональный комментарий. Последующие шаги ссылаются на этот вывод через ${{ steps.approval.outputs.approved }} — ровно тот же синтаксис, что и для вывода любого другого шага.

Gates для агентной маршрутизации

builtin:gate — эквивалент подтверждения на стороне агента. Вместо ожидания человека вычисляет выражение-решение и маршрутизирует выполнение: continue, fail или restartFrom (с контекстом). Gates позволяют строить циклы: агент может повторить шаг с изменёнными параметрами, пока не будут достигнуты критерии качества.

Почему это важно

Свободная компоновка человеко-агентных цепочек

Поскольку подтверждения и шаги агента разделяют одну модель вывода, их можно свободно компоновать:

Никакого склеивающего кода для границы человек-агент. Движок выражений if вычисляет выводы шагов единообразно.

Наблюдаемость по умолчанию

Каждый шаг — человеческий или агентный — производит одинаковые переходы состояний: pending → running → waiting/completed/failed. Хранилище состояний воркфлоу (Redis через контракт ICache) отслеживает все шаги идентично.

Аудитабельность

Поскольку решения людей — это выводы шагов (а не внешние webhook-пэйлоады), они часть записи выполнения воркфлоу. Кто подтвердил, когда, с каким комментарием — всё запрашивается через тот же API, что показывает выводы агентов.

Принцип дизайна

Автоматизация — не про удаление людей из цикла. Она про то, чтобы цикл был одинаковым вне зависимости от того, кто в нём участвует. Когда люди и агенты работают на одних рельсах, единственный вопрос — кто должен обрабатывать этот шаг, а не как иначе подключить этот шаг, если его обрабатывает человек.

Это workflow-движок, масштабирующийся вместе с вашей зрелостью автоматизации. Начинаете с преимущественно человеческих шагов и нескольких автоматических проверок. Постепенно заменяете человеческие шаги агентными по мере роста доверия. Форма воркфлоу не меняется — только поле uses.