← Back to Blog

An Agent Is a Loop, Not a Personality: Three Shifts That Separate AI Teams That Ship

I trained several hundred enterprise engineers on AI this year. Some of their teams went on to ship agents into production. Others stalled somewhere between a promising demo and a system nobody trusted. The difference was almost never talent, budget or model choice. It was whether the team stopped treating agents like magic and started treating them like software.

What stalling looks like

The pattern is remarkably consistent. A team builds a demo in a week. It is genuinely impressive. Leadership gets excited, a pilot gets scoped, and then progress slows to a crawl. The agent works most of the time. Nobody can say exactly when it doesn't, or why. Every fix to one failure seems to cause another. Three months later the project is still "nearly there".

When I look closely at these teams, the root cause is rarely technical in the narrow sense. It's a mental model. They're debugging a personality — nudging the prompt, adding another instruction, trying a bigger model — when what they actually have is a piece of software with a control flow, inputs, failure modes and no tests.

Three shifts separate the teams that get out of that trap from the ones that don't.

1. An agent is a loop, not a personality

Strip away the framework and every agent is the same small thing: a loop that asks a model what to do next, runs whatever tool it chose, feeds the result back, and stops when some condition is met.

messages = [system_prompt, user_question]

for step in range(MAX_STEPS):
    reply = llm(messages, tools=TOOLS)

    if not reply.tool_calls:          # model is done
        return reply.content

    for call in reply.tool_calls:     # model wants to act
        result = run_tool(call.name, call.args)
        messages.append(tool_result(call.id, result))

raise AgentDidNotFinish(messages)     # never loop forever

That's it. Fifteen lines. Everything interesting about agent reliability lives in the details of that loop: what happens when a tool throws, what happens when the model calls a tool that doesn't exist, what happens when it calls the same tool with the same arguments five times in a row, how you decide it's done, and what you do when it isn't.

This is why every engineering programme I run spends a full day building this loop by hand before anyone touches LangGraph. Not because frameworks are bad — I ship on LangGraph for clients — but because an engineer who has never written the loop cannot debug the graph. When a LangGraph agent misbehaves, the cause is almost always in one of those loop details, now hidden behind an abstraction. If you've written it yourself, you know where to look. If you haven't, you tune the prompt and hope.

The tell is in the vocabulary. Teams that stall say the agent "got confused" or "decided to" do something. Teams that ship say it "exceeded the step budget", "received a malformed tool result" or "terminated early because the stop condition was too loose". One of these is a description of a mood. The other is a bug report.

2. RAG isn't a vector database

The most common architecture decision I see made too early is "we need a vector database". A team picks one, loads their documents in, wires up retrieval, and considers RAG done. Then the answers are mediocre, and the instinct is to blame the model.

The vector database is the least interesting part of a RAG system. What matters is retrieval quality: whether, for a given question, the right passage actually comes back in the top results. And when it doesn't, the cause is overwhelmingly a data problem, not a model problem.

The failures I see most often in real enterprise corpora:

  • Chunking that splits the answer in half. A table cut across two chunks, where neither half makes sense alone.
  • Scanned PDFs with no usable text layer, silently indexed as empty or garbage.
  • Stale documents outranking current ones, because the 2021 policy is longer and more keyword-dense than the 2024 revision.
  • Contradictory sources with nothing in the pipeline to tell them apart.
  • Missing metadata, so there's no way to filter by region, product or date even when the question plainly implies one.

None of these is fixed by a better model. A more capable model given the wrong passage produces a more fluent wrong answer.

The single most useful diagnostic habit I teach is to separate the two halves. When an answer is wrong, first ask: did the right chunk come back at all? If it didn't, stop looking at the prompt — you have a retrieval problem. If it did and the answer is still wrong, then you have a generation problem. Most teams never make this split, so they spend weeks tuning generation to compensate for broken retrieval.

3. Evals before scale

"It looks good" is not a measurement. It's a feeling formed from the handful of examples you happened to try, which are disproportionately the ones you expected to work.

Without evals, every change to an agent is a coin flip. You adjust a prompt to fix one failure, and you have no way of knowing whether you broke three others. You swap an embedding model and the answers feel better. You can't tell improvement from regression, so you can't improve deliberately — you can only drift.

The minimum viable version is smaller than people expect:

  • A golden set of twenty to fifty real questions with known good answers — drawn from actual user traffic, not invented at a desk.
  • A retrieval score — did the right source come back in the top k? Hit rate and recall@k are enough to start.
  • A generation check — assertions where possible, a model-as-judge where not, and a healthy suspicion of the judge.
  • Run it on every change, ideally in CI, so a regression fails a build instead of reaching a user.

That last point matters beyond engineering. A team that can say "our retrieval hit rate went from 0.61 to 0.84 this sprint" gets budget. A team that says "it's working much better now" gets asked to demo it again. Evals are how AI work becomes reviewable, and reviewable work is fundable work.

One caution on model-as-judge. It's useful and it lies in consistent ways — favouring longer answers, agreeing with confident phrasing, and scoring fluent nonsense generously. Calibrate it against a small set of human-graded examples before you let it gate anything.

What the three have in common

Read them again and they're the same move three times. Replace a mood with a mechanism. Replace an intuition with a measurement.

  • "The agent got confused" becomes which step of the loop failed, and why.
  • "The model gives bad answers" becomes did the right passage come back.
  • "It seems better now" becomes the number moved, or it didn't.

None of this is new. It's what we already do with every other kind of software. The only thing that changed is that language models are fluent enough to make us forget, for a while, that we're still writing programs.

The uncomfortable part

These shifts are unglamorous, and that's precisely why teams skip them. Nobody demos a golden set. A hand-written agent loop looks less impressive than a framework diagram. Fixing chunking boundaries in a document pipeline doesn't make it onto a slide.

Which produces an odd inversion: the teams that stall are often doing the more impressive-looking work. They have the multi-agent architecture diagram, the latest model, the elaborate prompt. The teams that ship have a boring loop, a measured retrieval score and a regression suite — and a system people actually use.

This is the mental shift I build every RAG and agentic AI training around, and the same discipline behind the agents I build for clients. If your team is somewhere between an impressive demo and a system you'd trust, the gap is usually smaller than it feels — and it's almost never the model.

Arjun Thakur
Arjun Thakur — Principal AI Engineer & Fractional CTO. I build production agentic AI (LangGraph, RAG, voice) and help teams do the same through consulting and training. Work with me →