Skip to Content

PlanAndExecute

from loomflow.architecture import PlanAndExecute, Plan, PlanStep, StepResult

Plan-and-Execute commits to a plan upfront and walks it step-by-step. Wang et al. 2023 (Plan-and-Solve Prompting); He et al. 2025 (Plan-then-Execute Pattern Implementation).

For the conceptual page see Plan-and-Execute.


Class signature

class PlanAndExecute: name: str = "plan-and-execute" def __init__( self, *, max_steps: int = 8, planner_prompt: str | None = None, executor_prompt: str | None = None, synthesizer_prompt: str | None = None, ) -> None: ...

Constructor parameters

max_steps

Typeint
Default8

Hard cap on plan length. The planner sometimes produces a 30-step plan when 5 steps would do. That’s usually a planner failure mode. The architecture truncates to max_steps defensively. Must be >= 1; raises ValueError otherwise.

planner_prompt

Typestr | None
DefaultNone (uses built-in default)

Override the planner’s system prompt. The default teaches the model to emit a JSON list of steps, each a short imperative description. Provide your own when the default doesn’t fit your domain (e.g. domain-specific step shapes, custom output formats).

executor_prompt

Typestr | None
DefaultNone (uses built-in default)

Override the per-step executor prompt. The default seeds each step with the original problem + the plan + prior step outputs, then asks for the step’s result.

synthesizer_prompt

Typestr | None
DefaultNone (uses built-in default)

Override the final synthesizer prompt. The default combines step outputs into a single answer. Customize when you want a different output shape (structured JSON, citations format, etc.).


Methods

declared_workers

Returns {}. Single-agent.

run

Three-phase loop:

  1. Plan. ONE LLM call. Output is a JSON list parsed into a Plan. Emits plan.planner_started / plan.created events.
  2. Execute. Walks plan.steps sequentially. Each step is a text-only model call seeded with the original problem + the plan
    • prior step outputs. Per-step events: step.started / step.completed.
  3. Synthesize. ONE LLM call combining step outputs into the final answer. Writes to session.output.

Empty plan terminates with session.output = "Planner produced no steps; cannot execute." and emits plan.empty_plan.


Plan

class Plan(BaseModel): steps: list[PlanStep]

The planner’s output. Stored on session.metadata["plan"] for introspection.

PlanStep

class PlanStep(BaseModel): description: str

One imperative description of a step. Currently the only field; sub-architecture invocation per step (each step running its own ReAct / etc.) is planned for a future release.

StepResult

class StepResult(BaseModel): step: PlanStep output: str

The result of executing one PlanStep. The synthesizer receives list[StepResult] and produces the final answer.


Cost model

For an N-step plan: 1 (planner) + N (steps) + 1 (synthesizer) LLM calls. ReAct on the same task: roughly N + 1 calls. But each call carries the growing message history. Plan-and-Execute is cheaper when message history is the dominant token cost.


What’s NOT in v1

  • Sub-architecture invocation per step. Each step is a single text-only call, not a fresh ReAct (or any other architecture) invocation. That’s planned for a later release; until then, steps can’t call tools. For tool-heavy plans, use ReWOO.
  • Adaptive replanning. No re-plan after a failed step. The plan is committed at start. Failures surface as the step’s output text.

Example

from loomflow import Agent from loomflow.architecture import PlanAndExecute agent = Agent( "Research the topic and produce a structured brief.", model="claude-opus-4-7", architecture=PlanAndExecute(max_steps=5), ) result = await agent.run("State of vector databases in 2026.")

Or by string:

agent = Agent("...", model="...", architecture="plan-and-execute")

Source

loomflow/architecture/plan_and_execute.py

Plan-and-Execute vs ReWOO. Both are plan-then-execute architectures. PlanAndExecute steps are text-only model calls; ReWOO steps are tool calls with {En} placeholder substitution. Use ReWOO when the plan is “search → fetch → summarize”; use PlanAndExecute when each step is its own reasoning chunk.

Last updated on