- 01The dividing line is who owns the control flow: you, or the model at runtime.
- 02If you can enumerate the steps — branches included — build the workflow. It is cheaper, testable and cannot surprise you.
- 03Five patterns get sold as agents and are workflows: chaining, routing, parallelisation, orchestrator-workers, evaluator-optimiser.
- 04A workflow's worst-case cost is computable before you ship. An agent's is not.
- 05Testability is the real gap: finite paths you can assert on, versus unbounded trajectories you have to evaluate.
Note on terminology.The five-pattern taxonomy below follows Anthropic’s Building effective agents, which is where the workflow/agent distinction was set out most clearly and whose vocabulary the industry has largely adopted. The argument about which to choose, and the cost and testability analysis, is ours.
The one test
Everything that matters follows from that one difference. Not capability — a workflow calling the same model is exactly as intelligent per step. What changes is the size of the set of possible executions.
| Workflow | Agent | |
|---|---|---|
| Control flow | Yours, written in code | The model's, decided at runtime |
| Possible executions | Finite and known | Open-ended |
| Worst-case cost | Computable before shipping | Depends how the task goes |
| Testing | A case per branch | Trajectory evaluation |
| Failure | At a known step, in a known way | Anywhere, creatively |
| Auditing | The path is the spec | The path must be reconstructed |
“A workflow is exactly as intelligent as the agent per step. What you give up by choosing it is the ability to be surprised.”
- Agentic workflow
- A pipeline in which language-model calls do the reasoning and ordinary code does the orchestration. The model is a component; the program is still a program. The word agentic describes the components, not the architecture.
Five patterns that get sold as agents
1. Prompt chaining
Each call’s output feeds the next. Extract, then summarise, then format. Use it when a task decomposes into fixed sequential stages, and put a validation gate between stages so a bad intermediate result fails fast rather than propagating.
const extracted = await extract(document);
if (!isValid(extracted)) throw new ExtractionError(); // fail here, not three steps later
const summary = await summarise(extracted);
const formatted = await format(summary);2. Routing
A classifier picks a downstream handler. A support enquiry is triaged into billing, technical or cancellation, and each route has its own prompt and tools. This is the highest-value pattern in customer operations because it lets you use a cheap model for triage and reserve expensive handling for the routes that need it.
3. Parallelisation
Independent subtasks run concurrently and are aggregated — either sectioning one task into parts, or voting where several attempts are compared. Wall-clock is the slowest branch rather than the sum, which makes it the pattern to reach for when latency is the constraint.
4. Orchestrator-workers
A coordinator decomposes a task, dispatches workers, and combines results. This is the pattern most often confused with a true agent, and the distinction is precise: if the coordinator can only dispatch from a fixed set of worker types in a fixed shape, it is a workflow. If it decides at runtime what kinds of workers it needs and how many rounds to run, it is an agent.
5. Evaluator-optimiser
One call produces output, a second critiques it, and the first revises — looping until the critique passes or a limit is reached. The bounded loop is what keeps this a workflow, and the bound is not optional: an unbounded critique loop is the most common way a workflow quietly becomes an unpriced agent.
When you genuinely need an agent
| Task | Verdict | Why |
|---|---|---|
| Extract fields from a contract | Workflow | The fields are known in advance |
| Triage and answer a support ticket | Workflow (routing) | Finite categories, per-route handling |
| Reconcile two systems that disagree | Workflow with a gate | Known comparison, human on mismatch |
| Diagnose why a deploy broke | Agent | Each finding changes what to look at next |
| Fix a bug across an unfamiliar codebase | Agent | The path cannot be known before reading the code |
The honest test for the middle of that table: if you find yourself writing a prompt that says “figure out what to do and do it” for a task you could have specified, you have chosen an agent to avoid the work of specification — and you will pay for that choice in tokens, latency and untestability rather than saving anything.
What autonomy actually costs
That last property deserves emphasis because it is counter-intuitive and it wrecks budgets. In a normal system, failures are cheap — you error out early. In an agent loop, a failure is a run that kept trying: more turns, each carrying a longer context, each costing more than the last.
Workflow (3 fixed steps):
cost = c1 + c2 + c3 ← constant, known before shipping
Agent (n turns, context accumulating):
turn k input ≈ base + Σ(previous turns' outputs and tool results)
cost ≈ Σ(k=1..n) (base + k·δ) = n·base + δ·n(n+1)/2
→ cost grows with the SQUARE of turn count, not linearly
→ the runs that fail are the runs with the largest n
→ prompt caching flattens the base term, not the accumulationPrompt caching helps with the repeated prefix but not with the growing tail, which is the part that scales. The practical consequence is that a turn cap is a cost control as much as a safety one — and that an agent without one has no upper bound on what a single request can spend.
Testability is the real gap
This is the argument that should decide most real decisions, and it gets the least attention because it is unglamorous. Ask what your test suite looks like in each case:
| Workflow test suite | Agent test suite | |
|---|---|---|
| Unit of test | One branch | One trajectory |
| Assertion | Output equals expected | Path was acceptable AND output correct |
| Coverage | Countable — did you hit every branch? | Undefined — what is total coverage? |
| Determinism | Same input, same path | Same input, different path |
| Regression | Diff the output | Compare distributions of behaviour |
Coverage is the row that ends arguments. In a workflow you can say “we test every branch” and mean something. In an agent there is no denominator, so there is no such statement to make — which matters enormously if anyone ever has to sign off on the system’s behaviour.
If you do need the agent, the tooling burden is real and worth knowing about in advance — see what a trace has to contain before you can evaluate trajectories at all.
Start as a workflow, promote later
The sequence that works, and the reason each step is in that order:
| Step | What it gives you |
|---|---|
| 1. Write the workflow, even if it is clumsy | A specification, and a cost you can quote |
| 2. Ship it and log where it fails | Evidence, rather than an intuition about flexibility |
| 3. Find the ONE step with unbounded branching | Usually one step, not the whole pipeline |
| 4. Make that step an agent; keep the rest as code | Autonomy where it pays, determinism everywhere else |
| 5. Bound it — turn cap, cost cap, escalation | The agent inherits the workflow's predictability at the edges |
Step three is the one that surprises teams. When the failure log is actually examined, the unbounded branching is nearly always confined to a single step — a diagnosis, a decision about which of many systems to consult — while the rest of the pipeline was fixed all along. Promoting the whole pipeline because one step needed autonomy is the most common over-build in this space.
The hybrid that usually wins
// Fixed control flow: known steps, known cost ceiling, testable branches.
async function handleTicket(ticket: Ticket) {
const route = await classify(ticket); // workflow: routing
if (route === "billing") return billingFlow(ticket);
if (route === "cancellation") return escalateToHuman(ticket); // policy, not capability
// ONE step is genuinely open-ended — so this step, and only this step, is an agent.
const diagnosis = await runAgent({
objective: `Diagnose: ${ticket.body}`,
tools: [readLogs, searchDocs, checkStatus], // read-only: no authority to act
maxTurns: 12, // bounded
maxCostUsd: 0.40, // bounded
});
// Back to fixed control flow, with a human gate on anything consequential.
return diagnosis.confident
? replyWithFix(ticket, diagnosis)
: escalateToHuman(ticket, diagnosis); // the agent proposes; code decides
}Two design choices in that snippet carry most of the safety. The agent gets read-only tools, so the worst outcome of a bad trajectory is a wrong recommendation rather than a wrong action. And the decision to act stays in code, which means the authority boundary is enforced structurally rather than requested in a prompt — the subject of authority as code.
The conclusion is genuinely inconvenient for anyone selling agents, including us: most teams asking how to build an agent should build a workflow instead, and would ship sooner, spend less and sleep better. The interesting engineering is not in making a system autonomous — it is in working out the smallest part of it that needs to be.
Which is also why so many products marketed as agents are really workflows, or less. If you are evaluating one rather than building it, the same distinction becomes a buyer’s test — a handful of questions that separate a real agent from a wrapper wearing the label.
Frequently asked questions
What is an agentic workflow?
An agentic workflow is a system where a language model performs steps within a control flow that you defined in advance. The model does the reasoning inside each step; the sequence, branching and termination are code. That is different from an agent, which decides its own next step and when to stop.
What is the difference between an agentic workflow and an AI agent?
Who owns the control flow. In a workflow the path is written by you and the model fills in the steps, so the set of possible executions is finite and known. In an agent the model chooses the path at runtime, so the set of possible executions is open-ended. Everything else — cost, testability, auditability, failure modes — follows from that one difference.
How do I know whether I need a workflow or an agent?
Try to enumerate the steps. If you can write them down, even with branches, build the workflow — it will be cheaper, faster, testable and predictable. Reach for an agent only when the number of paths is genuinely unbounded or the next step depends on information that only appears mid-task.
What are the common agentic workflow patterns?
Five recur: prompt chaining, where each step feeds the next; routing, where a classifier picks a downstream handler; parallelisation, where independent subtasks run at once and are aggregated; orchestrator-workers, where a coordinator delegates and combines results; and evaluator-optimiser, where one call produces output and another critiques it in a loop.
Are agentic workflows cheaper than agents?
Substantially, and predictably. A workflow's token cost is bounded by its structure, so you can compute the worst case before shipping. An agent's cost depends on how many turns it takes, which depends on how well the task goes — the same task can cost three calls or thirty, and failing runs cost the most because they iterate longest.
Can you test an agentic workflow?
Yes, and this is its main practical advantage. A workflow has a finite set of paths, so you can write a case per branch and assert on outputs like ordinary software. An agent has an unbounded set of trajectories, and the same correct answer can be reached by an acceptable or an unacceptable route, so you have to evaluate the path rather than the result.
Sources
- 01Building effective agents — Anthropic, 2024
- 02Agent SDK overview and agent loop — Anthropic, 2026