DEV Community

lamingsrb
lamingsrb

Posted on Originally published at lazar-milicevic.com

Agentic Workflows vs AI Agents: What Ships

Agentic Workflows vs AI Agents: What Ships

Last month I killed an "autonomous agent" I had been babysitting for six weeks and replaced it with a boring state machine that calls an LLM at four specific steps. Output quality went up, cost dropped by roughly 70%, and I stopped getting Slack alerts at 3 a.m. That is the whole post, really. But the reasoning behind that swap is where most teams are getting the architecture wrong right now, so let me show you the actual difference between an agentic workflow and an AI agent, and when each one earns its place in production.

The Distinction That Actually Matters

An agentic workflow is a predefined graph where an LLM makes decisions at specific nodes, but the control flow is written by you. An AI agent is a loop where the LLM itself decides what to do next, which tool to call, and when to stop. Anthropic's engineering team drew this line clearly in their "Building effective agents" post, and I think it is the most useful framing anyone has published on this.

The confusion is that both use LLMs, both call tools, both can look "smart." The difference is who owns the control flow.

Dimension Agentic Workflow AI Agent
Control flow You (code) LLM (loop)
Steps Fixed or bounded DAG Open-ended
Debuggability High, per-node traces Low, emergent
Cost per run Predictable Highly variable
Failure mode Node fails, retry Loop diverges, burns tokens
Best for Known process, unknown content Unknown process, small scope

In my content system (BizFlowAI ContentStudio), I run both patterns side by side. Research and outline generation is a workflow. In-article fact-check with tool use during editing is a bounded agent. Publishing is a workflow again. Mixing them was the unlock.

Where I See Teams Burn Money

Most teams reach for a fully autonomous agent first because it looks more impressive in a demo. Then they hit production and discover three things at once:

  1. Token cost variance is brutal. A workflow costs $0.08 per run, plus or minus a cent. The same task as an autonomous agent averages $0.11, but the tail runs at $2.40 when it gets stuck in a self-correction loop. Your monthly bill is set by that tail, not the average.
  2. Debugging is guesswork. When a workflow node fails, I see the exact input, the prompt, the output, the tool call. When an agent misbehaves at step 14 of an emergent 22-step trajectory, I am reading a novel to figure out what happened.
  3. Latency creeps up. Every extra "let me think about this" turn adds 3 to 8 seconds. Users notice at 15 seconds. Agents cross that line often.

I ran a small internal measurement across 500 content generation runs, splitting the same task between a five-node workflow and a ReAct-style agent with the same tools:

  • Workflow: 100% completion, mean cost $0.079, p95 latency 41s
  • Agent: 94% completion, mean cost $0.112, p95 latency 78s, p99 cost $2.11

The 6% failure rate on the agent side was almost entirely "it kept trying to improve the output past the point of usefulness." That is not a prompt problem. It is an architecture problem.

When an Agent Actually Earns Its Keep

I do use agents in production. Just not for everything. An agent is the right call when the process is unknown but the scope is small and bounded. Three concrete examples from my own work:

  • Debugging assistant with shell access. I do not know in advance which files matter, which grep will surface the bug, or whether I need to read git blame. Claude Code doing agentic exploration inside a repo is genuinely better than any workflow I could write, because I cannot pre-specify the graph.
  • Data reconciliation across mismatched schemas. When comparing two vendor APIs where the mapping is fuzzy, an agent that can call list_fields, sample_records, and compare in whatever order it needs beats a rigid pipeline.
  • In-article fact-check. During editing, I let an agent decide which claims to verify and which sources to query. But I put a hard budget on it: max 6 tool calls, max 90 seconds, max $0.15 in tokens. If it hits any ceiling, the workflow catches it and moves on.

That last point is the trick. Every production agent I run has three hard budgets: turns, wall clock, and dollars. Without them you have a research project, not a system.

The Decision Framework I Use

Before I write a line of code, I answer five questions. If four or more push toward "workflow," I do not build an agent.

1. Can I draw the steps on a napkin before running it?
   Yes -> workflow. No -> maybe agent.

2. Does the step count vary by more than 3x across runs?
   No -> workflow. Yes -> agent territory.

3. Do I need per-step audit logs for compliance or debugging?
   Yes -> workflow. No -> either.

4. Is cost variance above 2x acceptable to the business?
   No -> workflow. Yes -> agent OK.

5. Is a human going to review the output before it ships?
   No (autonomous) -> workflow, with agent sub-tasks only.
   Yes -> agent OK.
Enter fullscreen mode Exit fullscreen mode

The one that surprises people is #5. I run content systems unattended, publishing without a human in the loop. That constraint alone forces workflow architecture at the top level. An autonomous system needs predictable behavior. Agents are unpredictable by design.

What a Good Agentic Workflow Looks Like in Code

Here is the shape of the top-level flow in my content pipeline, simplified. This is the boring, reliable core. Real code has retries, DLQs, and observability wrapped around each node, but the structure is this simple.

async function runContentPipeline(input: BriefInput) {
  const trace = startTrace(input.id);

  // Node 1: workflow. Deterministic LLM call.
  const research = await researchTopic(input, { model: "sonnet" });
  trace.log("research", research);

  // Node 2: workflow. Deterministic LLM call.
  const outline = await generateOutline(research, { model: "sonnet" });
  trace.log("outline", outline);

  // Node 3: workflow. Fan-out, parallel LLM calls per section.
  const sections = await Promise.all(
    outline.sections.map((s) => writeSection(s, research))
  );
  trace.log("sections", sections);

  // Node 4: BOUNDED AGENT. Fact-check with tool use.
  // Hard limits: 6 turns, 90s, $0.15.
  const verified = await factCheckAgent(sections, {
    maxTurns: 6,
    maxSeconds: 90,
    maxCostUSD: 0.15,
    onBudgetExceeded: "return_partial",
  });
  trace.log("factcheck", verified);

  // Node 5: workflow. Deterministic assembly.
  const article = assembleArticle(verified, outline);

  // Node 6: workflow. Publish with retries.
  return publish(article, input.destination);
}
Enter fullscreen mode Exit fullscreen mode

Five of six nodes are pure workflow. One is an agent, and it lives in a cage. The cage is what makes it production-safe.

Notice what is missing: there is no top-level "let the LLM decide what to do next." That is intentional. The LLM decides content, not control. I have run this pipeline unattended across multiple sites and the failure rate at the workflow level is essentially zero. Failures happen inside the fact-check agent when it hits budget, and the workflow handles that gracefully.

Cost, Reliability, and Debuggability, in Order

If I had to rank what matters in production LLM systems, it would be: debuggability, reliability, cost, latency, quality. In that order. Quality being fifth surprises people, but it is because the first four determine whether quality even matters. A brilliant system that fails 8% of the time and burns unpredictable money will not survive contact with a real business.

Agentic workflows dominate on the first three. Agents dominate on quality for open-ended tasks. The mistake is choosing quality-of-best-case over reliability-of-worst-case. Production is defined by worst cases.

The other dimension nobody talks about: debuggability compounds. Every workflow node I can inspect adds up over months. I now have six months of structured traces from my content system, which lets me improve prompts based on real failure patterns. If it were an autonomous agent, I would have six months of unstructured trajectories that are much harder to learn from. This is a real, cumulative advantage.

Two Traps I Fell Into

Trap 1: "Let's add a planning step." I once tried to add an LLM planner at the top of a workflow to decide which nodes to run. It felt clever. In practice, it added a 4-second latency hit, a $0.02 cost bump per run, and it was wrong about 12% of the time in ways that were hard to detect. I removed it and hardcoded the routing. Sometimes if-else is the right answer.

Trap 2: "The agent will handle edge cases." No, it will not. Agents handle edge cases the way a puppy handles a busy street: enthusiastically and badly. If you have a known edge case, code it. Agents are for cases you cannot enumerate, not for laziness in enumerating the ones you can.

What I'd Do If I Were You

If you are starting an LLM system today:

  1. Default to workflow. Draw the graph. Write the nodes. Use the LLM at specific decision points. Ship it.
  2. Introduce agents only where the process is genuinely unknown, and always with hard budgets on turns, time, and dollars.
  3. Instrument every node. Log inputs, outputs, tool calls, token counts, latencies. You will thank yourself in three months.
  4. Measure the p95 and p99, not just the mean. Your bill and your users live in the tail.
  5. Treat "autonomous end to end" as a maturity milestone, not a starting point. My content system runs unattended because each piece has been hardened separately over months. It did not start that way.

The industry has a bias toward agentic-looking demos because they are impressive on stage. Production has a bias toward boring systems that work. The gap between the two is where a lot of budgets get burned.

If you are debating the pattern for a real system and want a second pair of eyes on the architecture, get in touch at lazar-milicevic.com/#contact. I write more on production LLM patterns, RAG, and multi-agent systems on the blog.

Top comments (0)