DEV Community

Cover image for The Steelman: When an AI Agent Actually Earns Its Complexity
James Anderson
James Anderson

Posted on AI-assisted

The Steelman: When an AI Agent Actually Earns Its Complexity

A while back I wrote that most "AI agents" are just pipelines in a trench coat — deterministic workflows with an LLM call in them, dressed up as autonomous reasoning. I meant it, and I still do. The comment thread mostly agreed, often with better numbers than mine (one person audited their "agent" and found it made the same four API calls, in the same order, 94% of the time — the other 6% were retries).

But the best replies all circled the same fair question, and it nagged at me:

Fine. So when do you actually need a real one?

And I noticed something uncomfortable: nobody in that thread — including me — could point to a clean production case where genuine autonomy was necessary and a linear pipeline would have failed. A critique that can't describe its own exception isn't rigorous. It's just a vibe with good branding.

So this is me arguing the other side, as hard and as honestly as I can. Not "actually agents are great" — that would be as lazy as "agents are always bad." This is the steelman: the narrow, demanding conditions under which autonomy genuinely earns its cost. If your system meets them, the trench coat is a real coat. If it doesn't — and most don't — you're still paying agent prices for a pipeline.

Let's set the bar high, because that's the whole point.

First: remember that autonomy is a cost

The question is never "could an agent do this?" An agent could do anything; that's not a useful bar. The question is whether the task requires the model to own the control flow — because handing it the wheel is expensive, and you should have to justify the expense.

The bill, from the last piece: nondeterminism (same input, different path, bugs that don't reproduce), a debugging tax (you're doing forensics on a decision, not reading a stack trace), a token cost (a reasoning loop deliberating over routes you already knew), and no test story (you can't write regression tests against a system with no fixed paths).

So the real question is: does this task force the model to make control-flow decisions at runtime that genuinely could not have been made at design time — and is that worth the cost?

Most tasks don't. This piece is about the few that do. Here's what a real justification actually looks like.

Condition 1: The environment talks back

The cleanest case for real agency is when the next step depends on a response you cannot know until you act — because something outside your system gets a say.

A commenter put it better than I could: you can't pre-draw a conversation. If your system is negotiating, coaching, supporting, or interacting with a live participant whose reply branches unpredictably, there's no flowchart to draw in advance, because the flowchart has a second author who isn't in the room yet. The environment is a participant, not a fixed input.

Same logic applies to interacting with external systems that answer unpredictably — an API whose responses genuinely change what you should do next, a scraper facing a DOM that mutated overnight, a tool that fails in ways you can't fully enumerate. When the world talks back and its answer determines your path, you have a legitimate reason for runtime control flow.

The test: is there a step where a response from outside your system decides what happens next, in a way you couldn't script ahead of time? If yes, that's a real branch you can't pre-draw. If the "conversation" is really just you calling three tools in a fixed order, the environment isn't talking back — you're talking to yourself.

Condition 2: The path is discovered, not designed

The second case is genuine multi-hop, where the flowchart is the thing being discovered rather than the thing you drew.

The canonical example a commenter gave: open-ended debugging. You don't know step 2 until step 1's traceback tells you what actually broke. The bug that only appears on empty input isn't visible by reading the code — it exists only once you run the thing and read what came back. A fixed pipeline has nothing to branch on there, because the branch condition doesn't exist until execution produces it. Research and exploration work the same way: each finding determines the next question, and you couldn't have listed the questions in advance because they're generated by the answers.

Here's the sharp test the thread converged on, and it's better than my original "can you draw the flowchart": can a path appear that nobody wrote? If the system composes a sequence of actions from primitives that you genuinely could not have enumerated ahead of time, that's discovery — real agency. If every path it takes traces back to a line of code you wrote, it's branching in a costume, no matter how many branches there are. The distinction isn't "does the path vary." It's "is the model composing the path, or selecting from paths you already laid down."

Condition 3: The branch space is genuinely unenumerable

This is the condition people most often think they meet and don't, so I'll be strict about it.

Real agency needs a space of possibilities too large to pre-list — not "an if-statement with three cases." Here's the boundary a commenter drew that I've adopted: call tool A, on error call tool B, escalate to C. That feels dynamic, and you technically can't draw it as a single linear flow. But it's a fixed decision tree — you enumerated every branch in advance, you just wrote them as error handlers instead of a diagram. That's a pipeline. Retry-with-backoff is a pipeline. A router with five known routes is a pipeline.

Real agency starts where the branches themselves are unknowable until runtime — where you're handing the model a set of actions and letting it compose sequences you never listed, because listing them was impossible, not just tedious. The test: could you, with enough patience, have written every path as explicit code? If the answer is "yes, it'd just be a lot of if-statements" — write the if-statements. They're debuggable. If the answer is "no, the space is genuinely open," you have a candidate for real autonomy.

The load-bearing caveat: even then, minimize it

Here's where the steelman lands back near the pipeline, and this is the part that keeps it honest.

Even when a task genuinely clears the conditions above, the discipline is not "unleash the agent." It's to shrink the autonomous surface to the smallest possible point. The commenters said this better than I will: "one decision point out of fifteen steps, not the whole loop." "A bounded choice with a hard fallback." Deterministic orchestration wraps the model, and the model owns only the one decision that genuinely requires runtime judgment — everything around it is plain, testable, boring code that you were going to write anyway.

So the real design question, as one reader reframed it, was never "is this an agent or a pipeline?" It's where does the decision boundary belong — and the answer is almost always "at one node, not across the whole graph." A system doesn't become more capable because the model owns more of the control flow. It becomes less debuggable. Give the model the one branch it earns, hard-code the rest, and even your genuine agent is 90% pipeline.

The price of admission: it has to be cheap to verify

There's one more condition, and it's the one that upgrades the whole test — because a task can clear every condition above and still not justify autonomy.

The rule the thread landed on: autonomy is only defensible where each autonomous decision produces an outcome that is cheap to check, and the check leaves a record. The scraper adapting to a changed DOM earns its freedom precisely because "did we get the data?" is instantly verifiable. The 429-retry earns it because "did the request succeed?" is a cheap, clear signal. The wrong decision gets caught immediately, cheaply, and on the record.

The corollary is brutal: unverifiable autonomy is never justified, no matter how genuinely dynamic the task is. If the model makes a runtime decision whose correctness you can't check quickly and can't log durably, you haven't built an agent — you've built a source of expensive, untraceable nondeterminism. As one reader put it, agency without observability is just nondeterminism at premium rates. And another added the piece I keep coming back to: the verification has to carry who checked, not just that a check ran — an authorless green light is the thing nobody will stand behind.

The actual test

Pull it together, and the steelman gives you a bar with four requirements, all of which must hold:

  1. A path can appear that nobody wrote — the environment talks back, or the steps are discovered at runtime, not designed in advance.
  2. The branch space is genuinely unenumerable — not a decision tree you could have written as if-statements with enough patience.
  3. The autonomous surface is minimized — the model owns the one decision that needs runtime judgment, and deterministic code owns everything else.
  4. Each decision is cheap to verify, and the check leaves a record — with an author, so someone stands behind it.

Miss any one, and you're paying agent prices for a pipeline. Meet all four, and — finally, honestly — the trench coat is a real coat, and the complexity earned its place.

The uncomfortable conclusion

Here's what happened when I tried to argue the other side as hard as I could: I built a rigorous case for when agents are worth it, and the case is narrow. The set of tasks that clear all four conditions is small, and most of what gets called "agentic" in 2026 still doesn't make the cut.

Which means this piece doesn't contradict the last one. It completes it. The strongest possible argument for real agents turns out to also be the clearest measure of how rarely you need one — because the conditions that justify autonomy are exactly the conditions most systems don't meet. The steelman for the trench coat is also the proof that most coats are empty.

Autonomy is a cost. Now you know precisely what a justification looks like — and precisely how seldom you'll actually have one.


Last time I asked what you'd built that turned out to be a pipeline in disguise. This time the harder question: has anyone shipped something that clears all four conditions — genuine unenumerable branching, a minimized surface, cheap verified checks with an author — in production, not a demo? I asked the last thread and got no clean answer. I'm asking again, because I genuinely want to see one. Prove me wrong in the comments.

Top comments (0)