Bytes & Miles · AI

When does an app stop using AI and start being agentic?

Every product is "AI-powered" now, and the phrase has stopped meaning anything. But there's a real, sharp line between an app that just calls a model somewhere inside it and an app that's genuinely agentic, and it has nothing to do with how clever the model is. It comes down to one question: who decides what the app does next, step to step: you, or the model?

In this post we'll work through a problem you've lived if you've ever run a data warehouse: one morning a dashboard that used to load instantly is crawling, nobody shipped anything new, and the cause is a single query that used to take four seconds and now takes ninety, scanning half a terabyte every time someone hits refresh.

Somebody has to notice it, work out why, fix it, and prove the fix actually held, and we'll solve that exact problem three times over. We'll build on Snowflake, though the shape is universal to any warehouse or pipeline, and the goal stays the same across all three versions; what changes is how much of the thinking we hand to the model:

Option A
Option A · a straight line

You wrote every decision yourself.

Option A as a flow, left to right: a nightly job reads the query history that Snowflake already records, aggregates it, runs it through a rules engine you wrote by hand, and sends an email. There is no model anywhere in this path.

QUERY_HISTORY+ ACCESS_HISTORY
aggregate
RULES ENGINEevery rule hand-written
SEND_EMAIL

A nightly job pulls the history, rolls it up, runs it through rules you wrote, and emails what it found.

  • The two history views are already there. Snowflake logs every query automatically, so step one is just reading data it kept for you.
  • Every branch is hand-written: the thresholds, the order, what counts as "slow."
  • There's no model anywhere in this picture. It's a cron job and a pile of if-statements, the way monitoring has always worked, and this exact pattern predates LLMs by decades.
  • It's fully deterministic: the same history going in always produces the same alerts coming out. Easy to test, easy to audit, nothing ever surprises you.
  • That predictability is also the ceiling. A brand-new way for a query to go bad, one you never wrote a rule for, sails straight through unflagged. The app can only ever do what you already thought of.
who decides what happens?YOU · all of it
Option B
Option B · still a straight line

A model fills one blank. You still drew the line.

Option B as a flow, left to right: your code picks the slow queries, then a model rewrites the SQL. In Snowflake that model call is Cortex. Your code then checks the rewrite returns the same rows, benchmarks it, and emails the result. The model fills one step; your code controls everything around it.

pick slow queries
MODELrewrite the SQL
check same rows
benchmark
email

Now the rewrite step is a model, but the model is on a leash.

  • You still pick which queries to look at, you verify the rows match, you benchmark, you send the mail, in that exact order.
  • The model answers one question, in one spot, then your code takes back over.
  • The model is just a function call: hand it text, get text back. It never decides what happens next. It can't reach for another tool, reorder the steps, or loop, because your code owns the control flow start to finish.
  • Swap the model out for a hand-tuned heuristic and the diagram is identical. That's the tell: the shape of the app doesn't depend on the model at all.
  • Give it a smarter model and you get a better rewrite, not more autonomy. Intelligence isn't agency, which is exactly the line this post opened with.
  • This is what "AI-powered" usually means. It is not agentic.
who decides what happens?still YOU
Option C
Option C · not a line, a loop

You hand over the goal. The model holds the wheel.

Option C as a loop: you give the model a goal and a toolbox of allowed actions, such as reading a query's profile, inspecting the table, checking how it's clustered, or benchmarking a change. The model thinks about what to try next, picks one tool, observes the result, then loops back to decide its next move on its own, repeating until it judges the job is done and sends an email.

goal + toolbox
MODELthink: what do I try next?
act: pick ONE tool
get_query_profile · inspect_ddl · check_clustering
run_explain · compare_results · benchmark
observe result ↩ back to the model
email

↻ the model loops on its own · until it decides it's done

This time you don't hand over a list of steps at all. You hand over two things:

  • A goal: "make this query faster, and prove it."
  • A toolbox: the actions you've allowed the model to take on its own (the panel on the right). Most are things Snowflake already exposes; you're just letting the model reach for them.

And you don't have to build this loop from scratch: Snowflake's own Cortex Agents are this exact shape, an LLM handed a set of tools and left to loop inside the warehouse until the goal is met.

Think of hiring an expert and pointing at a wall of tools. You don't tell them which one to grab, or in what order: you say what "done" looks like and let them work. The model picks one tool, looks at what comes back, decides the next move, and repeats, looping on its own until it judges the job is finished. You stopped writing the steps; you only wrote the goal. That's the line.

who decides what happens next?the MODEL
Compare
Side by side · the whole picture

Same goal. Three owners of the next step.

Option A
a straight line
0 models
you pull history
you aggregate
you run rules
you email

Every step hand-written. Reliable, but blind to anything you didn't foresee.

YOU · all of it
Option B
a straight line
1 model, on a leash
you pick queries
MODEL
you check & benchmark
you email

One smart step, slotted into your line. This is what "AI-powered" usually means.

still YOU
Option C
a loop, not a line
the agent drives
goal + tools
MODEL
pick a tool
↻ loops on its own
email

You set the goal; the agent picks the steps. Control flow lives inside the agent.

the AGENT
you decide every stepthe model decides
A B C

The three options side by side: Option A is a straight line with no model, where you own every step. Option B is a straight line with one model dropped into it, where you still own the flow. Option C is a loop where the agent owns the choice of what happens next. On a control spectrum running from you deciding every step to the model deciding, A and B sit close to you, and C sits at the far end.

Watch the jump. A → B feels like progress, but the shape never changes; it's still a line you drew, with one box made smarter. B → C changes the shape itself: the line becomes a loop, and the decision of "what next?" moves out of your code and into the model. That jump, not the cleverness of the model, is where agentic begins.

And it doesn't take a swarm. One model running one loop has already crossed the line; multiple agents handing work back and forth is just that same idea scaled up, not what makes something agentic in the first place.

Recap