Skip to content
Forward Deployed

Forward Deployed
Lessons and contents
Learn

Deep-research and reflective dynamic planners

Source
From the RAG & Agents Engineering course
By
Sourav Banerjee
Last updated
9 Nov 2026

Report an issue

The project: two research planners

What you'll build

  • A report planner that researches a topic briefly, then plans the report's sections as structured output.
  • A nested section builder (queries, web search, writing) that runs once per planned section, in parallel.
  • A reflective planner that hands each step to a ReAct research agent and replans after every step.
  • Caps in code on sections, searches, page text and steps, each proved without trusting the prompt.

Lesson 1 of T8.1 planned single searches. This project makes each planned step bigger: a report section that a nested workflow researches and writes, or a sub-question that a whole ReAct agent answers before a replanner decides what is left.

It adds no new pattern. It combines lesson 1 of T8.1's planning and replanning with the Send fan-out from T7.3. What changes is that each step now costs live web searches, which puts the planner in charge of how much the run spends.

Architecture

The report planner is a compound agent: one system with one state, whose section builder is a compiled graph used as a single node:

Diagram: Topic; Planner 2 LLM calls, 2 searches; Section builder queries, search, write; Format the researched sections; Intro and conclusion writer; Compiled reportDiagram: Topic; Planner 2 LLM calls, 2 searches; Section builder queries, search, write; Format the researched sections; Intro and conclusion writer; Compiled report

Figure 1: The report planner. Both fan-outs use Send, and the planner's outline decides how many branches run.

The reflective planner nests an agent instead of a workflow, which makes it a hierarchical compound agent:

Diagram: Question; Planner at most 5 steps; ReAct research agent runs step 1; Replanner: answer or new plan?; ResponseDiagram: Question; Planner at most 5 steps; ReAct research agent runs step 1; Replanner: answer or new plan?; Response

Figure 2: The reflective planner. The replanner sees every step done so far and returns either a shorter plan or the final response.

Piece What it does Built on
Report planner Writes planning queries, searches, then returns sections with a name, a description and a research flag Plan-and-execute, lesson 1 of T8.1
Section builder Turns a section into targeted queries, runs them concurrently, writes the section from truncated sources Prompt chaining, T7.3
Fan-out with Send One branch per researched section, gathered by an append reducer Orchestrator-worker, T7.3
ReAct research agent Answers one step with a web-extraction tool, trimming its history to a token budget The ReAct loop, T7.2
Replanner Returns either a plan of the steps still needed or the final answer Replanning, lesson 1 of T8.1

Table 1: The pieces of both builds and the lessons they reuse.

Following one research run

The report notebook researches How to build agentic AI systems: design patterns and current frameworks. A Larkspur team could point the same graph at How do rival hosts price GPU servers? and the call order would be identical:

Stage LLM calls Searches
Planner: write planning queries 1
Planner: search, then plan sections 1 2
Section builder, per researched section (2 kept): queries and writing 2 × 2 = 4 2 × 2 = 4
Introduction and conclusion, written from the researched sections 2
Compile in the planned order 0
Total 8 at most 6

Table 2: One report run with the notebook's settings and the template's introduction and conclusion. Search results are live. Only the order and the counts repeat.

The introduction and conclusion run last, written from the finished sections. They summarise what the research found rather than what the planner guessed.

The reflective planner is less predictable by design. On its notebook question (who founded Microsoft, the founder's hometown and the history of both), the replanner usually stops before the last planned step, often "compile the answer", because the results already cover it.

Design choices worth copying

The report planner's cost is multiplicative: sections × queries per section × results per query × tokens per result. The notebook's first version had no section cap and ran tens of searches and well over 100k tokens. The arithmetic for one researched section's source text:

Setting Queries Results each Raw tokens kept per source Upper bound per section
First version 3 6 4,000 72,000 tokens
Current knobs 2 3 800 4,800 tokens

Table 3: Source text one section writer may read, before duplicate URLs are removed.

Choice Why
Cap the plan in code The prompt can ask for fewer sections. Only code keeps the first two researched sections and guarantees the 6-search bound the run then checks
Count real searches A log of every query sent turns the cost claim into an assertion at the end of the run
Return copies from parallel branches Each section builder returns an updated section, and branches never mutate shared objects
Bound the agent's context The research tool keeps 4,000 tokens of page text per call (the first version allowed 127,000), and the agent trims its history to 50,000 tokens
Overrule the replanner at a step cap After 6 executed steps the replan node stops with the findings so far, whatever the model wants

Table 4: Five choices and what each protects against.

The last row guards against a replanner that always finds one more thing to look up. The notebook proves it without a live model: a stub executor returns canned text, a stub replanner always asks for one more step, and the run still stops after exactly 6 steps.

Limits

  • Live data. Reports and answers change with the web, which leaves no expected text to compare. Test the call order, the search count and the cap instead.
  • No result check. Neither build evaluates a search result the way lesson 1 of T8.1's evaluator does. A wrong page reaches the section writer or the replanner as evidence, and lesson 4 of T8.1's verification is the missing step.
  • Silent search failures. A failed search is dropped from its batch, and a section can end up written from fewer sources than planned.

Both notebooks need an OpenAI key and a Tavily key, and every run issues real searches against your Tavily quota.

Run the notebooks

The code for this lesson is in these notebooks. Colab runs one in your browser: install the packages its first cell imports and set the API keys it reads. To run every notebook as written, clone the repository and use its uv environment.

Notebook GitHub Colab
Planning agent deep research Open on GitHub Open in Colab
Reflective dynamic planning agent (optional) Open on GitHub Open in Colab

Key Takeaways

  • A research planner decides which pieces of work exist, so the plan sets the bill. Cap sections, queries, results and source length in code, and check the real search count against the bound.
  • Nesting a workflow (one section builder per section) or an agent (one ReAct run per step) inside a plan gives one system with one state, a compound agent, and Send sizes the fan-out at run time.
  • A replanner that reviews every step can stop early or add a step. It needs a step cap that overrules it, proved with stubs that never finish.

Check yourself

1. Why can the report planner not use a fixed edge for each section builder?

The planner decides at run time how many researched sections exist, so the graph cannot know the number of branches in advance. A Send per researched section starts one section builder each, and an append reducer gathers their completed sections.

2. With the notebook's settings, how many searches and LLM calls does one report use, and where does each come from?

At most 6 searches: 2 to plan and 2 for each of the 2 researched sections. 8 LLM calls when the plan has the template's introduction and conclusion: 2 in the planner, 2 per researched section for queries and writing, and 1 each for the introduction and the conclusion.

3. A reflective planner keeps running because its replanner always proposes one more step. What stops it, and how do you show the guard works?

A step cap in the replan node: after 6 executed steps it returns the findings so far instead of calling the replanner. Building the graph around swappable parts lets a stub executor and a stub replanner that never answers reproduce the case with no model calls, and the run stops after exactly 6 steps.

Rate your confidence and keep notes on the module page.