Two people fix a broken washing machine. The first pokes at it, sees what happens, pokes somewhere else — reacting to each finding. The second reads the symptoms, writes a checklist, then works through it. Neither is wrong; they suit different problems. Agent architectures are exactly this choice, with proper names attached — ReAct, Plan-and-Execute, Reflection — and interviewers use those names as shorthand for whether you understand agent design or just the vocabulary.
ReAct — the default pattern
ReAct = Reasoning + Acting, interleaved. Before each action the model writes a short thought about what it's doing and why; after each action it reads the result as an observation. Repeat until the goal is met.
Read that trace and notice what it is: a diary. The agent never plans beyond the next step, because each observation may change what the next step should be. That's the strength — it adapts to whatever it finds — and the cost, since every step pays for reasoning tokens and another round trip.
Why writing the thought actually helps
It looks like theatre. It isn't, for two reasons. Better choices: forcing the model to state a reason before acting is chain-of-thought applied to tool selection — it commits to a rationale, which measurably reduces "grabbed the first plausible tool" errors. Debuggability: when an agent does something bizarre, the thought line tells you why. Without it you have a sequence of tool calls and no explanation — and agent bugs live in the middle of runs, not at the end.
The reasoning trace is the difference between an agent you can debug and one you can only restart.
Plan-and-Execute — decide the route first
Instead of one step at a time, the model produces a full plan upfront, then executes the steps (usually with a cheaper model), re-planning if a step fails.
plan = planner.create(goal)
# ["search flights DEL->BLR for tomorrow",
# "pick cheapest morning option",
# "check weather in Bangalore",
# "summarize for the user"]
for step in plan:
result = executor.run(step, tools=TOOLS)
if result.failed:
plan = planner.replan(goal, done_so_far, failure=result) # adapt
continueAdvantages: fewer expensive reasoning calls (one plan, cheap execution), and — the underrated one — the plan is a visible artifact a human can approve before anything runs. For agents that touch real systems, that's a genuine safety feature. Disadvantage: a plan written before seeing any results can be wrong from step one, which is why re-planning is part of the pattern rather than an optional extra.
Reflection — draft, critique, revise
For output-quality tasks — writing, code, analysis — the agent produces a draft, then critiques its own work against explicit criteria, then revises. It works because generating and evaluating are different tasks: a model reviewing a finished draft notices problems it didn't avoid while writing it.
draft = model.write(task)
for _ in range(2): # cap the rounds - quality plateaus
critique = model.review(draft, rubric=BRAND_RULES)
if critique.is_acceptable:
break
draft = model.revise(draft, critique)Two practical notes: cap the rounds (improvement flattens fast, usually after one or two), and give the critic a rubric — "make it better" produces waffle, while "check: every claim cited, under 200 words, no competitor names" produces fixes.
Wait — which one do I actually use?
Real systems combine them, because different phases of one task want different patterns. "Research this company and write a brief" splits cleanly: the research half benefits from Plan-and-Execute (the sub-questions are knowable upfront — financials, news, competitors, leadership), and the writing half benefits from Reflection (draft, critique against the brief's requirements, revise). ReAct handles the genuinely unknown middle — a search that returns something surprising and changes the next question.
Rules of thumb: unknown path → ReAct; knowable steps, or human approval needed → Plan-and-Execute; output quality matters → Reflection; fixed path → not an agent at all.
Step limits and budgets — non-negotiable
Every pattern here can loop forever. The classic failure isn't dramatic: the agent simply can't achieve the goal, so it tries variation after variation — rephrasing the same failing search, oscillating between two tools — while your bill grows.
MAX_STEPS = 8
MAX_COST_RS = 5.0
for step in range(MAX_STEPS):
if run.cost_so_far > MAX_COST_RS:
return escalate("budget exceeded", trace=run.history)
...
else:
return escalate("step limit reached", trace=run.history)An agent without a step limit is an unbounded bill waiting for a bad day. Note the escalation carries the trace — the human picking it up shouldn't have to start from zero.
Selection-round radar: "Explain ReAct" is the most-asked question in this lesson — answer with the thought/action/observation cycle plus why the thought improves tool choice and debugging. Expect the follow-up "how do you stop it looping forever?" and answer with step limits, cost budgets and escalation-with-context.
Common mistakes
- Using ReAct for a task whose steps are known — paying reasoning tokens for decisions nobody needed.
- Reflection with a vague rubric — the critique becomes praise.
- Plan-and-Execute without re-planning, so one wrong assumption ruins the run.
- Discarding the reasoning trace, then being unable to debug anything.
- No step limit or cost budget.
- Escalating without the trace, so a human restarts the whole investigation.
Quick recap
| Pattern | Shape | Best for |
|---|---|---|
| ReAct | thought → action → observation, looped | unknown paths; investigations; adaptive tasks |
| Plan-and-Execute | plan upfront → execute → re-plan on failure | knowable steps; cheaper execution; human-approvable plans |
| Reflection | draft → critique vs rubric → revise (capped) | writing, code, anything judged on quality |
| Combination | different patterns per phase of one task | research-then-write style work |
| Always | step limit + cost budget + escalation with trace | every production agent |
Practice Zone — PYQs from real selection rounds
Six MCQs and two tasks — write a full ReAct trace including the moment the agent stops to ask the user, then match four tasks to patterns.
The ReAct pattern interleaves:
Asked in

Plan-and-Execute differs from ReAct because:
Asked in

The Reflection pattern means:
Asked in

Which pattern best suits: "research this company and write a two-page brief"?
Asked in

Why do agent loops need a hard step limit?
Asked in

What is the main downside of writing out reasoning at every step (ReAct)?
Asked in

Hands-on tasks:
Tools: get_order(order_id), get_policy(topic), issue_refund(order_id, amount). User: "My order #8123 arrived broken, I want my money back." Write the expected ReAct trace, including the human-approval moment.
Asked in

Choose ReAct, Plan-and-Execute, Reflection, or a plain workflow for: 1) Answer a support question using a knowledge base. 2) Migrate 200 files to a new API format. 3) Write a marketing email that must match brand voice. 4) Investigate why a nightly job failed.
Asked in

FAQ
Do reasoning models make ReAct unnecessary?
They move some of it inside the model — reasoning models deliberate internally before answering. You still need the outer loop for tool calls and observations; what changes is that you may need fewer explicit "think step by step" instructions, and you pay for reasoning tokens either way.
How many steps do real agents take?
Most useful tasks finish in 2–8 tool calls. If yours routinely needs twenty, that's a signal: the tools are too fine-grained, the goal is too broad, or the task should be a workflow. Long runs also invite context bloat (lesson 6).
Is Reflection just asking the model to check its work twice?
In essence yes — with the important detail that the critique step gets explicit criteria and is a separate call where the model reads the draft as input. Vague self-review adds cost and little else; rubric- driven review catches real problems.
Next lesson: the toolkit most teams build on — Lesson 4: LangChain Basics →


