Паттерн цикла валидации
Назначение
Обеспечивает качество путём проверки результатов и повторного выполнения, если они не соответствуют критериям. Предотвращает прохождение некачественных результатов дальше.
Структура
[action] → [check] → success → [next] ↓ failure → [fix] → [increment-iteration] → [action]Реализация
Нода действия
{ "type": "agent-directive", "id": "do-work", "directive": "Complete the task. Iteration: {{current_iteration}}", "completionCondition": "Task completed with quality standards met", "inputSchema": { "type": "object", "properties": { "result": { "type": "string" }, "quality_check_passed": { "type": "string", "enum": ["yes", "no"] } }, "required": ["result", "quality_check_passed"] }, "connections": { "success": "check-quality" }}Нода проверки
{ "type": "condition", "id": "check-quality", "condition": { "operator": "eq", "left": { "contextPath": "quality_check_passed" }, "right": "yes" }, "connections": { "true": "next-step", "false": "fix-issues" }}Нода исправления
{ "type": "agent-directive", "id": "fix-issues", "directive": "Fix issues found in iteration {{current_iteration}}. Previous result: {{result}}", "connections": { "success": "increment-iteration" }}Счётчик итераций
С использованием expression ноды:
{ "type": "expression", "id": "increment-iteration", "expressions": ["current_iteration = current_iteration + 1"], "connections": { "default": "do-work" }}Всегда включайте счётчики итераций для предотвращения бесконечных циклов. Рекомендуется добавить проверку максимального количества итераций.
С ограничением итераций
Добавьте проверку перед повторной попыткой:
{ "type": "condition", "id": "check-max-iterations", "condition": { "operator": "lt", "left": { "contextPath": "current_iteration" }, "right": 5 }, "connections": { "true": "do-work", "false": "escalate-to-user" }}Ограниченный цикл ре-валидации
Цикл ре-валидации или ре-ревью на каждом круге возвращается к ОДНОЙ И ТОЙ ЖЕ ноде проверки. Без подсказки в директиве входа в цикл агент может ошибочно воспринять повторное появление той же ноды как зацикливание и сообщить о цикле пользователю. Два требования предотвращают это.
Счётчик — это expression нода
Счётчик кругов ДОЛЖЕН инкрементироваться expression нодой (автоматически потоком), объявленной в variableRegistry с числовым default. Счётчик, инкрементируемый агентом, — это антипаттерн: агента не просят выполнять арифметику, а отсутствующее или нечисловое значение ломает проверку предела.
{ "variableRegistry": { "validation_round": { "type": "number", "description": "Re-validation pass counter", "default": 0 }, "max_validation_rounds": { "type": "number", "description": "Re-validation bound", "default": 5 } }}{ "type": "expression", "id": "increment-validation-round", "expressions": ["validation_round = validation_round + 1"], "connections": { "default": "re-validate" }}Подсказка входа в цикл
Директива входа в цикл отображает счётчик кругов и сообщает, что повторение ожидаемо:
{ "type": "agent-directive", "id": "re-validate", "directive": "Re-validation pass {{validation_round}} of {{max_validation_rounds}} — a normal quality loop, expected to converge. This is NOT a bug and NOT a stuck flow; do not report a loop to the user.\n\nRe-check the work against the criteria and report whether all issues are resolved.", "completionCondition": "Work re-checked against criteria", "inputSchema": { "type": "object", "properties": { "all_resolved": { "type": "string", "enum": ["yes", "no"] } }, "required": ["all_resolved"] }, "connections": { "success": "check-resolved" }}Текст подсказки точный. Ре-валидация через одну и ту же ноду ожидаема, а не баг — директива должна это сообщать, иначе агент может остановиться и сообщить о ложном цикле.
Числовая проверка качества
Для свойства, которое машина решает сама, маршрутизируйте по её же ответу — числу воспроизводимых находок, коду возврата, количеству пробелов покрытия:
{ "inputSchema": { "properties": { "issues_count": { "type": "number", "minimum": 0 } }, "required": ["issues_count"] }}{ "condition": { "operator": "eq", "left": { "contextPath": "issues_count" }, "right": 0 }}Не маршрутизируйте по баллу качества. Число, которое рецензент присваивает связности, глубине или архитектуре, не различает два состояния результата — семь против восьми не говорит читателю ничего проверяемого, — а порог достигается подгонкой самого числа. Там, где свойство качественное, гейт — это обоснованный вердикт рецензента и число находок, к которым он привёл. См. Фиксированная оценка семантического качества.
Реальный пример
Из development-flow.json:
{ "id": "verify-step-implementation", "directive": "Verify step {{current_step_name}} implementation:\n- Expected: {{expected_outcome}}\n- Check actual matches expected", "inputSchema": { "properties": { "step_verified": { "type": "string", "enum": ["yes", "no"] }, "verification_evidence": { "type": "string" } }, "required": ["step_verified", "verification_evidence"] }}Поведение агента на воротах валидации
Когда workflow включает ворота валидации (ноды, запрашивающие подтверждение пользователя), агент должен следовать строгим правилам:
Паттерн директивы ворот валидации
Директива гейта говорит, что записывает её ответ и куда ведёт каждый вариант, — тогда агент видит, что честный ответ и есть единственный способ провести прогон правильно:
`approval` записывает собственный ответ пользователя. Всё, кроме безоговорочного «да», — это «нет»,и замечания идут в `user_feedback`: флоу направляет «нет» той ответственности, которой принадлежитправка, поэтому исправление, сделанное здесь, — изменение, которого никто не рецензировал.Почему это важно
Гейт существует, чтобы передать решение тому, кому оно принадлежит. Агент, прочитавший ответ как
«мелкие правки, которые я применю сам», выдаёт работу, не прошедшую путь правки и ревью, а
approval = "yes", записанное поверх замечаний, теряет сами замечания. Названное следствие — куда
уходит «нет» и что закрывает «да» — и делает честный ответ полезным.
Пример ворот валидации
{ "type": "agent-directive", "id": "approve-plan", "directive": "Представь план и спроси, утверждён ли он.\n\nПлан: {{plan_summary}}\n\n`approval` записывает собственный ответ пользователя: всё, кроме безоговорочного «да», — это «нет», с точными словами в `user_feedback`. «Нет» ведёт к ответственности, которой принадлежит ревизия, поэтому исправление, сделанное здесь, — изменение, которого никто не рецензировал.", "completionCondition": "User confirmed or rejected plan", "inputSchema": { "type": "object", "properties": { "plan_approved": { "type": "string", "enum": ["yes", "no"] }, "user_feedback": { "type": "string" } }, "required": ["plan_approved"] }, "connections": { "success": "route-plan-approval" }}Связанные паттерны
- Верификация шагов - Проверка конкретных шагов
- Эскалация - Обработка повторяющихся сбоев