Building a Research Agent from Scratch Part 02 — v0.4

Making Research Agents More Deliberate

Forced planning, better extraction, and mandatory reflection — three constraints that moved the agent from reactive to deliberate.

§ 00The lesson so far

One thing keeps proving itself while building agentic systems: the more you steer the context with clear, deterministic structure, the more useful the agent becomes.

An LLM is not conscious of what it knows. It predicts the next token. The job of an agent engineer is to create the conditions under which its intelligence is actually used — and those conditions are structural, not motivational.

With that in mind, three concrete changes to the research agent.

§ 01Forced planning

Previously the agent went straight to searching. Now it has to think first. I added a dedicated create_research_plan tool and made it the mandatory first step.

In the system prompt:

1. ALWAYS start by calling the `create_research_plan` tool.
   Never search before creating a plan.

And in the runtime, where it actually counts:

if step == 1:
    tool_choice = {"type": "function",
                   "function": {"name": "create_research_plan"}}

The prompt asks. The runtime decides. Pinning tool_choice on the first step means there is no path through the code where research begins without a plan — the model isn't being persuaded, it's being routed. That single constraint noticeably improved the coherence of everything that followed.

§ 02Better page extraction

trafilatura on its own kept failing on modern sites with anti-bot protection, and a failed extraction isn't loud — it comes back as a short string that looks like a real observation. The agent then reasons over almost nothing.

So browse_page became a fallback chain:

  1. Try trafilatura directly.
  2. If it fails, or the content comes back too short, retry through httpx and extract from that.
  3. Reject pages that still don't yield enough content, rather than passing the scraps along.

Step three is the one that matters. Returning “this page gave nothing useful” is more valuable than returning two sentences of navigation text, because the first tells the agent to go elsewhere and the second quietly poisons the report.

§ 03Reflection before finishing

The most interesting addition was a reflect tool. Before the agent is allowed to call finish_research, it has to critically evaluate its own work:

This forces the model to use its own intelligence to critique its work, rather than just accumulating information until it stops.

It's the same trick as forced planning, applied at the other end of the loop. Planning constrains the entrance; reflection constrains the exit. In between, the agent is free.

§ 04Results

I compared the original v0.1 against v0.4 on the same research question. The biggest gains came from forced planning and reflection — those two mechanisms alone moved the agent from reactive behaviour to something closer to a deliberate research process.

§ 05Key takeaway

Good agentic systems are not about giving the model more tools.

Closing

They are about designing the right constraints and structure so the model is forced to think better. Planning and reflection are simple ideas, and both of them measurably raised the quality of the final output.

Steer the context, and the intelligence follows.