Most Agent Projects Start One Pattern Too High

A team needs to turn support emails into tickets: read the email, pull out the product and the order number, pick a queue, write a summary. Someone builds it as an autonomous agent with six tools and a loop. In testing it works. In production it sometimes calls the order API four times for the same email, sometimes skips the queue lookup, and the cost per email swings by a factor of ten. Nobody can say why a given run took the path it did.

That task has a fixed shape. Every email goes through the same four steps, so it wants a chain of calls in your own code, with a check between steps. Anthropic's guide to building agents makes the same split: workflows run LLMs and tools through predefined code paths, while agents let the model direct its own process and tool use. Their advice is to find the simplest solution that works and add complexity only when it pays for itself, which for many applications means a single well-prompted call with retrieval and a few examples.

Patterns help because they give you names for those levels. Below are the ones I reach for, in the order I'd try them, with the evidence behind each and where it stops being worth the cost.

You need this when
  • You are about to give a model a loop and a set of tools, and you aren't sure it needs either
  • An agent works in demos but its cost and step count vary wildly in production
  • Someone suggested adding "reflection" and you want to know when it actually helps
  • You need a shared vocabulary for design reviews of LLM features

The Ladder

Think of the patterns as rungs. Each rung up gives the model more control over what happens next, and costs you predictability, latency and money. Climb only when the rung below has failed on real inputs.


flowchart TD
    A["Single call<br/>+ retrieval + examples"] -->|"task has fixed steps"| B["Prompt chaining<br/>with gates"]
    A -->|"inputs fall into clear categories"| C["Routing"]
    B -->|"steps are independent"| D["Parallelization<br/>sectioning or voting"]
    B -->|"subtasks unknown up front"| E["Orchestrator-workers"]
    B -->|"output can be checked and improved"| F["Evaluator-optimizer"]
    E -->|"path depends on what tools return"| G["Agent loop<br/>ReAct, plan-and-execute"]
      

Workflow Patterns: Your Code Holds the Control Flow

PatternWhat it doesUse it when
Prompt chainingEach call works on the previous call's output; code checks run between stepsThe task splits cleanly into fixed steps, such as outline, check the outline, write
RoutingClassify the input, then send it to a specialised prompt, tool set or modelDistinct categories that are better handled apart, such as refunds versus technical questions, or easy versus hard
ParallelizationSectioning runs independent subtasks at once; voting runs the same task several timesSubtasks don't depend on each other, or you want several independent opinions, such as a security review
Orchestrator-workersA central call breaks the task down at run time and hands pieces to workersYou can't know the subtasks in advance, such as how many files a code change touches
Evaluator-optimizerOne call produces, another evaluates and gives feedback, in a loopYou have clear criteria and a second pass measurably improves the result

The support-email task above is prompt chaining. Extraction is one call with a JSON schema, a code check rejects the result if the order number doesn't match your format, queue selection is a second call, and the summary is a third. Every run takes the same path, and when it fails you know which step failed.

Routing is the cheapest win I know. A small model or even a plain classifier decides which bucket an input belongs in, and only the hard bucket goes to the large model. The gate that checks the route matters as much as the route: log the chosen bucket on every request, because a router that quietly sends everything to one path is a common failure.

Agent Patterns: The Model Holds the Control Flow

An agent is, at its core, a model calling tools in a loop and reading what comes back. What changes between patterns is how it plans and whether it looks back at its own work.

ReAct: reason, act, observe

ReAct (Yao et al., 2022) interleaves a reasoning step with an action and feeds the observation back into the next step. On HotpotQA and Fever, letting the model query a simple Wikipedia API reduced the hallucination and error propagation seen in chain-of-thought reasoning on its own. On the ALFWorld and WebShop decision benchmarks, ReAct beat imitation and reinforcement learning baselines by 34 and 10 points of absolute success rate. Most tool-calling loops you write today are ReAct, whether or not they use the name. The journey for this topic walks one run step by step.

MAX_STEPS = 8

def run_agent(task: str) -> str:
    messages = [system_prompt(), user(task)]
    for step in range(MAX_STEPS):
        reply = call_model(messages, tools=TOOLS)       # your provider's SDK
        if not reply.tool_calls:
            return reply.text                            # model decided it is done
        for call in reply.tool_calls:
            if call.name in WRITE_TOOLS and not approved(call):
                result = "Not run: needs user confirmation."
            else:
                result = run_tool(call.name, call.arguments)
            messages += [reply.as_message(), tool_result(call.id, result)]
    return escalate(task, messages)                      # out of steps: hand to a person

Three lines in that loop matter more than the prompt. MAX_STEPSis the stopping condition Anthropic's guide recommends for keeping control. The write-tool check means anything that changes state waits for a person. And running out of steps escalates instead of returning whatever the model said last.

Plan-and-execute: decide the steps once

ReAct pays for a full model call after every observation, and each call re-reads everything before it. Plan-and-execute writes the plan first and then runs the steps, calling the model again only to put the answer together or to re-plan after a failure. ReWOO (Xu et al., 2023) is the clearest version: a planner writes the tool calls with placeholders for the results, workers run them, and a solver combines the evidence. The authors report 5 times fewer tokens and a 4-point accuracy gain on HotpotQA. Plan-and-Solve prompting (Wang et al., 2023) applies a similar "plan first" idea inside a single prompt.

The trade-off is adaptability. A plan written before any tool has run can't react to a surprising result, so I use plan-and-execute when the tools are reliable and the steps are mostly predictable, and keep ReAct for exploratory work like debugging or research.

Reflection: only with something real to reflect on

Reflexion (Shinn et al., 2023) has the agent write a short critique after a failed attempt, keep it in memory, and try again. It reached 91% pass@1 on HumanEval, against 80% for GPT-4 at the time. Self-Refine (Madaan et al., 2023) uses one model as generator, critic and refiner, with no training.

Read the fine print before you add a reflection step everywhere. Huang et al. (ICLR 2024) found that, on reasoning tasks, models struggle to correct themselves without external feedback, and sometimes get worse after trying. The coding results above work because the feedback is real: tests failed. So my rule is that reflection needs a signal from outside the model, such as a test run, a compiler error, a schema validation failure or a tool error. Asking the model "are you sure?" with nothing new to look at mostly buys you a second bill.

def write_function(spec: str, max_rounds: int = 3) -> str:
    code = call_model(prompt_for(spec)).text
    for _ in range(max_rounds):
        result = run_tests(code)                 # external feedback, not opinion
        if result.passed:
            return code
        critique = call_model(reflect_prompt(spec, code, result.failures)).text
        code = call_model(fix_prompt(spec, code, critique)).text
    raise NeedsHuman(spec, code, result.failures)

Tree search: when you can afford many attempts

LATS (Zhou et al., 2023) combines Monte Carlo tree search with model-generated value estimates and self-reflection, exploring several paths instead of one. It reached 92.7% pass@1 on HumanEval with GPT-4. The cost is the point: you run many branches to get one answer. It fits offline or batch work where a correct answer is worth many calls and you can score candidates automatically. I have not seen it pay off for interactive requests.

Choosing: The Questions I Ask

  1. Can I write the steps down today?If yes, it's a workflow. Chaining or routing first.
  2. Does the next step depend on what a tool returns? If yes, you need a loop. Start with ReAct and a hard step limit.
  3. Is there an automatic check of quality?Tests, a schema, a policy rule. If yes, an evaluator-optimizer loop or reflection can earn its cost. If no, don't add one.
  4. What does a wrong action cost? Anything that sends, deletes, pays or changes access goes behind a confirmation, whatever the pattern.
  5. What is the latency budget? Each extra model call adds a round trip. A pattern that needs eight calls rarely fits a chat reply.

What Goes Wrong

⚠️ Common Mistakes

1. An agent where a chain would do

If every input follows the same path, the loop only adds variance. Move the control flow into code and keep the model for each step's judgement.

2. No step limit, no budget

A confused agent repeats itself. Cap steps, cap tokens per run, and alert on the same tool called with the same arguments three times. The agent observability topic covers how to see that in traces.

3. Reflection without feedback

A critique step that sees nothing new is a second guess at the same answer. Give it test results or errors, or remove it.

4. Choosing a framework before a pattern

Frameworks make the first version quick and can hide the prompts and responses you need to debug. Write the pattern by hand once, so you know what the framework is doing for you.

5. Copying benchmark numbers as expectations

The results above come from specific models and benchmarks, mostly from 2022 and 2023. They show the patterns work, not what you will get. Build a small evaluation set from your own traffic and measure each rung before you climb.

Where to Go Next

If one agent turns into several, the multi-agent systems topic covers handoffs and supervisors. For the tool side of every pattern here, start with function calling, because a pattern is only as reliable as the tool definitions it calls.