Calling an LLM Once Doesn't Make It an Agent
Teams that label every LLM wrapper an Agent skip the engineering that prevents runaway loops, enforces permissions, and recovers from failure — the parts that actually determine whether an autonomous system ships or collapses.
A single LLM API call wrapped in a function named `review_agent` is still just a model service call, not an autonomous runtime unit. An Agent is defined by a goal-driven loop: the model inspects state, selects tools, executes actions, reads results, and decides the next step until a stopping condition is met. Skills are reusable operation manuals — packaged steps, scripts, and references — that an Agent can load, but they contain no decision loop of their own. A Subagent is a separately configured Agent delegated by a main Agent, with its own tools, context, and independent loop. The Harness is the outer control layer that provides sandboxing, permissions, state persistence, retries, human-in-the-loop gates, and failure recovery — everything that lets an Agent run safely in production. Confusing these layers leads teams to overclaim capability or underinvest in the runtime infrastructure that makes autonomous systems reliable.
The term “Agent” has become a prestige label applied to anything that touches an LLM, which obscures genuine architectural differences and inflates expectations.
A function named `review_agent` that calls `llm.invoke()` once is architecturally identical to calling a payment API — the name changes nothing.
The gap between a demo and a production Agent is almost entirely in the Harness: sandboxing, state recovery, permission boundaries, and human-in-the-loop gates.
Skills are often mistaken for Agents because they are packaged alongside code, but they lack the decision loop that defines autonomous runtime behavior.
The confusion mirrors an earlier pattern where executives flattened LLMs into “just a search engine,” skipping the system layers that make them useful.