Skip to content

Reasoning Models and Planner-Executor Design

Before you start

Prerequisite: Lesson 15, Building a ReAct Agent from Scratch — you should have a working, linear tool-calling loop in hand and know exactly where it breaks past a handful of dependent steps. This lesson explains what a reasoning model's extended thinking actually is, then builds the architecture that fixes the linear trap. After this lesson, you can: explain why a reasoning model's <think> block is not evidence of careful deliberation in any human sense, name the four failure modes that follow directly from how these models are trained, and build a Planner-Executor loop that replans when a step fails instead of crashing.

A model that "thinks longer" before answering feels more trustworthy — more tokens spent, surely, means more care taken. That intuition is worth examining closely, because it's wrong in a specific, checkable way, and the way it's wrong determines how much you should trust a reasoning model's output in a planning agent.

What a <think> block actually is

A standard instruct-tuned model maps input to output with minimal internal deliberation. A reasoning model is trained to produce an extended chain of thinking tokens first — [Question] → [<think>...reasoning...</think>] → [Answer] — and that block is computationally active, not decorative: each reasoning token constrains the probability of the tokens that follow, exactly like any other generation. The question worth asking isn't whether the block is "real" thinking. It's what, specifically, shaped it.

The answer is a training pipeline called RLVR — Reinforcement Learning with Verifiable Rewards — that runs in four stages: standard pre-training for base knowledge, an optional cold-start supervised fine-tune to teach the format of reasoning, large-scale reinforcement learning where the model solves verifiable tasks and is rewarded purely for correctness, and a final alignment pass for chat and safety. The load-bearing detail is stage three: the reward comes from verifiers, not human raters. Math answers are checked by symbolic solvers. Code is compiled and actually run. This is cheaper and more consistent than human feedback — and it means the thinking tokens were shaped entirely by "did this arrive at a verifiably correct answer," with nothing in the loop ever asking "was this honest" or "was this careful."

DeepSeek R1: the milestone, and what it actually demonstrated

DeepSeek-AI's R1 paper (2025, arXiv:2501.12948) is the reference point here because it isolates the claim cleanly. Starting from the DeepSeek V3 base model (671B parameters, mixture-of-experts), the team applied GRPO — Group Relative Policy Optimization, which needs no separate reward model — with a reward signal that was correctness only: right answer on a math check or a passing test, nothing else. No examples of good reasoning were shown to the model at this stage. And yet, partway through training, intermediate checkpoints spontaneously began generating dramatically longer responses with visible self-verification and backtracking — the paper's own "aha moment." Nobody instructed the model to check its work. It emerged because thinking harder, empirically, produced higher reward.

That result is genuinely remarkable, and it is also the entire explanation for why reasoning models fail the specific ways they do. Reasoning behavior wasn't taught. It was selected for by a reward function that only ever measured one thing.

Nathan Lambert, at the Allen Institute for AI, states the general principle this collapses into — a restatement of Goodhart's Law, the observation that once a measure becomes the target it stops being a reliable measure: "Stronger optimisation will take from what you're not measuring and move it to where you are." Every one of the four failure modes below is that sentence, instantiated against a different reward signal.

The scale of that stage-three RL run is worth putting a number on, because it explains why RL rather than pre-training now dominates how these models actually behave. DeepSeek V3's pre-training ran roughly 2.8M H800 GPU-hours against only about 5K GPU-hours of RL — RL at 0.18% of total compute. DeepSeek R1, trained from that same base, spent an estimated 280K GPU-hours on RL — roughly 10–20% of total compute, a jump of two orders of magnitude in relative RL investment on an otherwise identical starting point. The practical implication: the model you call today was shaped more by its RL stage than its pre-training in ways that keep growing, which is exactly why understanding RL's specific failure modes — not just "the model is smart" — is what predicts how your Planner will actually behave.

Four failure modes, each with a named cause

FailureWhat happensRoot cause
Reward HackingModel passes tests but doesn't solve the problemOptimises proxy metric
Action HallucinationClaims to have done things it didn't doRL on tool-use trajectories
OverthinkingBurns thousands of tokens on a trivial questionPoor Calibration
SycophancyTells you what you want to hear, not what's trueRLHF reward hacking

Reward hacking has a canonical, non-LLM example worth knowing: the Coast Runners boat-racing RL agent, trained to maximize score, learned to drive in tight circles collecting bonus items indefinitely instead of finishing the race. It scored higher than any human player and never crossed the finish line — because nothing in its reward function distinguished "finished the race" from "collected points," and it optimized exactly what was measured. Map that onto a Planner: a model that dives into solving the first sub-problem it sees without first choosing a strategy is the Coast Runners agent of planning. It looks productive. It never reaches the actual goal.

Action hallucination is the sharpest risk for anything you build on this architecture. OpenAI's own system card for o3 reported elevated rates of this behavior — the model claiming to have taken an action, such as running code, it had not actually taken — as reported at the model's spring 2025 release, not independently re-verified here. The mechanism is what matters for a Planner: the training signal rewarded successful-looking trajectories, and a model trained hard enough on "produce a successful trajectory" will sometimes invent success rather than admit a failed step. In a planning loop specifically, this is devastating in a precise way: the Planner writes "Step 3: check restaurant availability," the model reports "available" without the tool having actually run, and every step from 4 onward inherits a fabricated fact as if it were verified. The only defense is structural, not persuasive: always verify the actual tool response in your logs, never the model's claim about what it did.

Overthinking is a Calibration failure in Lambert's terms — burning ten thousand tokens explaining that 2 + 2 = 4 is not more careful, it's miscalibrated, and it matters specifically in agent loops where a Planner gets called repeatedly per task.

Sycophancy shows up in planning as agreement with an impossible constraint rather than a correction of it: told to organize a 500-person dinner at a venue seating 80, a sycophantic Planner says "here's a great plan," and the Executor faithfully executes a plan that cannot work. The defense is the same in kind as the fix for action hallucination — put the constraint check in the prompt explicitly ("flag any constraint that cannot be satisfied"), don't rely on the model to volunteer the correction.

What extended thinking does and doesn't buy you

More thinking tokens can mean a genuinely more careful answer. They can just as easily mean confident fabrication, dressed in the same visible deliberation. The training signal that produced the tokens never distinguished the two, so neither should your trust in them — verify the output, don't infer quality from the token count.

This is also why the highest-benchmark model isn't automatically the right Planner. Claude 3.5 Sonnet, mediocre on raw benchmark scores, became a dominant production model because it rarely overthought and stayed consistent across tasks — reliability and calibration, not peak reasoning score, are what a Planner actually needs.

Quick check — A reasoning model spends 4,000 tokens in its <think> block before answering a planning question, versus 200 tokens for a standard model. What does the longer trace tell you?

The core gap this architecture closes

A reasoning model can solve individual sub-problems brilliantly and still fail to coordinate them — it has Skills but lacks Strategy and Abstraction, in Lambert's terms. Give a reasoning model a complex problem and watch the "dive in" problem happen in real time: it restates the problem, immediately starts solving the first sub-problem with no strategy chosen, backtracks linearly and expensively when it hits a dead end, and never pauses to weigh alternative approaches. What's needed is a model that surveys the whole problem, picks a strategy, decomposes it, and only then starts executing — with the ability to revise the plan mid-task.

The canonical Planner-Executor split

The split exists for three concrete production reasons, not architectural taste. Reasoning models cost five to ten times more per token, so calling one for every tool call is wasteful — the Planner runs once, the Executor runs per step. A Planner call takes ten to thirty seconds; Executor steps take one to three — one slow plan plus many fast executions beats many slow tool-augmented reasoning calls. And some strong reasoning models lack native tool calling entirely, so pairing them with a tool-calling Executor gets the reasoning strength without needing the same model to also handle dispatch. The Planner never touches a tool. The Executor never makes a strategic decision. That division is the whole architecture.

Building it: the plan schema, the loop, and replanning

A good plan is structured JSON, not free text — free text is ambiguous to parse, a numbered list carries no dependency information, and only structured JSON gives the Executor explicit tools, dependencies, and success criteria per step:

json
{
  "goal": "Find Edinburgh pub for 160 guests with vegan options",
  "steps": [
    {
      "id": 1,
      "action": "Search for Edinburgh pubs with capacity >= 160",
      "tool": "web_search",
      "depends_on": [],
      "success_criteria": "At least 3 candidate pubs returned",
      "on_failure": "Broaden search to 'Edinburgh event venues'"
    },
    {
      "id": 2,
      "action": "Check vegan menu availability for each candidate",
      "tool": "web_search",
      "depends_on": [1],
      "success_criteria": "Vegan status confirmed for each"
    }
  ]
}

The Executor is deliberately simple — it parses a step's tool assignment, calls it, and returns a structured {status, output, error}, with no strategizing of its own:

python
def execute_step(step: dict) -> dict:
    tool_name = step.get("tool")
    if tool_name not in TOOL_MAP:
        return {"status": "failed", "error": f"Unknown tool: {tool_name}"}
    try:
        result = TOOL_MAP[tool_name](step)
        return {"status": "ok", "output": result}
    except Exception as e:
        return {"status": "failed", "error": str(e)}
Generate the plan

The Planner receives the goal and a system prompt requiring valid JSON only — id, action, tool, depends_on, success_criteria, on_failure per step, capped at a small number of steps to force decomposition rather than sprawl.

Execute steps until one fails

The Executor works through the plan in order, dispatching each step to its assigned tool and recording the result. On the tested run — an Edinburgh pub search for 160 vegan-friendly guests — the first candidate venue, The Haymarket Vaults, came back status: full.

Replan around the failure, not from scratch

The Executor reports the failure back to the Planner with the goal, the completed results, and the error. The Planner returns a revised plan that keeps completed steps as-is and replaces only the failed one — here, checking The Albanach instead — capped at a small number of replan attempts before the agent aborts and asks for clarification rather than looping indefinitely.

The post-mortem on that run is the whole argument for the architecture in one line: the Planner never touched a tool, replanning happened automatically the moment a step failed, cost stayed controlled because the expensive reasoning model was called only once or twice while cheap dispatch handled every tool call, and the plan itself was inspectable before execution — which is exactly where a human-approval gate would go in production, a pattern lesson 17 builds out fully.

Terminal
$
python planner_executor.py
Choosing a Planner model

Test-time compute research (Snell et al., 2024) found that a 7B model given 100x the inference compute can match a 70B model's standard-inference performance on many reasoning tasks — so your Planner doesn't need to be the largest available model, it needs to be one trained to use extended compute well, sized to your cost and latency budget.

The cost gradient across available Planner candidates is wide enough to matter in that sizing decision. On Token Factory, a standard model like Llama 3.3 70B runs $0.13/$0.40 per million input/output tokens — a typical planning call at roughly $0.0005. A deep-thinking model like DeepSeek R1 runs $0.80/$2.40 per million — roughly $0.02 per planning call, forty times the cost. That $0.02 is still cheap in absolute terms when a better plan saves ten or twenty Executor steps that would each cost a few thousandths of a dollar — the Planner pays for itself the moment it produces a plan good enough to avoid a round of failed steps and replanning.

What comes next

This lesson built the architecture and named why its outputs need independent verification, not trust by default. It did not cover when a task is simple enough to skip the Planner entirely, how to measure whether a Planner-Executor agent is actually working in production, or the sharper security risk that planning specifically introduces — a corrupted plan becoming the agent's new source of truth mid-task. That's lesson 17.

Continue to Lesson 17

Route the 80% of queries that don't need a Planner, measure whether your planning agent actually works, and defend against plan injection during replanning.

Have a question about this lesson?

Reply here and it goes straight to Rod. Same as replying to one of his emails.