AI agents: where they help and where they hurt
AI agents: understand where they help and where they hurt, with practical criteria for deciding when adopting them is actually worth it.
I built an "agent" that was a script with extra steps
I set out to build an agent to classify support tickets. The ambitious version had a loop: the model decided to read the ticket, search the history, query a knowledge base, decide the category, and if unsure, start over. It looked impressive in the demo and was unstable in production — sometimes it spun through two or three unnecessary iterations, burning tokens and latency, to reach where a single call would have landed. I rewrote it as a deterministic script with exactly one model call at the end. Same accuracy, half the cost, zero surprises. That's when I understood that "agent" had become a word that hides more than it explains.
The plan here is to give practical criteria for deciding when an agent is worth it and when it just adds risk. Since much of what makes an agent useful depends on retrieving the right information, read it alongside the post on what embeddings are.
What an agent actually is
Strip the marketing and an agent is three things: an LLM, a set of tools it can call, and a loop that lets it decide which tool to use and when to stop. That's it. The model gets a goal, picks an action, sees the result, picks the next one, and repeats until it concludes or gives up.
The keyword in that definition is loop. Without the loop, you have just one LLM call with tool use — useful, predictable, cheap. With the loop, you hand over autonomy: the model decides the sequence of steps on its own. That autonomy is exactly what gives it power and what gives it problems. Almost every decision about whether to adopt an agent boils down to: does the gain from that autonomy outweigh the unpredictability it brings?
Where an agent genuinely helps
There's a family of tasks where the loop is worth the cost. The common pattern is: the task is bounded and the result is verifiable.
- Triage and routing. Classify, tag, forward. The action space is small and the result is checkable against a taxonomy.
- Code generation with tests. The agent writes code, runs the test suite, reads the error, fixes it, repeats. Here the loop shines because each iteration has an objective truth signal — the test passes or it doesn't. Verification is built in.
- Research with citations. Search across multiple sources, synthesize, and cite where each claim came from. The loop lets it follow a lead, and the citations give you a way to audit the result.
The common thread: in all of these, there's an objective stopping criterion and a way to verify the agent got it right. The loop works against a real signal, not against the model's own opinion of being done.
Where an agent hurts
The symmetry is direct: an agent becomes a problem exactly when it lacks what makes the good cases good. Four patterns to avoid:
Unbounded autonomy. "Solve the customer's problem" without bounding what it can do is an invitation to erratic behavior. An open action space multiplies the paths to failure.
Irreversible actions without confirmation. Deleting data, sending email, charging a card, deploying to production. If a step can't be undone, the agent can't be the last one to decide alone. The cost of a hallucination here isn't a wasted token, it's a customer charged wrong.
No verification. If there's no test, citation, or external check to validate the result, the agent is grading its own work — and the model is optimistic about its own output. With no truth signal, the loop just accumulates unjustified confidence.
Stacking latency and cost. Each iteration is a model call: more latency, more tokens, more chance of compounding error. A five-step agent is five times slower and pricier than one call — and at each step the previous step's error propagates. At volume, this becomes a bill nobody forecast in the demo.
Human-in-the-loop isn't optional
The bridge between "helps" and "hurts" is almost always where the human sits. The rule I use: the more irreversible or more open-ended the action, the earlier the human needs to step in.
In practice that means designing the agent to propose and ask for approval before executing the critical step, not to execute and notify afterward. For reversible and verifiable tasks — classify, draft, research — the human can sit at the end, reviewing the result. For irreversible tasks, the human sits in the middle, approving the action before it happens. Pulling the human out of the path to "gain autonomy" is the point where most agent projects trade reliability for a pretty demo.
The unpopular opinion: most should be a script
I'll be blunt, because it's the lesson that saved me the most time: most things sold as an "agent" should be a deterministic script with a single LLM call at the point where natural language actually needs interpretation.
# not an agent; a pipeline with one LLM call where it's needed
def classify_ticket(ticket: str) -> str:
context = fetch_history(ticket) # deterministic
category = llm_classify(ticket, context) # one call
if category not in VALID_CATEGORIES: # verification
return "human_review"
return category
Notice what this code does: the flow is fixed and readable, the search is plain code, the LLM enters only where it needs to interpret free text, and there's an explicit verification with a fallback to a human. You get nearly all the value of the "agent" without the loop's unpredictability. The honest question that separates the two: does your problem really require the model to decide the sequence of steps? If the sequence is known, write the sequence. Reserve the loop for when the real path can't be predicted in advance.
Frequently asked questions
What's the difference between an agent and an LLM call with tools?
A call with tools is the model picking an action inside a flow you control. An agent adds a loop where the model itself decides the sequence of actions and when to stop. The difference is who controls the flow: you or the model. That autonomy is what gives it power and also what brings unpredictability.
When is it actually worth using an agent?
When the task is bounded and the result is verifiable by an objective signal: code generation against tests, research with auditable citations, triage against a closed taxonomy. If there's a clear stopping criterion and a way to check correctness without trusting only the model's opinion, the loop pays for itself.
Why do agents get expensive and slow?
Because each loop iteration is a model call, with its latency and token cost. A five-step agent is roughly five times more expensive and slower than a single call, and one step's error propagates into the next. In production, under volume, this stacking becomes a cost the demo never reveals.
Can I let an agent execute irreversible actions on its own?
Not without human confirmation. For any action that can't be undone — delete, charge, send, deploy — the agent should propose and wait for approval, not execute and notify afterward. The cost of a wrong decision in those cases isn't a wasted token, it's real damage, and the model is too confident about its own work to be the final judge.
What to take from this
An agent is an LLM plus tools plus a loop, and the loop is both the power and the risk. It helps when the task is bounded and the result is verifiable — code with tests, research with citations, triage against a taxonomy. It hurts when there's open autonomy, irreversible actions without confirmation, or no verification at all. Keep the human in the path in proportion to the irreversibility. And before building an agent, ask the honest question: does the problem require the model to decide the steps, or is it a script with one LLM call dressed up as something fancier?
- 01 UTF-8 and encoding problems: why accents break and how to fix them What UTF-8 is, code points, mojibake, and why accented text turns to garbage — the mechanism explained end to end.
- 02 MIT, Apache, and GPL Licenses: Practical Differences for Developers MIT, Apache 2.0, and GPL are not the same thing. Understand permissive vs copyleft, patent protection, and compatibility before shipping code to production.