Lab 01 — Multi-Mode Agent Runtime (ReAct / ReWOO / Plan-Execute)

Phase 01 · Lab 01 · Phase README · Warmup

The problem

Phase 00 gave you the arithmetic of ReAct-vs-ReWOO (quadratic vs linear tokens). Now build all three orchestration strategies for real, behind one runtime, with the LLM injected as a deterministic policy so you can see the tradeoff in the trace:

  • ReAct — reason → act → observe, interleaved. One LLM call per step. Adaptive.
  • ReWOO — plan the whole task (1 call) → execute tools without the LLM (variable substitution) → solve (1 call). Exactly two LLM calls. Cheap; not adaptive.
  • Plan-execute-replan — plan, execute, and re-plan on failure (bounded). Adaptive recovery without ReAct's per-step cost.

The Trace counts llm_calls and tool_calls, so a test proves ReWOO makes two LLM calls where ReAct makes N — Phase 00's lesson, empirically.

What you build

PieceWhat it does
ToolRegistry.dispatchruns a tool; never raises — failures become ToolError observations
parse_react_stepReAct text → Action | FinalAnswer; malformed → ValueError
run_reactthe interleaved loop with a max_steps guard; llm_calls == steps
parse_plan + substitutea JSON plan → PlanSteps; wire #E1 outputs into later inputs (type-preserving)
run_rewooplan → execute (no LLM) → solve; 2 LLM calls regardless of plan length
run_plan_executeexecute a plan, re-plan on failure with the error in context
runthe facade that dispatches by mode

File map

FileRole
lab.pyyour implementation (fill the # TODOs)
solution.pyreference + a worked example that runs the same task in all three modes
test_lab.py18 tests: parsing, the loop, the guard, errors-as-observations, the 2-vs-N call proof, replan recovery
requirements.txtpytest only

Run it

pytest test_lab.py -v                       # your lab.py (red until you implement)
LAB_MODULE=solution pytest test_lab.py -v   # the reference (green)
python solution.py                          # the three-mode worked example

Success criteria

  • You can explain why run_react records llm_calls == steps and run_rewoo records llm_calls == 2, and connect that to Phase 00's quadratic-vs-linear cost.
  • Your dispatch turns every tool failure into a ToolError observation — the loop never crashes on a bad tool call.
  • substitute preserves an int for an exact #E1 reference (so the next tool gets a number, not a string) and raises on an unresolved reference.
  • run_plan_execute recovers from a bad first plan by re-planning with the failure in context, and stops at max_replans.
  • All 18 tests pass under both lab and solution.

How this maps to the real stack

  • ReAct is the loop inside the OpenAI Agents SDK Runner, a LangGraph ReAct node, and LangChain's AgentExecutor. Your parse_react_step is the framework's tool-call parser; your max_steps is its recursion/iteration limit.
  • ReWOO is the plan-and-execute / LLMCompiler family — LangGraph ships a plan-execute template; your #E1 substitution is exactly their variable-passing between plan steps.
  • Plan-execute-replan is what production "planner" agents actually do (LangGraph's plan-execute with a re-plan edge, ADK's LoopAgent around a planner). The bounded replan is the reliability lever from Phase 00 §5 made concrete.
  • Injecting the policy is how real teams unit-test agents: record/replay fixtures, FakeLLM, VCR-style cassettes. Correctness that doesn't depend on the model being right is the craft.

Limits. A real planner is an LLM whose plan quality varies; real tools are async and can fail transiently (retries/backoff live in Phase 08); real ReAct parsing must handle native tool-call JSON, not just the text format (Phase 02). The control flow, though, is exactly this.

Extensions (your own machine)

  • Add token accounting to each Step (word-count stand-in) and print the ReAct-vs-ReWOO token totals for a 10-step task — reproduce Phase 00's cost curve empirically.
  • Add a parallel ReWOO executor: independent plan steps (no #E dependency between them) run concurrently; latency becomes the max of a group, not the sum.
  • Wire a real model behind the Policy interface (one function swap) and run the same three modes against a live LLM; compare traces.

Interview / resume signal

"Built a multi-strategy agent runtime — ReAct (interleaved), ReWOO (plan-execute with variable substitution), and plan-execute-replan — behind one interface with an injected, deterministic model, and proved the ReAct-quadratic vs ReWOO-linear LLM-call tradeoff in the execution trace. Errors are structured observations, so the loop survives bad tool calls."