Перейти к содержимому

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

Антипаттерны — это повторяющиеся ошибки проектирования workflow, которые приводят к сломанным, неэффективным или неподдерживаемым workflow. Workflow Management Flow (WMF) автоматически проверяет их при создании и редактировании.

Директива говорит агенту собрать данные, затем inputSchema просит агента вернуть эти же данные как структурированный вывод. Агент работает как оператор ввода данных, копируя из вывода инструмента в поля схемы.

Обнаружение: inputSchema повторяет структуру данных, которые агенту было поручено собрать.

❌ Directive: "Get project info from package.json"
inputSchema: { project_name: string, version: string, description: string }
// Агент копирует данные из файла в поля схемы — бессмысленный кругооборот
✅ Use expression node to extract data, or capture agent's ANALYSIS in inputSchema
inputSchema: { architecture_assessment: string, risks_identified: string[] }

У узла нет inputSchema, но директива указывает агенту выполнить побочные эффекты (создать файлы, запустить команды). Никаких свидетельств о выполненном не сохраняется.

Обнаружение: Узел agent-directive без inputSchema, где директива описывает действия с наблюдаемыми результатами.

❌ Directive: "Create test files for auth module" (no inputSchema)
// Workflow не знает, что было создано и было ли выполнено успешно
✅ inputSchema: { files_created: string[], tests_passing: boolean }
// Свидетельства завершения сохраняются в контексте workflow

Системное соображение. Движок хранит переменные как объекты {description, value}. Не применимо на уровне отдельного workflow — следуйте формату, который ожидает движок.

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

Обнаружение: Цикл ревью/исправления, где узел исправления получает обратную связь только через текст inputSchema, а не через персистентный файл.

❌ Review node → inputSchema: { feedback: string } → Fix node reads feedback from input
// Обратная связь эфемерна, теряется при повторе
✅ Review node writes review.md → Fix node reads review.md
// Результаты сохраняются между итерациями и повторами

Директива говорит «исправляй пока не будет готово» без явной структуры цикла в графе. Агент повторяет попытки внутренне без контроля workflow.

Обнаружение: Слова вроде «retry», «keep trying», «fix until» в директиве без соответствующего условного узла, создающего цикл в графе.

❌ Directive: "Keep fixing tests until they all pass"
// Нет структуры графа, агент зацикливается внутренне без контроля workflow
✅ [fix] → [run-tests] → condition(passed?) → [fix] / [next]
// Явный цикл в графе с видимостью каждой итерации для workflow

Циклы валидации без лимитов итераций или путей эскалации. Могут выполняться бесконечно, если условие никогда не будет выполнено.

Обнаружение: Цикл в графе без переменной-счётчика итераций или без условия проверки лимита итераций.

❌ Loop: [action] → [check] → [fix] → [action] (бесконечно, если качество никогда не пройдёт)
✅ Expression node increments counter → Condition: iterations > max → escalation path
// Агент не может застрять — после N попыток эскалация пользователю

Хранение динамических данных, генерируемых в ходе выполнения workflow (содержимое файлов, ответы API, HTML-вывод, результаты извлечения) в переменных workflow. Эти переменные внедряются в каждую директиву через шаблоны, раздувая контекст потенциально неограниченным содержимым.

Обнаружение: Переменные, получающие динамический контент через inputSchema во время выполнения, особенно контент >1KB или контент, растущий неограниченно.

Область применения: Этот антипаттерн относится к данным, передаваемым между шагами workflow — НЕ к статической конфигурации, хранящейся в initialData при запуске workflow. См. паттерн Статическая конфигурация workflow для понимания различия.

❌ inputSchema: { html_content: string }
Next directive: "Publish {{step.html_content}}"
// Целая HTML-страница хранится в переменной, внедряется в каждую последующую директиву
❌ inputSchema: { extraction_results: object }
Next directive: "Analyze {{extraction_results}}"
// Потенциально большие данные извлечения передаются туда-обратно через переменные
✅ Directive: "Save HTML to {{workspace_path}}/report.html"
inputSchema: { file_path: string }
Next directive: "Publish file at {{step.file_path}}"
// В переменной хранится только путь, агент читает файл по необходимости

Исключение: Статический инструктивный контент в initialData (правила, стандарты, чек-листы) — это правильный паттерн, а не злоупотребление переменными. Они намеренно размещены, чтобы агент видел их на каждом соответствующем шаге. См. Статическая конфигурация workflow.

Системное соображение. systemReminder статичен и применяется ко ВСЕМ шагам. Инструкции для конкретных шагов должны быть в директивах узлов, а не в systemReminder.

Агент вручную отслеживает индексы массивов, счётчики или пагинацию через inputSchema. Подвержено ошибкам и ломается при повторе.

Обнаружение: inputSchema с полями вроде current_index, next_item_number или значениями счётчиков, которые агент должен вычислять.

❌ inputSchema: { current_index: number, next_item: string }
// Агент выполняет арифметику, подвержен ошибкам
✅ Expression node: current_index = {current_index} + 1
Directive: "Process {{items[{current_index}]}}"
// Движок workflow обрабатывает арифметику детерминированно

Передача всего JSON workflow через параметры MCP-инструмента для больших workflow. Упирается в лимиты размера.

Обнаружение: manage({ action: "create", workflow: <large JSON> }) с workflow >50KB.

❌ manage({ action: "create", workflow: <50KB JSON> })
// Может упереться в лимиты размера параметров
✅ token({ action: "upload" }) → HTTP PUT with file content
// Загрузка по токену обрабатывает любой размер

Копирование информации, уже имеющейся в контексте агента, в переменные workflow. Избыточно и раздувает контекст.

Обнаружение: inputSchema, захватывающая данные, которые агент уже имеет в контексте разговора (например, списки директорий, информация о проекте из предыдущего анализа).

❌ variable: project_structure = "<output of tree command>"
// Агент уже имеет это в контексте; повторное хранение тратит токены
✅ Let agent re-read current data when needed. Store only stable references (paths, IDs).

#12: Вынесение критических инструкций в файлы

Заголовок раздела «#12: Вынесение критических инструкций в файлы»

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

Обнаружение: Директива говорит «прочитай правила из файла X» для контента, который должен быть стабильно доступен. Инструкции, критичные для поведения агента, хранятся вне workflow.

❌ Directive: "Read planning standards from ./standards.md before creating plan"
// Агент может пропустить чтение, вспомнить из обучающих данных или прочитать выборочно
// Дополнительная операция ввода-вывода на каждом шаге, требующем этих правил
✅ Store in initialData variable: planning_standards = "1. Each step must... 2. Tests built-in..."
Directive: "Create plan following {{planning_standards}}"
// Движок workflow гарантирует доставку; нет ввода-вывода; нет риска галлюцинаций

Правильный способ итерации по элементам массива:

1. Store array: items = ["a", "b", "c"]
2. Store index: current_index = 0
3. Directive: "Process item {{items[{current_index}]}}"
4. Expression: current_index = {current_index} + 1
5. Condition: {current_index} < items.length → loop / continue
[implement] → [review-to-file] → [check-issues] → [fix-from-file] → [review-to-file]
no issues → [next]