TL;DR
-
Workflows are deterministic graphs - predefined steps, fixed routing, predictable execution. You know what happens before it runs.
-
Agents are dynamic control loops - the LLM decides what to do next at runtime. You know the goal, not the path.
-
Workflows win on reliability, cost, and debuggability - use them when steps are known and consistency matters.
-
Agents win on flexibility - use them when the path depends on runtime data, user input, or exploratory reasoning.
-
Most production systems are hybrids - deterministic workflow skeleton with agent nodes for the steps that require dynamic decision-making.
Why This Matters
The agent hype cycle pushes teams toward full autonomy: "Replace your entire pipeline with an agent." Then production hits - unpredictable costs, non-reproducible failures, compliance teams asking "why did it do that?" and no answer.
The workflow camp pushes back: "Agents are unreliable. Use chains." Then product teams need the system to handle queries the workflow designer didn't anticipate, and the rigid pipeline breaks on edge cases.
Both camps are half right. The engineers shipping reliable AI products aren't choosing workflows or agents - they're choosing the right tool for each step. The support bot runs a deterministic workflow for ticket classification and routing, then an agent for open-ended troubleshooting. The code review pipeline is a fixed sequence of lint → test → LLM review, but the LLM review step uses agentic tool access to explore the codebase.
Understanding this distinction - and where the boundary blurs - is one of the highest-leverage decisions in AI system design.
The Problem Workflows vs Agents Solves
Teams face a design question on every AI feature: how much autonomy should the LLM have?
Too much autonomy (full agent):
- Unpredictable execution paths
- Variable cost and latency
- Hard to test and audit
- Difficult to explain to stakeholders
Too little autonomy (pure workflow):
- Breaks on unanticipated inputs
- Requires manual updates for new scenarios
- Can't handle exploratory tasks
- Feels rigid to users
The solution is a deliberate design choice - not a binary pick, but a spectrum with clear criteria for where each step lands.
How We Got Here
The industry did not invent this spectrum overnight - it rediscovered an old automation ladder with LLMs in the nodes:
Diagram: Evolution of AI agents
flowchart LR
A[Scripts / cron] --> B[RPA / BPM]
B --> C[Durable workflows]
C --> D[LLM chains]
D --> E[Agent loops]
E --> F[Hybrid + HITL]
Automation moved from scripts and RPA to tool-calling LLMs, then to bounded production agent loops.
| Era | What shipped | Gap |
|---|---|---|
| Scripts & cron | Deterministic jobs | Brittle to novel inputs |
| RPA / BPM | Visual / enterprise workflows | Fragile; weak open-ended judgment |
| Durable workflows | Temporal, Inngest, sagas | Explicit steps; limited LLM branching |
| LLM chains | LCEL, fixed LangGraph edges | Predictable; breaks on exploration |
| Agent loops | ReAct / tool loops | Flexible; costly and hard to audit |
| Hybrid production | Workflow skeleton + agent nodes + HITL | Needs routing evals and bounds |
Anthropic — Building effective agents argues for the simplest composition that works - often workflows and prompt chains before full agents. LangGraph makes both patterns first-class (fixed edges vs conditional loops). Coding products like GitHub Copilot and Cursor illustrate hybrid surfaces: fixed IDE actions mixed with open-ended agent runs.
What Are Workflows and Agents?
LLM Workflows
A workflow is a directed graph of nodes where:
-
Nodes are functions (LLM calls, tool calls, data transforms, conditionals).
-
Edges are predefined - routing is deterministic or rule-based.
-
State flows through the graph in a predictable pattern.
# Workflow: fixed pipeline
def support_workflow(ticket):
category = classify(ticket) # LLM call, fixed output schema
if category == "billing":
return billing_handler(ticket) # Deterministic route
elif category == "technical":
return technical_handler(ticket) # Deterministic route
else:
return general_handler(ticket) # Deterministic route
You can trace the execution path before running it (given the classification). Testing is straightforward: mock each node, assert routing.
AI Agents
An agent is a dynamic loop where:
-
The LLM decides the next action at each step.
-
The path is not predetermined - it depends on tool results, reasoning, and runtime context.
-
Termination is conditional - the agent stops when it decides the goal is met (or hits a limit).
# Agent: dynamic loop
def support_agent(ticket):
state = init_state(ticket)
for _ in range(max_steps):
action = llm.decide(state, tools) # LLM chooses next action
if action.type == "done":
return action.response
state = execute(action, state) # Path emerges at runtime
You cannot trace the path before running it. Testing requires scenario-based evaluation, not path assertion.
The Spectrum
| Position | Example | Autonomy |
|---|---|---|
| Pure Code | Regex classifier → SQL query | None |
| LLM Workflow | Classify → route → template response | Low - LLM fills nodes |
| Hybrid | Workflow with agent node for troubleshooting | Medium - agent in one step |
| Constrained Agent | Agent with 3 tools, 5-step limit, allowed actions list | Medium-high |
| Full Agent | Open-ended research agent with 20 tools | High |
Diagram: Deterministic workflow vs agent loop
flowchart LR
A[Pure code] --> B[LLM workflow]
B --> C[Hybrid]
C --> D[Constrained agent]
D --> E[Full agent]
Major components and how control or data moves between them.
How Workflows and Agents Work
Workflow Execution Model
Properties:
-
Predictable - same input category → same path.
-
Testable - unit test each node, integration test each path.
-
Auditable - compliance teams can review the graph.
-
Efficient - no wasted LLM calls on routing decisions.
Frameworks: LangGraph (StateGraph with fixed edges), LangChain LCEL chains, n8n, Temporal with LLM nodes.
Agent Execution Model
Properties:
-
Flexible - handles inputs the designer didn't anticipate.
-
Expensive - multiple LLM calls for routing + execution.
-
Variable - same input may take different paths on different runs.
-
Powerful - handles exploratory, multi-step, conditional tasks.
Frameworks: LangGraph (create_react_agent), AutoGen, CrewAI, OpenAI Agents SDK.
Execution lifecycle (hybrid)
Diagram: State lifecycle
stateDiagram-v2
[*] --> Classify
Classify --> WorkflowPath: known intent
Classify --> AgentPath: complex / low confidence
WorkflowPath --> Validate
AgentPath --> AgentLoop
AgentLoop --> AgentLoop: tool / observe
AgentLoop --> Interrupt: gated write
Interrupt --> AgentLoop: human decision
AgentLoop --> Validate: done / max steps
Validate --> [*]
Valid states and transitions for this control-plane pattern.
Architecture
Hybrid Architecture (Recommended)
The production pattern that works:
Diagram: Hybrid workflow with agent nodes
flowchart TB
In[Request] --> Cls[Classify / route]
Cls --> W[Known-path workflows]
Cls --> Ag[Constrained agent node]
W --> Val[Deterministic validation]
Ag --> Val
Val --> Out[Response / side effects]
Ag --> HITL[HITL gate]
HITL --> Ag
Major components and how control or data moves between them.
-
Entry pipeline - deterministic classification and routing (workflow).
-
Known paths - fixed handlers for common intents (workflow).
-
Complex paths - agent for open-ended tasks (agent).
-
Validation - deterministic output checks regardless of path (workflow).
-
Human escalation - deterministic trigger on confidence/failure (HITL).
Step-by-Step Flow
Scenario: Customer support system handling "I was charged twice for order O-991."
Workflow Path (Billing Category)
- Classify (LLM, structured output) →
{category: "billing", confidence: 0.95} - Route (deterministic) → billing workflow
- Lookup order (tool call, fixed) → order details retrieved
- Check payments (tool call, fixed) → duplicate charge confirmed
- Issue refund (tool call, fixed, requires approval gate) → refund processed
- Format response (LLM, template prompt) → customer notification
- Validate (rules) → refund amount matches, order ID present ✓
Steps 1–7 are predictable. A test engineer can mock each step and verify the path.
Agent Path (Complex Category)
- Classify (LLM) →
{category: "complex", confidence: 0.6} - Route (deterministic) → agent handler
Agent loop begins:
- Thought: "Need to understand the full issue first"
- Action: ask_clarifying_question
- Observation: customer explains multi-order billing issue
- Thought: "Need to check all recent orders"
- Action: search_orders(customer_id)
- Observation: 3 orders, 2 with duplicate charges
- Thought: "Need to issue refunds for both, escalate for root cause"
- Action: issue_refund(order_1), issue_refund(order_2)
- Action: create_investigation_ticket(billing_system)
- Final answer: synthesized response
Validate (rules) → same validation as workflow path
Steps 3 is dynamic - path varies by issue complexity. Steps 1, 2, 4 are deterministic.
Real Production Example
LangGraph hybrid with workflow routing and agent fallback:
from typing import Literal
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from typing_extensions import TypedDict
class IntentClassification(BaseModel):
intent: Literal["billing", "technical", "general", "complex"]
confidence: float
class SupportState(TypedDict):
ticket: str
intent: str
confidence: float
order_data: dict
response: str
classifier = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# --- Workflow nodes (deterministic) ---
def classify_intent(state: SupportState):
result = classifier.with_structured_output(IntentClassification).invoke([
{"role": "system", "content": "Classify the support ticket intent."},
{"role": "user", "content": state["ticket"]},
])
return {"intent": result.intent, "confidence": result.confidence}
def route_intent(state: SupportState) -> str:
if state["confidence"] < 0.7 or state["intent"] == "complex":
return "agent"
return state["intent"]
def billing_workflow(state: SupportState):
order = lookup_order(state["ticket"])
payments = check_payments(order["id"])
if has_duplicate_charge(payments):
refund = issue_refund(order["id"], reason="duplicate_charge")
response = format_billing_response(order, refund)
else:
response = format_no_issue_response(order)
return {"order_data": order, "response": response}
def technical_workflow(state: SupportState):
error_logs = fetch_error_logs(state["ticket"])
diagnosis = classifier.invoke([
{"role": "system", "content": "Diagnose the technical issue from logs."},
{"role": "user", "content": str(error_logs)},
])
return {"response": diagnosis.content}
# --- Agent node (dynamic) ---
support_agent = create_react_agent(
ChatOpenAI(model="gpt-4o", temperature=0),
tools=[search_orders, issue_refund, create_ticket, search_kb, ask_user],
state_modifier="Handle complex support issues. Verify before taking action.",
)
def agent_handler(state: SupportState):
result = support_agent.invoke({"messages": [("user", state["ticket"])]})
return {"response": result["messages"][-1].content}
# --- Validation (deterministic) ---
def validate_response(state: SupportState):
if not state.get("response"):
return {"response": "Unable to process your request. A human agent will follow up."}
if contains_pii_leak(state["response"]):
return {"response": "Your request has been received. A team member will respond shortly."}
return {}
# --- Graph ---
graph = StateGraph(SupportState)
graph.add_node("classify", classify_intent)
graph.add_node("billing", billing_workflow)
graph.add_node("technical", technical_workflow)
graph.add_node("general", general_workflow)
graph.add_node("agent", agent_handler)
graph.add_node("validate", validate_response)
graph.set_entry_point("classify")
graph.add_conditional_edges("classify", route_intent, {
"billing": "billing",
"technical": "technical",
"general": "general",
"agent": "agent",
})
graph.add_edge("billing", "validate")
graph.add_edge("technical", "validate")
graph.add_edge("general", "validate")
graph.add_edge("agent", "validate")
graph.add_edge("validate", END)
support_system = graph.compile()
This is the pattern most production systems converge on: workflow skeleton, agent for the hard part, deterministic validation at the end.
Design Decisions
| Decision | Workflow | Agent | Hybrid |
|---|---|---|---|
| Predictability | High - fixed paths | Low - emergent paths | High for common cases, flexible for edge cases |
| Cost | Low - minimal LLM calls | High - multiple calls per step | Optimized - agent only when needed |
| Latency | Fast - direct execution | Slow - iterative loop | Fast for common paths |
| Testability | Unit + integration tests | Scenario-based eval | Both - test workflow paths + agent eval |
| Auditability | Full - graph is the spec | Partial - log traces | Strong - workflow audit + agent traces |
| Flexibility | Low - breaks on new inputs | High - handles novelty | Medium-high |
| Best for | Known processes, compliance | Exploration, complex reasoning | Production systems |
Decision Framework
Use a workflow when:
- Steps are known and stable
- Consistency is required (compliance, billing, legal)
- You can enumerate the paths
- Cost and latency must be predictable
- Stakeholders need to review the logic
Use an agent when:
- The path depends on runtime discovery
- The task requires exploratory reasoning
- Input variability is high
- Tool selection depends on intermediate results
- The task can't be decomposed upfront
Use a hybrid when:
- Most requests follow known paths (workflow) but some need flexibility (agent)
- You need deterministic guardrails around agentic steps
- Different parts of the task have different autonomy requirements
Comparisons
Workflow vs agent vs hybrid
| Dimension | Workflow | Agent | Hybrid |
|---|---|---|---|
| Control | Explicit DAG / fixed edges | LLM policy selects next action | Workflow skeleton + agent nodes |
| Path known? | Yes (given inputs) | Emerges at runtime | Known for common cases |
| Cost | Low, predictable | Variable with steps | Optimized by routing |
| Testability | Path / branch tests | Scenario evals | Both |
| Auditability | Graph is the spec | Trace-dependent | Strong for known paths |
| Flexibility | Low on novel inputs | High | Medium-high |
| Best for | Compliance, billing, ETL | Exploration, research | Most production products |
When each wins (and when not)
| Choose | Prefer when | Avoid when |
|---|---|---|
| Workflow | Steps stable; consistency required; paths enumerable | Inputs are open-ended and you cannot maintain branches |
| Agent | Next tool depends on observations; high input variance | You need sub-second latency or formal determinism |
| Hybrid | 80% known paths, 20% messy; need guardrails around autonomy | Prototype stage where two systems to test is overkill |
Decision tree: Workflow vs agent vs hybrid
flowchart TD
Start[Is the happy path enumerable?] -->|Yes| Det[Can failures be handled with fixed branches?]
Start -->|No| Agent[Prefer agent loop + bounds]
Det -->|Yes| WF[Prefer workflow / DAG]
Det -->|No| Hybrid[Hybrid: workflow skeleton + agent nodes]
Agent --> Gate{Irreversible writes?}
Hybrid --> Gate
Gate -->|Yes| HITL[Add HITL + durable checkpoints]
Gate -->|No| Eval[Ship with traces + evals]
HITL --> Eval
Enumerate paths first; add agent nodes only where observations change the next step, then gate irreversible writes.
Deepen the agent-side patterns in Agent Architectures; pair irreversible agent steps with HITL and durable execution.
Common Mistakes
-
Agent by default - Using an agent for tasks with known steps wastes money and introduces variance. "Extract fields from invoice" is a workflow.
-
Workflow for everything - Rigid pipelines break on edge cases. If your workflow has 47 conditional branches, you needed an agent for the complex route.
-
No validation layer - Agent output goes directly to users without deterministic checks. Always validate regardless of path.
-
Missing routing - Sending all queries to the agent because "it's smarter." Route by intent/complexity first.
-
Undifferentiated tool access - Workflow steps and agent steps sharing the same tool registry. Workflows should call specific tools directly; agents get curated tool sets.
-
No eval for either path - Workflows need path coverage tests. Agents need scenario evals. Both need end-to-end quality measurement.
-
Confusing LangGraph with agents - LangGraph is a graph framework. You can build workflows (fixed edges) or agents (conditional loops) with it. The framework doesn't dictate the pattern.
Where It Breaks Down
-
Routing errors - Misclassified intents send complex issues to rigid workflows or simple questions to expensive agents. Monitor routing accuracy.
-
Agent in a compliance-critical path - Regulated industries often can't accept non-deterministic execution for certain operations. Keep those as workflows with human gates.
-
Workflow maintenance burden - Workflows with 30+ branches become undebuggable.
Refactor into sub-workflows or convert the complex branches to agent nodes.
-
False economy - Building elaborate routing to avoid agents on tasks that genuinely need them. If 40% of queries hit the agent fallback, consider expanding agent scope.
-
Hybrid complexity - Two systems to test, monitor, and maintain. Justified at scale but overkill for prototypes.
When NOT to Use Agents (Prefer Workflows)
Skip a full agent loop when:
- Steps are known and stable - invoice extraction, ticket classify → template reply, fixed ETL.
- Compliance needs a reviewable graph - regulated billing, legal, or audit-critical paths.
- Cost/latency must be predictable - customer SLAs that cannot tolerate 15–60s variable loops.
- You cannot bound side effects - no RBAC, no validation layer, no HITL for writes.
- You lack routing and path evals - without measuring misroutes, "hybrid" becomes "everything hits the expensive agent."
Conversely, do not force a pure workflow when you already maintain dozens of brittle branches for the same exploratory task - that is when a constrained agent node earns its keep.
Running in Production
Best Practice
✅ Best Practices - Default to workflows, route before invoking agents, validate every path, gate irreversible writes, and measure routing accuracy plus per-path quality before expanding autonomy.
| Dimension | Consideration |
|---|---|
| Scaling | Workflow nodes scale independently and predictably. Agent nodes need pool sizing for variable execution length. Route aggressively to workflows. |
| Latency | Workflows: 1–3s (fixed LLM calls). Agents: 5–60s (variable steps). Publish SLA by path type. |
| Cost | Workflows: $0.001–0.01 per request. Agents: $0.01–0.20 per request. Track cost by path. Optimize routing to minimize agent usage. |
| Monitoring | Workflow: path distribution, node failure rates, latency per node. Agent: steps per task, tool usage, termination reasons. Both: output quality, escalation rate. |
| Evaluation | Workflow: path coverage tests (every branch tested). Agent: scenario eval suites. Hybrid: routing accuracy + per-path quality metrics. |
| Security | Workflows: audit the graph, restrict tool access per node. Agents: RBAC on tool registry, step limits, human approval gates. Both: output validation. |
Important
Default to workflows. Add agent nodes only for steps where you've measured that workflows fail. The hybrid pattern - workflow skeleton with targeted agent nodes - is the production standard, not the exception.
Related Guides
-
Models: GPT-5 · Claude Sonnet · Claude Opus — models used in both deterministic workflows and agent loops.
-
Companies: OpenAI · Anthropic — platforms spanning workflow and agent products.
-
Both patterns: LangGraph - fixed edges (workflow) or conditional loops (
create_react_agent). -
Workflow-first: LangChain LCEL, n8n / Zapier, Temporal / Inngest for durable steps.
-
Agent-first: OpenAI Agents SDK, CrewAI, AutoGen.
-
Guidance & rankings: Anthropic — Building effective agents · Best AI Agent Frameworks · LangGraph vs CrewAI
-
AI Agents: The autonomous pattern - dynamic loops with tool use.
-
Human-in-the-Loop: Approval gates on agent (and some workflow) writes.
-
Durable Execution: Checkpointing long hybrid runs and interrupts.
-
Agent Architectures: How agent nodes within hybrid systems are structured.
-
Agent Planning: Planning blurs the workflow/agent boundary - structured plans resemble workflows.
-
Multi-Agent Systems: Multi-agent pipelines often use workflow-style orchestration with agent workers.
-
Multi-Agent Handoffs: Peer transfer inside hybrid or multi-agent graphs.
-
Guardrails: Validation layer that applies to both workflow and agent outputs.
If you understood this topic, read next:
Diagram: Learning path: workflows to agents
flowchart LR
A[Workflows] --> B[HITL]
B --> C[Durable]
C --> D[Architectures]
D --> E[Handoffs]
E --> F[Multi-agent]
Prerequisites: AI Agents · Prompt Engineering
Next topics: Human-in-the-Loop · Durable Execution · Agent Architectures
Estimated time: 45 min · Difficulty: Intermediate
Key Takeaways
- Workflows have predefined paths; agents choose the next action at runtime.
- Workflows win on predictability, cost, testability, and auditability; agents win on novel inputs.
- Most production systems are hybrids - workflow skeleton with constrained agent nodes.
- Default to workflows; add agents only where evals show fixed paths failing.
- Always validate outputs and gate irreversible writes - path type does not remove that duty.
- Route by intent/complexity before invoking agents - the highest-leverage cost control.
- The real question is which steps need autonomy, not whether the product is "an agent."
FAQs
Is a LangChain chain a workflow?
Yes. LCEL chains and LangGraph graphs with fixed edges are workflows. The term "chain" predates "workflow" in the LLM ecosystem but describes the same pattern.
Is Plan-and-Execute a workflow or an agent?
Both. It has a workflow structure (plan → execute steps sequentially) with agent-like behavior in the replanner. This blurring is normal - focus on whether the path is predictable, not the label.
Can a workflow contain LLM calls and still be a workflow?
Yes. LLM calls in fixed positions with structured outputs are workflow nodes. The LLM fills a step; it doesn't choose the next step.
How do I decide where to put the agent in a hybrid system?
Identify the step where execution path depends on runtime data. In support: classification is workflow, troubleshooting is agent. In code review: lint/test are workflow, analysis is agent.
What's the cost difference?
Workflows typically cost 1–3 LLM calls per request. Agents cost 3–15+. Hybrid systems cost proportional to agent usage rate. If 80% of queries take the workflow path, average cost stays low.
Can I convert a workflow to an agent later?
Yes, incrementally. Replace one workflow branch with an agent node, measure quality improvement, expand if justified. Don't rewrite the entire system.
Are AI agents just if-else with LLM?
Agents replace hardcoded conditionals with LLM decisions. The if-else framework (or LangGraph routing) still exists - what's dynamic is the decision inside the loop, not the outer structure.
What about "agentic workflows"?
Marketing term for hybrids - workflows with agent nodes. The pattern is valid; the label is redundant. Call it a hybrid system.
How do I test a hybrid system?
Workflow paths: unit test each node, integration test each route. Agent paths: scenario eval with expected outcomes. Routing: test classification accuracy. End-to-end: golden test set covering both paths.
When is a full agent (no workflow) appropriate?
Internal tools for power users (coding agents, research tools), exploratory tasks with no compliance constraints, and prototyping. Customer-facing production systems rarely stay full-agent.
Does this apply to multi-agent systems?
Yes. Multi-agent orchestration is typically workflow-like (supervisor routes to workers), while individual agents may use agent loops internally. See Multi-Agent Systems.
What's the simplest hybrid pattern?
Classify intent (LLM) → if known intent, fixed handler (code/chain) → else, ReAct agent → validate output (rules). Five nodes in LangGraph. Start here.
References
- Anthropic — Building effective agents
- LangGraph Documentation
- LLM-based Multi-Agents: A Survey of Progress and Challenges (arXiv:2402.01680)
- OpenAI Agents Guide