Most AI agents shouldn't be agents
One agent
Large model
Every turn. Full system prompt, every tool description, whether or not it calls one.
Three steps
When agents landed in n8n I built a lot of them. You drop an agent node, you hang three tools off it, and it figures out which one to call. It felt like the whole thing had just become easy.
Over the following months I took most of them back out. In the workflows that had to scale and actually run in production, I’m down to about a fifth of the agents I had.
Not because agents are bad. Because for most of what I was doing, the agent was deciding things at runtime that I already knew at build time, and charging me for the privilege on every single turn.
The canvas I’m picking on
A support chatbot. Chat trigger, an agent on a large model, and one tool: an HTTP request to a retrieval endpoint that answers questions from my documents. Someone asks about the product, the agent calls the tool, reads what comes back and writes the reply.
AI knowledge agent
- When chat message received
- AI Knowledge Agentgpt-4.1Chat ModelOpenAI Chat Modelgpt-4.1MemorySimple MemoryToolQuery knowledge baseHTTP request. The agent writes the query and decides when to call it
Someone says hi, and it costs you a frontier model
Send “hi” to that agent. You get a friendly reply in about 1.3 seconds, written by one of the largest models available.
No tool was called. Nothing was retrieved. The entire system prompt went in as input tokens, including every line describing tools that were never touched.
- The message arrives"hi"1 token
- The full system prompt goes inEvery tool description, every rule about when to call whatall of it
- The large model decidesIt decides not to call anything
- The large model answers"Hey, how can I assist you today?"
The greeting is the easy case to see, but it’s not a rare one. On a chatbot, a large share of messages need nothing retrieved and nothing looked up.
The same thing, written out
Here is the replacement. It’s more nodes, and every one of them is a decision I made once instead of a decision a model makes on every message.
Smart and efficient RAG chatbot
- When chat message received
- Find past messagesMemory manager, load modeMemorySimple Memory
- Intent routerText classifier, two categoriesChat ModelVery small modelgpt-4.1-nano
no knowledge retrieval needed
- Simple responseBasic LLM chain on the same tiny model
knowledge retrieval is needed
- Prepare retrieval queryBasic LLM chain, gpt-4.1-mini
- RAG via LookioPlain HTTP request. No model in this step at all
- Write the final responseBasic LLM chain, gpt-4.1. The only large model on the canvas
- Respond to Chat
- Store messagesMemory manager, insert mode
Route first, with a model that costs nothing
The Text Classifier’s only job is to decide which path the message takes. Two categories, each with a description:
- No knowledge retrieval needed. Greetings, confirmations, small talk. Anything answerable without consulting anything.
- Knowledge retrieval is needed. The message needs information from the documents before it can be answered.
Classification is a light task and a small model is very good at it. It’s fast enough that the step barely registers in the total latency, and cheap enough that I stopped thinking about it.
The cheap path is a basic LLM chain on that same tiny model with a short system prompt. “Hi” now comes back in about two seconds, reading exactly the same, on a model that costs a fraction per token of the one it replaced.
One model node feeds both the router and the simple reply. They’re different jobs but the same size of job, and having one place to change the model means I actually try a different one occasionally instead of editing two nodes and forgetting the second.
I use the same approach for the chat sidebar: generate conversation titles on a schedule with a small model instead of making a title call on every message.
Set the trigger to respond from a node
Small thing that blocks the whole design if you miss it. A chat trigger answers from the last node by default, and this workflow has two paths that both need to answer.
Set the trigger’s response mode to respond from a node, then put a Respond to Chat node where the branches meet. Without it there’s no way to have a cheap path and an expensive path that both reply, which is the entire point of routing.
The retrieval path, as three nodes
Watch what the agent did on a real question. The large model got called, spent 600ms, and decided to call the tool. Good decision. But the thing it produced with all that intelligence is one short query string, roughly a cleaned up version of what the user just typed. And to write it, the entire system prompt went in again.
Jobs in the turnAll on the large model
- Decide that retrieval is needed
- Write a short search query
- Write the final answer from what came back
What each one needsIf you pick per step
- A classifier, tiny model
- A rewrite, small model
- A large model, and here it earns it
So the path is three nodes rather than one agent.
Prepare retrieval query is a basic LLM chain on a mini model. Its system prompt: from the user message, formulate the short and concise query to send to the knowledge retrieval tool, and output it directly as a question. In my tests the small model wrote the same query the large one had.
RAG via Lookio is a plain HTTP request. The query goes in the body, the assistant ID and the mode are fixed values I chose rather than parameters a model can drift on. Most tools you attach to an agent are an API underneath, and the platform usually gives you the node ready to paste.
Write the final response gets the original message and the retrieved content, labelled, and writes the reply. This one stays on the large model, because the wording of the final answer is where the quality shows.
Memory is yours to carry now
This is the part the agent was doing for you, and the part you have to put back.
An agent node takes a memory sub-node and handles it. Split the agent into steps and nothing does, so the conversation gets loaded once at the top and stored once at the bottom.
- Find past messagesMemory manager in load mode, right after the triggeronce
- Every prompt appends itThe router, the simple reply and both retrieval steps each get the history×4
- Respond to ChatThe reply goes back to the user
- Store messagesMemory manager in insert mode: the user message and the answeronce
It’s more work. It’s also the moment you notice that an agent was pushing the whole conversation into every single turn, and that a query-rewriting step needs the last two messages rather than the last twenty.
What you get back
AgentDecides at runtime
- Large model on every turn, greeting or not
- System prompt and tool descriptions in every call
- It can skip a tool and answer from memory
- It can reorder things and you find out in production
Explicit stepsDecided at build time
- Large model on one node out of five
- No tool descriptions anywhere
- The retrieval always runs, because it is a step
- The order is the order you drew
The one that matters most to me is the third line. An agent skipping a tool and answering from what it happens to know is the failure you can’t reproduce and can’t test for. A workflow can’t do it. The node is there, it runs.
When I still reach for an agent
When I genuinely don’t know the order. Open-ended research, where the second query depends on what the first one found. Anything where the number of steps isn’t knowable in advance.
That’s the test I use now: can I draw this on paper before it runs? If I can, an agent is paying a model to rediscover my drawing on every request.
The same question, one level up
This is the habit that transfers. When I’m in Claude Code or Codex, a lot of what I do is the same shape as that support bot, and the expensive parts are the same parts: the whole context going in again for a step that needed a fraction of it, a model rediscovering something I already knew.
Knowing what a tool call costs, because you once wired one up by hand and watched the token count, is what lets you see it happening inside a harness that shows you almost nothing.
Go open your own agents and look at the executions. For each one, ask whether you could have drawn the steps yourself before it ran. Most of mine, I could.


