Most teams building with large language models eventually face the same fork: should this task run as a deterministic workflow, where every step is declared in advance, or as an autonomous agent, where the model decides what to do next? The two fail in different ways, cost different amounts, and need different safety nets. This guide answers the question of deterministic workflows vs agents with a decision framework you can apply in minutes, five worked examples, and the hybrid pattern most production systems actually end up with.
The short answer: pick predictability unless the task genuinely needs judgement
Default to deterministic workflows. Reach for an agent only when the task needs runtime planning and tool selection beyond predefined branches. A bounded model call — classification, extraction, summarisation — inside a workflow is model use, not autonomous control, and it does not turn the workflow into an agent.
The distinction Anthropic draws is the one that matters. As Erik Schluntz and Barry Zhang put it: “Workflows are systems where LLMs and tools are orchestrated through predefined code paths, while agents are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they perform tasks.” The line is control, not tools or loops. If the model controls the process, you are in agent territory. Anthropic’s guidance: start with the simplest pattern that passes evaluation, and reserve agents for cases where you cannot hardcode the path but can still verify progress. Agents trade predictability for flexibility, and each extra autonomous turn adds latency, token cost, and the chance that an early mistake propagates through everything that follows.
What a deterministic workflow actually guarantees
A deterministic workflow gives you predefined control flow: steps, order and tool calls are declared in advance, so the same input takes the same declared path unless a branch condition says otherwise — that is the guarantee. Everything else people attach to workflows — replay, auditability, bounded cost — is an engine feature, not an inherent property, and it depends on the engine’s documented behaviour plus the configuration you actually set.
Temporal illustrates it best: its workflow code must be deterministic because the platform recovers by replaying it from the start. Anything non-deterministic — network calls, clock reads, random numbers — has to live in activities, whose results are recorded in history and returned verbatim on replay. If a worker dies between two steps, another worker picks the run up and replays the recorded history. The card is not charged twice. But that replay only works if the code stays deterministic: branching on replay status breaks it, and external calls inside workflow code instead of activities break it too.
The same conditional logic applies to cost and latency. A workflow’s cost is bounded only when the engine enforces configured limits — step caps, timeouts, token budgets. Replay and audit support are likewise engine features: whether a run can be replayed step by step, and what gets logged, depends on the engine’s documented tracing and the retries, timeouts and budgets you configured.
What an autonomous agent actually buys you
Agents handle tasks where the next step itself must be chosen at runtime — the plan depends on what previous steps found, not just on ambiguous input. A workflow with a bounded model step can already classify, extract or summarise free text, so ambiguous input alone is not a reason to build an agent.
In LangGraph, the mechanism is explicit. The model determines tool selection from function descriptions, generated by bind_tools(), and the function-call API’s tool_calls response. The tool node runs the chosen tool and returns the result to the model, which may call another tool or finish. That loop — observe, reason, choose a tool, act, observe the result, repeat — is the agent. It is powerful because nobody wrote the sequence down in advance: the agent adapts to whatever the environment returns.
That freedom is the product and the risk: the path a run takes is not known in advance, so neither are its cost, duration or side effects. An agent is worth building when the steps genuinely cannot be listed in advance — open-ended research, multi-file code changes, debugging — and when progress can still be verified outside the agent, such as tests or a human reviewer.
The four questions that decide it — deterministic workflows vs agents

Apply these four questions in order — they are the whole framework.
Does the variability change the steps? Free text and novel cases can still be handled by a workflow with bounded model steps. Only when the plan itself must be formed at runtime — when step three depends on what step two discovered — does the task point to an agent. Input variability alone does not decide it.
What does a wrong step cost? Money movement, customer-facing actions and irreversible operations need controls at the action boundary: authorisation, validation and approval. An agent step that moves money is acceptable only behind the same gate a workflow step would face, and a workflow step that skips validation is no safer than an agent step.
Do you need to prove what happened? Regulated or audited processes need records that are traceable, time-stamped and provably unaltered at retrieval. SOX requires seven-year retention for financial records, HIPAA six years, GDPR three to five years. For AI workflows that means immutable append-only logs, human-in-the-loop decision logs recording the context shown and the authorisation given, and data provenance back to the source documents.
Is the task decomposable? If the steps are known, write them down. A workflow is expected to execute known steps cheaper and faster than an agent that re-derives them — an expectation to test against equivalent tasks and the same success criteria, since no controlled comparison on the same task was found — and every model call re-sends the entire accumulated context — system prompt, tool definitions, history, prior tool outputs — so cost grows superlinearly with steps.
Worked examples: five tasks, five answers
Invoice processing and payment reconciliation: workflow. The steps are known, money moves, and an audit trail is required. An agent adds nothing except cost and risk — except for the exception queue, where a bounded model step can extract fields from invoices the workflow cannot parse, with the result validated against the schema before the workflow continues.
Customer support triage with ambiguous tickets: workflow with a bounded model step. A bounded model step inside the workflow classifies the ticket, and the workflow runs the fixed resolution steps. Ambiguous input is handled without handing control to an agent — this routing pattern is the example most teams get wrong by reaching for an agent first.
Code review on every pull request: workflow skeleton with an agent step inside a bounded scope. The workflow fetches the diff, runs tests and linting, and routes the result. One agentic step reviews the diff, but it cannot merge or run unreviewed commands, and its output is a comment, not an action.
Open-ended research and summarisation: agent. The steps cannot be listed in advance — which sources to check depends on what the first sources say — and nothing irreversible happens. The output is a draft a human reads, which is the verification the pattern needs.
Data pipeline with schema drift: workflow with agent-assisted mapping, guarded by validation. The pipeline is fixed; mapping a new source schema to the target schema is the one step nobody can predefine. An agent proposes the mapping, a validation gate checks it against the schema and sample rows, and only a passing mapping enters the pipeline. The decision record can be as simple as:
{
"task": "invoice processing",
"input_variability": "low",
"failure_cost": "high",
"audit_required": true,
"decision": "deterministic workflow",
"reason": "steps are known and money moves"
}
The hybrid pattern most teams actually end up with

The hybrid pattern is a practical design option: deterministic orchestration around the outside, agentic steps inside bounded, validated sub-tasks. The workflow decides what happens and in what order; the agent decides only inside a step whose boundaries the workflow defined.
Validation gates are what make the hybrid safe. In LangGraph, the approval gate is a first-class primitive: interrupt() pauses the graph and resumes only on a human decision:
from langgraph.graph import StateGraph, START, END
from typing import TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import interrupt, Command
class DeployState(TypedDict):
service: str
approved: bool
def plan_deploy(state: DeployState) -> DeployState:
return {**state, "approved": False}
def approval_gate(state: DeployState) -> DeployState:
decision = interrupt({"question": f"Deploy {state['service']} to prod?"})
if decision is True:
return {**state, "approved": True}
if decision is False:
return {**state, "approved": False}
raise ValueError("approval decision must be a Boolean (True/False)")
def deploy(state: DeployState) -> DeployState:
print(f"deploying {state['service']}")
return state
def route_on_approval(state: DeployState) -> str:
return "deploy" if state["approved"] else "end"
builder = StateGraph(DeployState)
builder.add_node("plan", plan_deploy)
builder.add_node("gate", approval_gate)
builder.add_node("deploy", deploy)
builder.add_edge(START, "plan")
builder.add_edge("plan", "gate")
builder.add_conditional_edges("gate", route_on_approval, {"deploy": "deploy", "end": END})
builder.add_edge("deploy", END)
graph = builder.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "deploy-1"}}
graph.invoke({"service": "billing-api"}, config)
graph.invoke(Command(resume=True), config) # approves: deploys
denied = {"configurable": {"thread_id": "deploy-2"}}
graph.invoke({"service": "billing-api"}, denied)
graph.invoke(Command(resume=False), denied) # denies: ends without deploying
The conditional edge is the whole point: the gate routes to deploy only when the decision is exactly True, and to the end of the graph otherwise. The input contract is that the resume value must be a Boolean — Command(resume=True) approves and Command(resume=False) denies — and the gate validates it instead of coercing it: a non-Boolean resume value such as the string "false" or "deny" raises a ValueError instead of being treated as approval. Without that validation, a truthy-looking rejection would deploy; without the end branch, the gate would pause for a decision it never enforced.
Fallbacks complete the pattern. When an agent step fails or exceeds its budget, the workflow routes to a human or a deterministic path instead of letting the loop continue. LangGraph enforces loop limits with message counts, token budgets, time limits or an iteration counter, and a hard exit limit is always required — for example, returning FINISH when the step count reaches ten.
Common mistakes when teams choose wrong
Putting an agent in front of a task with a known, fixed procedure. The team pays token and latency costs to re-derive a known answer. Gartner’s March 2026 analysis found agentic models require five to thirty times more tokens per task than a standard chatbot, and practitioner reports converge on five to twenty-five times the cost per task. At October 2026 prices, one practitioner’s worked example puts an eight-call agent run resolving a support ticket at about $0.128 on Claude Sonnet 5.5, while a single classification step inside a workflow costs about $0.000175 on Haiku 5.5. That comparison changes two things at once — the model and the number of calls — so it cannot show the loop alone causes the gap: both the cheaper model and the single call contribute, and the context re-sent on every step adds more. Treat the figures as an illustrative calculation, not a controlled benchmark, and the cheaper-and-faster expectation for workflows as something to test against your own baseline.
Putting a workflow in front of genuinely variable input. The branching explodes into unmaintainable conditionals, and every new input shape becomes a code change. When the team is writing its fifteenth if branch for a new document format, the task needed a bounded model step.
No budget or step cap on agent loops. Runaway loops are one of the most documented production failure modes: an agent enters an infinite retry cycle and consumes cloud budgets overnight, because one bad tool call triggers a cascade of retries. Gartner predicts 40% of agentic AI projects will be cancelled by 2027, driven by cost, unclear ROI and inadequate risk management.
Treating an agent’s output as verified because it sounds confident. Confident hallucination, tool misuse — the right tool with wrong arguments or wrong order — and cascading errors, where one bad tool call poisons every step after it, are all documented failure modes. In a 2026 study of 998 framework bug reports, API misuse and API incompatibility made up over 55% of cases. The fix is external verification: validate arguments against a schema before execution and check outcomes independently of the agent’s own report.
Skipping the failure path. Missing engineering controls are documented contributors to agent failures: weak permissions, absent evaluations, vague tool contracts, context overload, prompt injection, uncontrolled retries, and no owned failure path. That does not rule out model capability as a contributing cause — the research does not establish that missing controls explain most failures. OWASP’s Top 10 for LLM Applications 2025 found 73% of assessed deployments vulnerable to prompt injection. Separate what the agent can read from what it can change.
Bottom line: start deterministic, add agency where it earns its keep
Build the workflow first: it is the control group that tells you what the agent actually adds — same task, same success criteria, and, once you have configured tracing and replay in an engine that supports them and set execution budgets, a replayable trace and a cost baseline to measure against. Lower cost is something to measure in that baseline, not a guaranteed result. Then add one agentic step at a time, with a validation gate and a measured baseline. Measure cost per successful workflow, not cost per query — a $0.20 run that succeeds 20% of the time costs the same per successful outcome as a $1.00 run that succeeds every time ($0.20 / 0.20 = $1.00 per success), and failed runs are paid for either way.
Revisit the decision when inputs, volumes or failure costs change. A task that starts as a research agent can become a workflow once its steps stabilise, and a workflow can grow an agent step when a new input source arrives. The right answer drifts over time, which is why the four questions matter more than any single verdict.



