Plan and Execute

Plan-and-Execute — паттерн оркестрации, разделяющий Planner («что делать» — план) и Executor («как делать» — вызов инструментов). Это второй базовый подход к рассуждению агента наряду с ReAct: ReAct планирует онлайн пошагово, Plan-and-Execute сначала строит план, потом исполняет.

Суть

Вместо того чтобы на каждом шаге думать и сразу действовать (ReAct), агент сначала формирует план целиком, а затем отдельный слой его исполняет. Разделение ролей делает поведение прозрачнее и дешевле.

Зачем это нужно

Главная мысль: «не забивать гвозди микроскопом». LLM может сделать простое сложение, но сожжёт тысячи токенов — поэтому сначала решаем что нужно (план), а как — отдаём подходящему инструменту/коду, не тратя дорогой reasoning впустую. Это снижает стоимость (см. Agent CostControl).

Как работает

  • ReAct — онлайн-планирование step-by-step; состояние неявно закодировано в контексте; управление через max_steps / stop-rules.
  • Plan-and-Execute — сначала план (список шагов/изменений), затем исполнение; состояние явное.
  • Роли Planner / Coder / Reviewer — логически разные даже при одной LLM (разные промпты/ограничения): Planner понимает задачу и планирует, Coder делает, Reviewer проверяет результат по чек-листу. Ревью-роль критична.
  • Architect/Editor split — экономический вариант planner/executor: «умная» дорогая модель проектирует короткий план, «дешёвая быстрая» печатает код по нему (экономия 50–80%, см. Agent CostControl). Развитие ревью-роли — внешний оценщик Generator Evaluator (Planner/Generator/Evaluator), т.к. самооценке агента доверять нельзя.
  • Условия выхода общие для обоих: Success, User Feedback (позитивные); Max iterations / Max tokens / Max time / No Progress (негативные).
  • Опирается на компоненты Agent Anatomy и питается ground truth, как и ReAct.

Пример

PLAN (Planner):
  1. найти клиента по email
  2. проверить статус заказа
  3. оформить возврат
EXECUTE (Executor):
  step1 → tool find_customer(...)
  step2 → tool get_order_status(...)
  step3 → tool create_refund(...)  # реальное действие

Когда что и как заставить ревьюера работать

ReAct против Plan-and-Execute — та же развилка, что между агентом и воркфлоу, только на уровень ниже. ReAct уместен, когда следующий шаг определяется результатом предыдущего и план заранее не выписывается. Plan-and-Execute — когда задача декомпозируется до начала работы: тогда план строится один раз дорогой моделью, а исполнение идёт дешёвой, что заодно даёт экономию (Agent CostControl, Architect/Editor). Признак неправильного выбора: план, который переписывается почти на каждом шаге — значит, задача на самом деле реактивная.

Чтобы ревьюер не штамповал ОК, нужны три вещи, и первая — не про промпт. Ревьюер должен быть внешним по отношению к исполнителю: самооценка не работает, модели уверенно хвалят собственную работу (Generator Evaluator). Дальше — бинарные критерии вместо шкалы: «прошло / не прошло» по каждому пункту, а не «оцени качество», иначе средняя оценка всегда выходит приемлемой. И третье — всё, что проверяется кодом, до ревьюера не доходит: схема, лимиты, существование сущностей проверяются детерминированно, а модели остаётся только то, что кодом не выражается (LLM as Judge).

Спектр reasoning-паттернов и цена каждого

Plan-and-Execute — не крайняя точка спектра, а середина. Полезно видеть весь ряд, потому что выбор здесь — это в первую очередь выбор расхода токенов:

Паттерн Принцип Расход токенов Область применения
Chain-of-Thought Пошаговая цепочка в рамках одного вызова Минимальный (1 вызов) Математика, логика, классификация без внешних данных
ReAct Мысль → Действие → Наблюдение, циклично Очень высокий Непредсказуемые исследовательские задачи, диалог
Plan-and-Execute Планировщик формирует список шагов один раз, исполнители закрывают Средний Задачи с понятной заранее структурой
ReWOO План с переменными-заглушками, параллельный запуск инструментов Низкий (экономия до 60%) Аналитические отчёты, сбор данных из независимых API
LLM Compiler DAG задач, инструменты запускаются по готовности аргументов Минимальный среди сложных Высоконагруженные конвейеры со сложными зависимостями

ReWOO отличается от обычного планирования одной деталью, которая и даёт экономию: план строится с переменными-заглушками вместо реальных результатов, поэтому наблюдения не возвращаются в модель между шагами. Модель вызывается дважды — на планирование и на финальную сборку, — а не на каждой итерации.

LLM Compiler идёт дальше и строит из плана направленный ациклический граф: инструмент запускается, как только готовы его аргументы, а не когда до него дошла очередь в списке. Выигрыш здесь уже не только в токенах, но и во времени ответа за счёт параллелизма.

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

Список задач с одним активным пунктом

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

Механика минимальна: пункты со состояниями «ожидает», «в работе», «сделано», и ровно одно правило, которое агент не может обойти: в работе одновременно не больше одного пункта. Попытка начать второй отклоняется.

Ценность именно в ограничении, а не в списке. Список без него превращается в декларацию намерений, которую агент пополняет вместо того, чтобы закрывать. Одно активное дело делает прогресс наблюдаемым: в любой момент видно, что именно делается сейчас, и это же попадает в поток событий для интерфейса (Agent Harness).

Обратная сторона — на одношаговой задаче список пропускается. Декомпозиция задачи из одного шага стоит дороже самой задачи, и агент, заводящий список ради списка, тратит ходы впустую.

Список надо не только вести, но и перечитывать

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

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

Работает это по механической причине: чтение помещает план в конец контекста, туда, где внимание модели выше всего, и делает это заново на каждом круге. Инструмент чтения нужен именно отдельный, потому что пересказ по памяти воспроизводит не список, а представление о нём.

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

Связано с

  • ReAct — второй базовый паттерн рассуждения (онлайн vs план-вперёд)
  • AI Agent — оба паттерна — способ реализовать «мозг» агента
  • Agent Anatomy — оркестрация как компонент
  • Generator Evaluator — Planner/Generator/Evaluator: ревью выносится во внешний оценщик
  • Agent Architecture — где планировщик встраивается в master loop