У большинства 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 позволяют строить циклы: агент может повторить шаг с изменёнными параметрами, пока не будут достигнуты критерии качества.
Почему это важно
Свободная компоновка человеко-агентных цепочек
Поскольку подтверждения и шаги агента разделяют одну модель вывода, их можно свободно компоновать:
- Агент генерирует план релиза → человек подтверждает → агент выполняет
- Человек регистрирует баг → агент триажирует → агент исправляет → человек ревьюит фикс
- Агент прогоняет QA → gate проверяет покрытие → человек подтверждает деплой
Никакого склеивающего кода для границы человек-агент. Движок выражений if вычисляет выводы шагов единообразно.
Наблюдаемость по умолчанию
Каждый шаг — человеческий или агентный — производит одинаковые переходы состояний: pending → running → waiting/completed/failed. Хранилище состояний воркфлоу (Redis через контракт ICache) отслеживает все шаги идентично.
Аудитабельность
Поскольку решения людей — это выводы шагов (а не внешние webhook-пэйлоады), они часть записи выполнения воркфлоу. Кто подтвердил, когда, с каким комментарием — всё запрашивается через тот же API, что показывает выводы агентов.
Принцип дизайна
Автоматизация — не про удаление людей из цикла. Она про то, чтобы цикл был одинаковым вне зависимости от того, кто в нём участвует. Когда люди и агенты работают на одних рельсах, единственный вопрос — кто должен обрабатывать этот шаг, а не как иначе подключить этот шаг, если его обрабатывает человек.
Это workflow-движок, масштабирующийся вместе с вашей зрелостью автоматизации. Начинаете с преимущественно человеческих шагов и нескольких автоматических проверок. Постепенно заменяете человеческие шаги агентными по мере роста доверия. Форма воркфлоу не меняется — только поле uses.