Most systems marketed as "AI agents" are not agents. Strip away the branding and you find three model calls, a database lookup, and an if statement — a script with a language model in the loop. That is usually the right design. The expensive mistake is reaching for an autonomous, self-directing loop when a fixed pipeline would be cheaper, more predictable, and far easier to debug at 2 a.m. when it starts spending money in a circle.
The useful skill here is not building the most autonomous system you can. It is recognizing the small catalog of patterns that actually recur in production, and then choosing the least agency that solves the problem in front of you.
The one distinction that decides everything
Anthropic's engineering guidance draws a line worth memorizing. Workflows are systems where "LLMs and tools are orchestrated through predefined code paths." Agents are systems where the model "dynamically directs its own processes and tool usage, maintaining control over how they accomplish tasks."
The question underneath that distinction is simple: who owns control flow, your code or the model? In a workflow, you decide the sequence and the model fills in reasoning at each step. In an agent, the model decides the sequence — including when it is finished.
That single choice sets your cost profile, your testability, and your failure modes. Workflows fail predictably. Agents fail creatively — they invent new ways to be wrong that you never wrote a test for.
Start with the augmented LLM
Before any pattern, there is one building block: a model enhanced with retrieval, tools, and memory — the augmented LLM. This is the atom everything else is built from. Getting the tool and retrieval interfaces right at this layer pays off in every pattern above it, so it is worth doing before you compose anything larger.
The workflow patterns: control flow in your code
Five shapes recur, roughly in order of increasing complexity:
- Prompt chaining — decompose the task into fixed sequential steps, each processing the previous output. Use it when the work cleanly splits into subtasks. Add a programmatic gate between steps so a bad intermediate result fails fast instead of poisoning the rest.
- Routing — classify the input, then hand it to a specialized path. Use it when distinct categories are better handled separately: a cheap model for simple queries, a strong one for the hard tail.
- Parallelization — run subtasks simultaneously (sectioning) or run the same task several times and aggregate (voting). Use it for speed, or when several independent perspectives improve the answer.
- Orchestrator-workers — a central model breaks a task into subtasks on the fly and delegates them. Use it when you cannot predict the subtasks in advance. This is where "workflow" starts blurring into "agent."
- Evaluator-optimizer — one call generates, another critiques, and you loop until the critique passes. Use it when you have clear evaluation criteria and iteration provides measurable value.
The evaluator-optimizer loop is worth seeing in code, because it makes the workflow discipline concrete:
draft = generate(task)
for _ in range(MAX_ROUNDS):
review = evaluate(task, draft) # "check correctness, style, efficiency"
if review.passed:
break
draft = revise(task, draft, review.feedback)
return draft
The loop bound lives in your code, not in the model's sense of when to quit. That is the whole point: agency exists here, but it is on a leash you control.
The agent behaviors: control flow in the model
DeepLearning.AI's series frames a complementary set of behaviors — the cognitive moves an agent makes when it, not your code, is driving:
- Reflection — the model critiques its own output and revises it. Cheap to add and often surprisingly effective. Strengthen it with real signals rather than self-grading in a vacuum: run the code through unit tests, compile it, or verify claims with a search before the model calls its work good.
- Tool use — the model calls external functions to act on the world and fetch facts it does not hold. It shows up in nearly every production system that does anything useful.
- Planning — the model decomposes a goal into steps, sequences them, and adjusts as it learns from results.
An autonomous agent is these behaviors run in an open loop: plan, act with tools, observe, reflect, repeat — until the model itself decides it is done. Reserve that shape for genuinely open-ended problems where you cannot predict the number of steps, and only ship it with guardrails and a sandboxed environment. The freedom that makes an agent capable is the same freedom that lets it run up a bill or delete the wrong thing.
The part almost everyone underinvests in
Put as much thought into your tool interface — the agent-computer interface — as you would into a human-facing UI.
That advice from Anthropic's write-up is the most under-applied idea in the field. A flaky agent is more often a symptom of a bad tool interface than a bad model. A few rules that consistently pay off:
- Give the model enough tokens to "think" before it commits to a call, so it does not write itself into a corner.
- Keep argument formats close to what the model has seen in training — well-formed function signatures, plain JSON — and avoid brittle escaping schemes.
- Apply Poka-yoke: design tools so that incorrect use is hard. Prefer absolute paths over relative ones, enums over free-text fields, and required parameters that make an invalid call impossible to express.
Compose across the ladder, don't just climb it
In practice you stack two or three of these. Tool use is nearly universal; reflection layers onto almost anything; a router can sit in front of an evaluator-optimizer loop. Almost no real system is one clean pattern.
The failure mode is escalating up the agency ladder when you should be composing across it. For most bounded tasks, routing into a small evaluator-optimizer loop beats a fully autonomous agent — it is cheaper, it fails in ways you can enumerate, and, critically, you can put it under test. A test you can write is worth more than autonomy you cannot predict.
The takeaway
Write your control flow in code until you hit a task whose steps you genuinely cannot enumerate in advance. That boundary is where an agent starts earning its cost, and not one line sooner. Before it, you are paying agent prices for a workflow problem. The patterns above are not a menu of ambitions to work through in order — they are a set of levers, and the senior move is pulling the smallest one that gets the job done.
Sources: Building Effective AI Agents — Anthropic, Agentic Design Patterns Part 2: Reflection — DeepLearning.AI