You Don't Need an Agent for That

You Don't Need an Agent for That

Published: August 11, 2026

Watch as video

Same content on YouTube if you prefer video.

Watch on YouTube

One of my clients recently had a real problem: support tickets were piling up faster than anyone could triage them.

Someone had to read each one, figure out the category, and route it to the right queue.

They reached for an AI agent.

The idea was simple enough: give an LLM the ticket, a set of tools, and the goal "route this correctly," and let it figure out the rest.

Three weeks in, they had a working prototype that was slow, expensive per ticket, and occasionally routed a billing question to the security team for reasons nobody could reconstruct from the trace logs.

Then someone pulled the historical tickets, trained a very simple plain-text classifier on eighteen months' worth of routing decisions, and had something faster, cheaper, and more predictable running by the end of the week.

The technology was almost embarrassingly boring.

And that was exactly the point.

Classification is a problem that had already been solved by supervised learning for decades.

You don't even need an LLM for that.


Task, Goal, and the Difference That Actually Matters

One of the easiest ways to decide whether you need an agent is to ask a deceptively simple question:

Can I describe the correct output as a function of the input?

A task is a fixed input-output mapping.

Given this ticket:

My invoice contains two charges for the same subscription.
Can you refund the duplicate?

Produce:

billing

That's a function:

def classify(ticket):
    return model.predict(ticket)

There's no state.

No branching.

No decision about what to do next.

No need to inspect the result of one action before deciding which action to take.

Just:

A goal is different.

A goal describes an outcome without prescribing the path to it.

For example:

Resolve this customer's problem.

That could involve:

The next step depends on what you discover.

That's where an agent starts becoming interesting.

But here's the trap.

"Route this ticket correctly" sounds like a goal because it's phrased as an instruction.

It isn't necessarily one.

If there's one correct routing decision for a given ticket, the problem is still fundamentally:

It just happens to be written in imperative English.

The distinction isn't about how open-ended the sentence sounds.

It's about whether the path to the answer needs to be discovered at runtime.

That distinction is the whole ballgame.


A Simple Test

Before reaching for an agent, try to write the problem as a function.

For example:

def route_ticket(ticket):
    """
    Input:
        ticket: customer support message

    Output:
        one of:
        - billing
        - security
        - technical
        - account
    """
    ...

If you can reasonably define the function, the next question is:

Do I have historical examples of this function's inputs and outputs?

If the answer is yes, you probably have a machine learning problem.

For example:

That's training data.

You don't need to give a model a toolbox and ask it to discover what classification means.

You can just teach it the mapping.


What This Looks Like in Code

The actual model could be remarkably simple.

For example, a traditional text classification pipeline might look roughly like this:

from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression

model = Pipeline([
    ("features", TfidfVectorizer(
        ngram_range=(1, 2),
        min_df=2
    )),
    ("classifier", LogisticRegression())
])

model.fit(training_tickets, training_labels)

queue = model.predict([
    "I was charged twice for my subscription"
])[0]

print(queue)
# billing

No prompt engineering.

No tool calling.

No agent framework.

No conversation history.

No autonomous loop.

Just a model learning:

And that's often exactly what you want in production.

You can measure it with a confusion matrix:

Actual \ Predicted Bill Sec Tech Account
Bill 940 3 12 5
Sec 2 410 4 1
Tech 8 2 870 9
Account 4 1 7 690

Now you can see exactly where the system fails.

Compare that with:

Agent trace:
"I thought this might be a security issue..."
"Then I checked the customer..."
"Then I considered billing..."
"Then I decided..."

One is a confusion matrix.

The other is a detective novel nobody asked for.


Workflow: Control Logic a Human Already Worked Out

A lot of what looks like it needs a decision-making system is actually a workflow.

Consider support routing again.

Maybe the actual process is:

You might even use an LLM for classification:

category = llm.classify(ticket)

customer = get_customer(ticket.customer_id)

queue = routing_rules(
    category=category,
    customer_tier=customer.tier
)

send_to_queue(ticket, queue)

There's nothing wrong with using an LLM here.

But this still isn't necessarily an agent.

The order of operations was decided by a human.

The branching was decided by a human.

The exit conditions were decided by a human.

The model is just one component in the workflow.

That's an important distinction because workflows have a major engineering advantage:

the control flow is visible.

You can read the code and answer:

What happens next?

With an agent, the equivalent answer may be:

Depends on what the model decides.

That can be useful when the environment genuinely requires exploration.

It's much less useful when you've already worked out the process.


Example: LLM Workflow vs Agent

Imagine an employee asks:

"What's the status of my expense reimbursement?"

A workflow might be:

employee = get_employee(user_id)
expense = get_latest_expense(employee.id)
status = get_expense_status(expense.id)

return format_response(status)

The LLM could turn the result into a natural-language response.

Still a workflow.

Now imagine the requirement is:

"Help resolve whatever problem this employee is having with their reimbursement."

The agent might need to:

The interesting part isn't that an LLM is involved.

The interesting part is that the next action wasn't known in advance.

That's agent territory.


Where a Plain Model Beats an Agent

Plenty of tasks that get pitched as agent projects are, underneath, classification, regression, or ranking problems that classical or lightweight ML already handles well.

1. Ticket and Email Triage

Input:

"Can I change the credit card associated with my subscription?"

Output:

billing

That's classification.

A classifier trained on historical tickets is a natural fit.

The system doesn't need to reason about what tool to call next.


2. Churn Prediction

Suppose you're trying to predict whether a customer is likely to cancel.

You might have:

account_age
monthly_spend
number_of_logins
support_tickets
days_since_last_login
feature_usage

The output could be:

P(churn) = 0.83

A gradient-boosted model is perfectly happy with this.

model.predict_proba([
    customer_features
])

An agent investigating the customer's account might produce a fascinating explanation.

But if the actual requirement is:

"Give me a churn probability."

then you've replaced a millisecond prediction problem with an expensive investigation.


3. Fraud Detection

Fraud systems often need something very boring and very valuable:

For example:

risk = fraud_model.predict_proba(transaction_features)[0, 1]

if risk > 0.95:
    block(transaction)
elif risk > 0.75:
    review(transaction)
else:
    approve(transaction)

You generally want the same input to produce the same decision boundary.

Introducing an autonomous model that can inspect arbitrary tools and make up its own investigation strategy adds variability to a problem where consistency is one of the requirements.


4. Demand Forecasting

If you're forecasting tomorrow's demand for a product, the model might need:

historical demand
seasonality
day of week
promotions
price
holidays
weather

Then:

That's a forecasting problem.

There's no useful role for an agent deciding:

"I should investigate what happened last Tuesday before making my prediction."

The model already has Tuesday in the dataset.


5. Defect Detection

Imagine a production line with a camera inspecting every manufactured part.

The input is an image.

The output is:

OK

or:

DEFECT

An image classifier can evaluate thousands of frames.

You don't need an agent to look at the image, call a tool, think about the image, reconsider the image, and then classify the image.

The factory doesn't care about the model's inner monologue.

It cares about the defect rate.


The Hidden Cost of Using an Agent

The problem with agents isn't that they're inherently bad.

It's that every additional degree of freedom becomes another thing your production system has to tolerate.

Consider a simple classifier:

Now compare it with an agent:

Every additional step can introduce:

  • latency
  • cost
  • transient failures
  • incorrect tool selection
  • hallucinations
  • non-deterministic behavior
  • state-management problems
  • observability complexity

And eventually someone has to explain the whole thing to the person who owns the SLA.

The more autonomy you add, the more expensive failure becomes.


Where an Agent Genuinely Earns Its Cost

None of this makes agents the wrong choice everywhere.

There are problems where the path genuinely isn't knowable in advance.

Consider an on-call assistant.

You give it a problem:

"The checkout service is returning elevated 5xx errors."

You might expose tools like:

get_logs()
get_metrics()
get_deployment_history()
get_database_status()
get_feature_flags()
rollback_deployment()

The agent might discover:

The important property here is that you couldn't necessarily write this exact workflow beforehand.

The agent discovers the path from observations.

That's what makes it useful.


Research Is Another Example

Suppose you ask:

"Figure out why our cloud costs increased 30% last month."

There isn't necessarily one predefined workflow.

The agent might:

The next question depends on the answer to the previous question.

That's fundamentally different from:

The former is exploration.

The latter is mapping.


Coding Agents Are a Good Example Too

A coding agent can do something a static workflow struggles with:

The environment gives the agent feedback.

That feedback changes what it should do next.

You could technically enumerate every possible sequence in advance.

You'd also technically be able to predict the weather by asking every molecule where it's going.

Neither is particularly useful.


A Useful Mental Model

A simple way to think about the three categories is:

And before either of those:

So the progression is roughly:

Model

Workflow

Agent

The mistake is jumping directly to the third one.


The Question to Ask Before Building an Agent

The reflex to reach for an agent is understandable.

Agents are interesting.

They're well funded.

They demo well.

A fixed classifier doesn't exactly make for a conference keynote.

But production systems don't award points for having the most fashionable architecture.

They award points for:

cost
latency
reliability
predictability
maintainability

So before reaching for an agent framework, ask:

Does the mapping from input to correct output already exist?

If yes, ask:

Can I learn that mapping from data I already have?

If yes, start there.

If the process is fixed but contains a few intelligent steps, build a workflow.

If the next action genuinely depends on what the system discovers, then consider an agent.

The goal isn't to use the most autonomous system you can build.

The goal is to use the simplest system that actually solves the problem.

Sometimes that's an agent.

Sometimes it's an LLM call.

Sometimes it's a workflow.

And sometimes, slightly horrifyingly, it's logistic regression.

That's not a failure of AI.

It's what good engineering looks like.