Foundations ⏱️ 9 min read

Planning & Reasoning Strategies: From CoT to Plan-and-Solve and Reflexion

Beyond naive next-token prediction: how high-performance agents decompose ambiguous goals using Plan-and-Solve DAGs, Tree-of-Thoughts search, and Reflexion verbal reinforcement loops.

A naive agent reacts impulse-by-impulse. When presented with a multi-step objective (e.g., "Audit our Q3 cloud infrastructure, identify compute cost anomalies, cross-reference against engineering sprints, and prepare an executive summary"), an unguided model starts executing the first tool that comes to mind.

Without structured planning, agents fall prey to premature optimization, myopic dead-ends, and exponential backtrack costs.

In this fourth article of our series, we move into the executive center of agentic intelligence: Planning and Reasoning Strategies. We compare the evolution of cognitive decomposition patterns and implement a production-grade Plan-and-Execute engine in Python.


1. The Evolution of Machine Reasoning

Over the last three years, reasoning architectures have progressed through four distinct paradigms:

1. Zero-Shot Direct      [Input Prompt] ───────────────────────────> [Final Answer]
                                                                        (High error rate)

2. Chain-of-Thought       [Input] ──> [Step 1] ──> [Step 2] ────────> [Final Answer]
                                                                        (Linear reasoning)

3. Plan-and-Solve        [Input] ──> [Decompose into Plan DAG]
                                               │
                                     ┌─────────┴─────────┐
                                     ▼                   ▼
                                [Sub-task 1]        [Sub-task 2] ───> [Synthesis]

4. Reflexion / Tree      [Input] ──> [Generate Multiple Branches]
                                               │
                                     [Evaluate & Prune Dead Ends]
                                               │
                                     [Reflect on Failure -> Retry]

Comparative Analysis of Reasoning Strategies

Reasoning Strategy Decision Topology Primary Advantage Primary Drawback
Chain-of-Thought (CoT) Linear Sequence Unlocks multi-step arithmetic & logical deduction. Cannot backtrack if an early step is flawed.
Plan-and-Solve Decoupled DAG Separates high-level planning from mechanical tool execution. Requires accurate upfront task estimation.
Tree-of-Thoughts (ToT) Branching Tree Search Evaluates multiple paths; prunes unpromising directions. High token cost; increased execution latency.
Reflexion (Verbal RL) Feedback Loop Learns from environmental failure traces via self-critique. Can enter self-reinforcing delusion loops if ungrounded.

2. The Plan-and-Execute Architecture

In enterprise applications, the Plan-and-Execute pattern outperforms naive ReAct loops by decoupling Strategy from Tactics:

  1. Planner Agent: Analyzes the user goal and generates an immutable or semi-mutable directed list of sub-tasks.
  2. Execution Worker: Focuses exclusively on solving the immediate sub-task using available tools.
  3. Replanner / Re-evaluator: After each step, checks whether the overarching goal has been reached or if the remaining plan requires dynamic adjustment.
from pydantic import BaseModel, Field
from typing import List, Optional
import json

class SubTask(BaseModel):
    id: int
    title: str = Field(..., description="Short summary of the sub-task")
    tool_name: Optional[str] = Field(None, description="Recommended tool to invoke")
    status: str = Field("PENDING", description="PENDING, IN_PROGRESS, COMPLETED, FAILED")
    output: Optional[str] = None

class ExecutionPlan(BaseModel):
    goal: str
    steps: List[SubTask]
    current_step_index: int = 0

    def mark_completed(self, step_id: int, result: str):
        for s in self.steps:
            if s.id == step_id:
                s.status = "COMPLETED"
                s.output = result
        self.current_step_index += 1

    def is_finished(self) -> bool:
        return self.current_step_index >= len(self.steps)

3. Implementing Reflexion: Self-Correction via Verbal Critique

When a sub-task fails, naive agents simply retry the same broken prompt. In Reflexion (Shinn et al., 2023), the agent intercepts its own failure trace and writes a verbal self-reflection:

class ReflexionEvaluator:
    """Generates verbal critiques when an agent encounters unexpected failures."""

    CRITIQUE_PROMPT_TEMPLATE = """
    You are an AI Self-Correction Critic. An agent attempted an action and failed.

    [USER GOAL]: {goal}
    [ACTION ATTEMPTED]: {action}
    [ENVIRONMENT OBSERVATION / ERROR]: {error}

    Provide an internal critique addressing:
    1. Why did the action fail?
    2. What assumption was incorrect?
    3. What concrete modification should be applied on the next attempt?

    Emit strictly JSON conforming to:
    {{"root_cause": "...", "lesson": "...", "revised_action": "..."}}
    """

    def generate_critique(self, client, goal: str, action: str, error: str) -> dict:
        prompt = self.CRITIQUE_PROMPT_TEMPLATE.format(goal=goal, action=action, error=error)
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": prompt}],
            response_format={"type": "json_object"},
            temperature=0.1
        )
        return json.loads(response.choices[0].message.content)

By prepending lesson to the working memory buffer on subsequent iterations, the agent navigates around the failure condition.


Summary of Module 1: Foundations

With this article, we conclude Module 1 (Foundations of Agency):
- In Post 01, we dissected the cognitive anatomy and built an end-to-end ReAct loop.
- In Post 02, we enforced type-safe deterministic tool boundaries with Pydantic.
- In Post 03, we structured a multi-tiered memory architecture across context buffers, episodic checkpoints, and vector stores.
- In Post 04, we graduated from reactive impulsivity to proactive Plan-and-Solve and Reflexion reasoning.

Now that our agent has a cognitive core, tools, memory, and a planner, it needs the ability to ingest and navigate vast external document stores.

Next up is Module 2: The Retrieval & Context Layer [Agentic RAG], beginning with [Post 05: Chunking Strategies for Agents]!

← Back to All Publications
B

Bharath

AI Engineer / Data Scientist specializing in Generative AI systems, transformer architectures, prompt engineering patterns, and autonomous agent orchestration. Writing technical breakdowns for production engineers.