Module 066 min

Patterns: six ways to wire a loop

The loop is the same everywhere. What changes is the wiring: who plans, when a human is asked, and whether steps run one at a time or all at once.

After this module
  • You can pick a pattern from the shape of the task instead of from whatever a tutorial used.
  • You know why "reflection" is not a cure-all, and where a human gate actually belongs.

Six patterns cover almost everything built in production today. They are not frameworks — you can implement any of them in a hundred lines with a model client and a while loop. Choosing well is mostly about two questions: does the next step depend on the last result? and what is the cost of a wrong action?

The working set. Most systems are one of these, with a permission gate bolted on.
PatternShapeBest forMain weakness
ReActThink → act → observe, repeatedlyOpen-ended research, debugging, browsingWanders; context and cost grow fast
Plan & executePlan once → execute steps → replan on failureMulti-step work with known shape; anything needing sign-offPlan is stale the moment reality differs
RouterClassify input → send to a specialist pathSupport triage, intent handling, cheap/expensive model selectionMisclassification is silent and systematic
ReflectionProduce → critique → reviseWriting, code review, catching obvious errorsSelf-critique can entrench a confident mistake
Human gateAny pattern + approval before risky actionMoney, email, deletion, production changesApproval fatigue — people click yes
Parallel fan-outSplit work → many workers → mergeIndependent sub-tasks: 20 files, 10 sources, 5 candidatesMerge quality; duplicated effort; cost spikes

6.1ReAct, in code

Reasoning and acting interleaved. It is the default because it handles surprise — which is what most real tasks are made of.

trajectory = [system_prompt, goal]

for step in range(MAX_STEPS):
    thought = model(context=trajectory, tools=TOOLS)

    if thought.is_final:
        return verify(thought.answer)          # never trust the claim

    action = parse(thought.tool_call)          # schema-validated
    if not permitted(action):
        return ask_human(action)

    result = run(action, timeout=30)           # errors are data
    trajectory += [thought, result]

    if budget_exceeded() or repeated_failure():
        return escalate(trajectory)

The interesting parts are the lines that are not the model call: schema validation, the permission check, the timeout, the repetition detector, the budget. Those five lines are the difference between a demo and something you'd let touch a customer.

6.2Plan first, when the plan is the product

If a human needs to approve the approach, or you need an audit trail of intent, generate the plan as a separate artifact before doing anything. It costs one extra call and buys you reviewability, parallel execution, and a natural place to attach estimates.

plan = model.plan(goal)          # steps, tools, dependencies, risks, cost estimate
if plan.requires_approval:
    plan = await human.review(plan)   # approve / edit / reject

for step in topo_sort(plan.steps):     # independent steps can run in parallel
    result = run(step.tool, step.args)
    if step.failed:
        plan = model.replan(goal, plan, results, error)  # bounded: 2 attempts

Note the bound on replanning. Unbounded replanning is how an agent spends an afternoon and $40 rediscovering that the API key is expired.

6.3Routing: the cheapest win in the system

Most requests are easy. Sending every one of them to the largest model is the single most common way to waste budget. A router classifies first — by rules, by embedding similarity, or by a small fast model — then hands off.

ROUTING · PAY FOR WHAT THE TASK NEEDS Request Classify rules · embeddings Cheap model faq · summary · triage Strong model planning · code · ambiguity agent loop if unsure easy hard
Cascade, don't gamble. Cheapest first, escalate on low confidence or failed validation. The escalation rule matters more than the classifier.

6.4Choosing: answer two questions

Try it · pattern chooser4 task shapes

ReAct loop — the next step genuinely depends on what the last one returned, so you need the flexibility; budget for 8–20 iterations and verify the final answer.

The trap · reflection theatre

"Ask the model to critique its own answer" is popular because it's one line of code. It helps most on small, checkable errors (formatting, missing constraints) and helps least on factual confidence — a model that is wrong and certain will often critique itself into being wrong and more detailed. Prefer external checks: tests, schemas, citations, a second model with different information.

Where the human gate goes

Put it immediately before the irreversible action, not at the start of the task. A person reviewing "the agent will send this email to this customer with this text" makes a real decision. A person approving "the agent may now work on the inbox" has approved nothing specific and will click yes every time.

Check yourselfQuestion 1 of 1

A finance team wants an agent to reconcile accounts monthly, with a manager signing off. Which pattern fits best?

60-second recap

  • Choose by task shape: unknown steps → ReAct; approval or audit → plan-and-execute; mixed difficulty → routing; independent pieces → fan-out.
  • Every pattern needs the same safety lines: schema validation, permission check, timeout, repetition detection, budget cap.
  • Gate the irreversible action, not the start of the task.
  • Reflection is weak without external checks. Tests and citations beat self-critique.