Nobody says RAG anymore. Everything is agentic now. Strip the loop off most of it, though, and you find the same model fetching the same documents with a better word on the slide. The loop is only worth its cost when it actually decides something: what to fetch, whether the pull was enough, whether the question can be answered at all. When it decides nothing, you have paid several times the tokens for branding.

Our matcher earns the loop. Type a vague request into it and it does not guess, it asks you for the role; give it a real one, a React Native engineer who has shipped a payments flow, and it comes back with a short list where every name carries the line from a real history that earned it. The hybrid search this series opened with, the dense and sparse retrieval, is one step inside that. The rest is the agent deciding what you asked, whether it can answer, and whether to go looking at all.

From a pipeline to a control loop

Classic RAG is a straight line. Take the question, retrieve once, put the context in the prompt, generate. It is simple and it works, right until the question needs more than one lookup, a comparison across sources, or a follow-up that depends on what just came back. Then the line breaks, because a line has no way to go back and try again.

Agentic RAG bends that line into a loop. An agent sits in the middle and makes the decisions a pipeline cannot: is this even a retrieval question, what should I fetch, was that enough, do I refine and go again. Retrieval stops being a step you run once before generating and becomes a tool the agent reaches for when it decides it needs one.

The graph is the agent

This is the actual graph behind our matcher, drawn from the code, and you can run the whole thing yourself at cv-matcher.2muchcoffee.com.

The real cv-matcher agent graph: classify intent routes to match profiles, follow up, or reject, then finalize the response.
The hybrid search from the flagship is the single match_profiles node. Everything around it, the routing and the refusal and the state, is the agent.

Read it once and the whole idea is there. A request comes in and classify_intent decides what kind it is. A real search routes to match_profiles, which is the hybrid retrieval from the flagship, one box on the page. A question about an existing shortlist routes to follow_up. Anything that is not a search at all routes to reject_intent. Whatever path it takes, finalize_response streams the answer back. There is a guard so a bad state skips the work, and the run keeps durable state in Postgres so a long job survives a restart.

The point of the picture is the proportion. The retrieval everyone argues about is a single node. Everything around it is the agent.

The patterns you will actually use

A handful of patterns cover most agentic RAG, and you will not need all of them. Routing, where the agent picks the path, which is our classify_intent. Re-retrieval, where a weak first pull triggers a second with refined parameters. Query rewriting, where a messy request gets cleaned into something worth searching. Self-critique, where the agent checks its own answer against what it retrieved before returning it; the productionized version of this is corrective RAG, where a lightweight evaluator grades the retrieved chunks first and triggers a rewrite or a fallback search when they come back weak, so the generator never runs on bad context. Tool use, where retrieval is one source alongside a database or a metadata lookup. Our matcher uses routing and a refusal branch and stops there, because that is what its job needs. LangGraph holds the graph together and the state lives in Postgres; the framework is not the interesting part, the decisions are.

The branch that refuses is the point

The branch that turns away an off-topic message, or asks for the role when the request is too thin, looks like a small thing on the diagram. It is the most important thing on it. A straight pipeline answers everything you send it, including the questions it has no business answering, which is exactly how a confident wrong answer ends up in front of a client. An agent can decline. It can say this is not a search, or I need more before I can help. The sturdy version of this is not a prompt that politely asks the model to say I don't know; it is selective prediction, where the system weighs its confidence in the retrieved context and in its own trained knowledge, and refuses when neither clears the bar. Declining is most of what trust is actually made of, and a pipeline cannot do it.

It is not free, so do not make everything an agent

Here is the honest part. Agents cost more and they are slower. A loop that retrieves, critiques, and retrieves again can burn several times the tokens of a single pass and add seconds of latency, most of it in the model calls, with a long tail on the hard questions. Which is why you cap the loop in code: a few iterations at most, plus a hard token ceiling and a wall-clock timeout, because past the third or fourth pass you are usually buying cost, not quality. That price buys real quality on open-ended, multi-step, or high-stakes work, the kind where a wrong answer is expensive. It buys almost nothing on a single-fact lookup or an FAQ, where a plain pipeline is faster, cheaper, and just as right. Whether the loop actually helped is not a feeling, by the way; you measure it the same way you measure any RAG change, with a golden set and a number.

classic RAG vs agentic RAGpick by the question, not the hype
 Classic RAGAgentic RAG
ShapeA straight lineA control loop
RetrievalOnce, before generatingA tool the agent calls, sometimes again
Can it declineNo, it answers anywayYes, it can refuse or ask
Multi-hop, follow-upBreaksHandles it
Cost and latencyBaselineSeveral times the tokens, slower
Best forSingle-fact lookup, FAQOpen-ended, multi-step, high-stakes

The mature setup in 2026 is not turning everything into an agent. It is routing the simple questions to a pipeline and escalating only the ones that need the loop.

What 2muchcoffee covers

We build these, the retrieval and the agent around it, and the call we make most often with a client is which questions even need the loop. If you have an agent that confidently answers things it should decline, or a pipeline straining against questions it cannot handle in one pass, that is the line we help you draw. The plain path to start is the AI work we do.

One concrete action

Ask your own system one question: when a user asks something it cannot answer, what happens. If the answer is that it answers anyway, you do not have an agent, you have a pipeline with good manners. Add the one branch that lets it decline, the refusal path, before you add anything fancier. It is the first real step from pipeline to agent, and it is the one that protects you.

Oleg Logvin Tech Lead at 2muchcoffee Builds production RAG, AI pipelines, and the boring infrastructure that makes them trustworthy.