Когда в агенте становится больше десяти шагов, инструкция в стиле «сделай всё возможное» ломается. Агент путается в условиях, вызывает не те инструменты, теряет контекст между ветками. Action-Based Workflow Engine — это способ вынести всю механику в набор независимых действий, а агенту оставить только выбор: какое действие и когда вызвать. Паттерн лежит в основе n8n, Zapier, GitHub Actions и любых систем, где шаги переиспользуются в разных сценариях.

Для AI-агента это особенно важно: модель сама решает, какое действие вызвать, но сами действия описаны заранее как типизированные функции с понятной схемой параметров. В результате система остаётся предсказуемой даже при десятках шагов.

Что это

Action-Based Workflow Engine — это архитектурный паттерн, в котором вся логика системы разбивается на атомарные действия. Каждое действие делает ровно одну вещь, имеет имя, описание, схему параметров и функцию-обработчик. Агент (или внешний оркестратор) выбирает действия из набора и вызывает их по цепочке, параллельно или по условию.

Главное отличие от процедурного подхода — каждое действие независимо. Его можно вызвать из любого места, переиспользовать в другом сценарии и тестировать отдельно. В большом агенте это превращает «кашу из условий» в читаемый набор операций, которые видно по именам.

Ключевое правило: действие — это одна функция с одной зоной ответственности. Если в обработчике появляется второе «и» («прочитать страницу и сразу обновить статус») — это два действия.

Зачем нужно

  • Когда шагов становится больше 5–10. Агент уже не может держать их все в одной инструкции без потери контекста.
  • Когда одни и те же операции повторяются в разных сценариях. Например, чтение карточки нужно и в обработке заявок, и в модерации, и в аналитике.
  • Когда нужна прозрачная отладка. Каждое действие логирует вход, выход и ошибку — видно, на каком шаге сломалось.
  • Когда хочется добавлять новые операции без переписывания агента. Достаточно зарегистрировать новое действие в наборе.
  • Когда нужна типобезопасность. Схема параметров действия фиксирует типы — модель не передаст строку вместо объекта.

Как устроено

Любое действие описывается четырьмя обязательными параметрами:

name — уникальный идентификатор. Используется как ключ при вызове из оркестратора и как имя в логах. Примеры: read\_page, send\_message, update\_status.

description — что делает действие и зачем оно нужно агенту. Этот текст уходит прямо в контекст LLM, поэтому от его качества зависит, правильно ли модель выберет действие.

parameters — схема входных данных с типами и описаниями каждого поля. Модель использует её, чтобы заполнить параметры корректно.

handler — функция, которая выполняет логику. Принимает типизированные параметры, возвращает результат, который добавляется в контекст для следующего шага.

Пример регистрации на TypeScript:

const actions = {
  read_notion_page: {
    name: "read_notion_page",
    description: "Прочитать страницу Notion по URL и вернуть содержимое в виде markdown",
    parameters: {
      url: { type: "string", description: "URL страницы Notion" }
    },
    handler: async ({ url }) => {
      const pageId = extractId(url);
      return await notionClient.pages.retrieve({ page_id: pageId });
    }
  },

  send_telegram: {
    name: "send_telegram",
    description: "Отправить сообщение в указанный Telegram-чат",
    parameters: {
      chat_id: { type: "string", description: "ID чата или канала" },
      text:    { type: "string", description: "Текст сообщения" }
    },
    handler: async ({ chat_id, text }) => {
      return await telegram.sendMessage(chat_id, text);
    }
  }
};

Оркестратор устроен как цикл:

  1. Агент получает задачу и текущий контекст.
  2. LLM выбирает одно или несколько действий из набора и заполняет параметры по схеме.
  3. Действия выполняются — последовательно, параллельно или по условию. Результат добавляется в контекст.
  4. LLM снова анализирует состояние: задача завершена или нужно ещё действие.
  5. Цикл повторяется до завершения задачи или до достижения лимита шагов.

Когда использовать

Режимы выполнения:

  • Последовательно (chain). Каждое действие запускается только после завершения предыдущего. Простой и предсказуемый поток — подходит для большинства пайплайнов.
  • Параллельно (parallel). Несколько действий запускаются одновременно, результаты собираются после. Ускоряет выполнение, но требует аккуратной балансировки нагрузки и отсутствия зависимостей между шагами.
  • По условию (conditional). Агент выбирает следующее действие в зависимости от результата предыдущего. Например, если парсинг вернул ошибку — попробовать обходной маршрут через резервный парсер.

Когда паттерн оправдан:

  • Агент выполняет больше 5–10 разных шагов.
  • Разные действия повторяются в разных сценариях.
  • Нужна прозрачность в отладке — понятно, на каком шаге сломалось.
  • Несколько разработчиков работают над одним агентом — действия изолированы и не конфликтуют.

Когда паттерн избыточен:

  • Агент делает 2–3 действия — достаточно простой инструкции без формального набора.
  • Все шаги линейны и никогда не переиспользуются — выделение в отдельные действия добавит бюрократию без выгоды.
  • Логика меняется каждый запуск — динамическая регистрация действий съест больше времени, чем сэкономит.

Пример

Контент-агент, который обрабатывает новые задачи из Notion-инбокса, может использовать пайплайн из десяти действий:

read_inbox_card
  → check_status          # проверить, что карточка новая
  → set_status_processing # статус → «В обработке»
  → read_source_url       # прочитать исходную страницу
  → classify_content      # определить целевую базу
  → write_draft           # написать черновик
  → create_page           # создать страницу в CMS
  → link_result           # привязать результат к инбокс-карточке
  → set_status_done       # статус → «Обработан»

Каждый шаг — отдельная функция со своей схемой параметров. Если что-то сломалось, легко понять, на каком именно шаге это произошло: достаточно открыть лог выполнения и найти первое действие со статусом failed.

Ограничения

Ограничения

Что учитывать

Несколько практических нюансов, которые всплывают при росте числа действий.

Рост описаний действий — каждое описание уходит в контекст LLM.

После 30–40 действий контекст раздувается, и модель начинает путаться. Решение — группировка или динамическая подгрузка.

Стоимость токенов — на длинных сценариях расход растёт заметно. Каждый цикл «выбор

→ выполнение → анализ» добавляет в историю все описания действий.

Зависимость от качества описаний — если description расплывчатое, модель будет выбирать не то действие или передавать не те параметры.

Это самая частая причина «странного» поведения агента.

Холодный старт новых действий — модель не «узнаёт» действие, пока не увидит его в контексте.

Новые операции нужно либо подробно описывать, либо давать примеры использования в description.

Безопасность handler’ов — handler выполняется «как есть», без песочницы.

Любая ошибка в обработчике ломает весь пайплайн, поэтому обработчики нужно писать защищённо и логировать подробно.

Антипаттерны

Антипаттерны

Чего не делать

Частые ошибки при проектировании набора действий.

Не делать: объединять несколько операций в одно действие «для краткости».

«Прочитать страницу и сразу обновить статус» — это два действия, иначе теряется переиспользуемость.

Не делать: передавать в параметрах сырые большие объекты (HTML-страницы, JSON-документы целиком).

Лучше передавать идентификатор, а содержимое читать внутри handler’а.

Не делать: держать описание действия короче одной строки.

Если модель не понимает, зачем действие и когда его вызывать, она выберет не то действие или пропустит нужное.

Не делать: регистрировать 80 действий «на вырост».

При росте числа действий модель начинает путаться. Лучше группировать по доменам или подгружать по контексту.

Не делать: обрабатывать ошибки внутри handler’а «молча».

Если действие упало — это должно быть видно в результате и попадать в контекст для следующего шага.

Чеклист

Чеклист

Проверка перед запуском

Перед тем как отдать агент в работу, пройдитесь по этим пунктам.

Каждое действие делает одно

— нет составных операций с «и» в описании.

Описание содержит когда применять

— модель должна понимать, в каком сценарии действие уместно.

Схема параметров типизирована

— каждый параметр имеет тип и пояснение.

Логирование входа и выхода

— на каждом handler’е есть трассировка, по которой видно, что и зачем вызвалось.

Лимит шагов задан

— оркестратор не зациклится, если модель не придёт к выводу о завершении.

Тест на 2–3 сценариях прошёл

— пайплайн отрабатывает ожидаемо хотя бы на коротких сценариях, прежде чем идти в прод.

Ссылки

Ссылки