Mastering n8n sub-workflows can make you dangerously good at AI
The agent
Writes one string: "everything about animals"
Inside the sub-workflow
- List 15 chaptersIDs and summaries only
- Pick 1 to 3Small model, structured output
- Fetch thoseBy record ID
- Strip the restTitle and content, nothing else
What comes back
Two chapters, cleaned. The large model never saw the other thirteen.
A sub-workflow in n8n is a workflow whose trigger is When executed by another workflow. You define what comes in, you build the steps, and the output of the last node is what the caller gets back.
It’s a function, or a microservice if you prefer that word. You can build everything without ever using one, which is why a lot of people never do.
I want to make a bigger claim than the title of the video suggests. Getting good at these is not an n8n skill. It’s where you learn, on a canvas where every step is visible, the four things that decide whether anything you build with AI is affordable: cut a repeated job into steps, give each step only the context it needs, pick a model per step, and stop handing decisions to an agent once you already know the order. n8n is not the subject. It’s the place those four are easiest to see.
Two things sub-workflows are good for. The first is the obvious one and saves you maintenance. The second is the one that taught me all of that.
The boring benefit: build it once
Sales ops example. One workflow handles demo requests. Another takes a CSV of event attendees. Both of them, at some point, need to enrich a lead: take an email, get the company and the industry from a data provider, have a model summarise what the company does, score the lead.
That’s five or six nodes. You can build them in the demo request workflow, then build them again in the CSV workflow, then again in the eight other places that end up needing the same thing.
Callers
- Demo request flow
- Event attendee CSV
- Eight other workflows
Enrich a lead
- In: an email
- Apollo for firmographics
- A model for the summary and the score
- Out: the fields the CRM needs
What they do next
- Create the CRM record
- Notify Slack
- Append to a sheet
The payoff shows up in six months, when the data provider changes or someone wants one more field on the output. You edit one workflow. Every caller has it.
The interesting benefit: a tool that returns only what matters
Here’s the setup. A biology course lives in Airtable: 15 chapters, each with a name, a summary, and the full content. An agent answers questions about it.
This agent is already better than the naive version. It has two tools rather than one big dump: search all chapters, which returns just IDs and summaries, and get a chapter’s content. The system prompt tells it to read the summaries first, pick one to three chapters, then fetch those.
That two-step design is already most of the win.
Words reaching the model, for one question about animals
So why change anything. Two reasons, and neither is about the word count.
The large model runs once per tool call
Look at an execution. GPT-5.1 is connected, it’s expensive and it’s good, and it was called three times: once deciding to search chapters, once deciding to fetch content, once writing the answer.
Every one of those calls carries the system message and the accumulated memory of the previous tool results. The input grows on each turn.
Two of those three calls did no reasoning worth an expensive model. They picked which chapters looked relevant from a list of summaries.
The tool returns fields you didn’t ask for
Airtable’s Get Record tool has no field filter. Ask for a chapter’s full content and you also get the chapter name, the created time and the summary, which you already had from the first call and are now carrying twice.
You can’t fix that on the tool. You can fix it one step later, if there is a step.
One sub-workflow, doing the whole retrieval
Delete both tools. Replace them with a single sub-workflow tool that goes from a topic to the full content of the right chapters.
Sub-workflow, tool for agent
- Chapter retrievalTrigger. Input: topics to look for, a string
- Search all chaptersAirtable. All 15, with their summaries
- Clean outputRecord ID and summary only, and rename id to record_id
- AggregateThe 15 summaries as one item
- Pick the chaptersAI node, not an agent. Small model, structured output: 1 to 3 record IDsChat ModelSmall modelgpt-4.1-mini
- Split OutOne item per chapter to fetch
- Get chapter contentAirtable, by record ID
- Clean and aggregateTitle and full content, nothing else
The selection step is the one worth dwelling on. Its system prompt is one sentence: the user message names a topic, find the one to three relevant chapters, and here is the full list of chapters with their summaries. Its structured output is a list of record IDs.
That’s a sorting job against a list of 15 summaries. GPT-4.1 Mini does it correctly and does it fast, and I never pay frontier prices for it.
- Before: decide to list chaptersLarge modelcall 1
- Before: decide which to fetchLarge model, memory includedcall 2
- Before: write the answerLarge modelcall 3
- After: call the one toolLarge model writes one topic stringcall 1
- After: the sub-workflow sortsSmall model, structured outputcheap
- After: write the answerLarge modelcall 2
Large model calls3 into 2
And because there’s a Set node between Airtable and the output, I return the chapter title and the full content. Nothing else travels.
The agent’s system prompt also gets shorter, which I didn’t expect to matter as much as it does. It’s now: answer from the biology course, always call this tool first, then answer only from what it gave you. One tool, no ordering rules, nothing to get wrong.
The same trick on a web search tool
Second example, same shape. An agent with a web search tool, in my case Linkup, though Perplexity or anything else behaves the same.
Wire the API in directly and you hit two problems. It takes one question per call, so a broad question has to be asked in pieces, one round trip each. And the response includes the full list of sources, which lands in the context whether you want it or not.
Sub-workflow, web search tool
- Web searchTrigger. Input: web queries, an array
- Split OutOne item per question
- Linkup APIRun in parallel. This API takes about 10 seconds each
- Clean outputKeep the query and the answer, drop the source list
- AggregateOne item back to the agent
Ask something like how SEO and generative engine optimisation fit together in 2026, and the agent breaks it into three searches by itself: trends and strategies, how to optimise for both, best practices by company size. One tool call, three parallel searches, one clean aggregated item back.
API as the toolOne question per call
- Three sub-questions means three tool calls
- They run one after another
- The whole source list enters the context
Sub-workflow as the toolAn array of questions
- Three sub-questions in one call
- Split out, then run in parallel
- Keep the query and the answer, drop the sources
It’s one skeleton, not three workflows
I built a third one of these for a RAG agent, on a vectorized course in Supabase. It looks different on the canvas and it’s the same thing again.
- TriggerAccepts an array, so one tool call covers several questions
- Split OutOne item per question
- Hit the sourceAirtable, an API, a vector store. In a loop or in parallel
- CleanKeep the fields the model needs, drop everything else
- FilterOnly when the source gives you something to rank on
- AggregateOne item, with the question and its results paired up
The filter is the step the other two don’t have, and it’s there because a vector store hands back a similarity score and Airtable doesn’t. When the source gives you a number, you can throw away the results that aren’t good enough. In that workflow the line is 0.4, and anything under it never reaches the agent.
Two things I learned building the third one that I’d now do in all of them.
Name the output fields. The aggregate at the end doesn’t produce an anonymous blob, it produces a field called Knowledge base retrieval, and inside it each entry pairs Query to the knowledge base with Chunks returned. The model reads those names. Handing it an array and hoping it works out which result answers which question is a cost you pay in the final answer.
Say when you found nothing. A filter that removes everything produces no items, and no items means the next node never runs and the agent gets silence. So there’s an IF after the filter, and its empty branch writes a sentence: nothing reached the relevance threshold for this query. In n8n that also means setting the filter to always output data, otherwise the branch you wrote for this case never fires.
That second one changes what the agent can do. Its system prompt ends with an instruction to say it doesn’t know rather than answer from general knowledge, and that instruction is only honest if the retrieval below it is honest about coming back empty.
None of this is really about n8n
All three do one thing: they put steps between the agent and the raw response, and in those steps they throw things away. Here is why I think that’s worth more than a workflow.
Cutting a repeated job into steps is the whole game. A job you run once can be sloppy. A job you run three hundred times pays for its sloppiness three hundred times, and an agent deciding the order on every one of those runs is paying a model to rediscover a drawing you could have made on paper. The moment you know the steps, writing them down is not a loss of flexibility, it’s the point.
Each step gets the context it needs and nothing else. That’s what every clean-up node in this article is doing. It’s also what I measured with Jev: putting a small classifier in front of an agent to decide which skills it preloads and to strip the fields it will never read out of every tool response came out 29% cheaper on average and 61% on the best task, with no drop in quality. Same idea, one level up. Context is not free and most of what arrives in it was never going to be read.
The right model for each step. A sorting job against fifteen summaries is not a frontier-model job. Once the steps are separate, that stops being an opinion and becomes a setting you can change per node.
Then orchestrate, rather than delegate. The steps have to hand each other something useful, which is why the output fields get names and why an empty result says so out loud. That’s orchestration, and it’s the part an agent does invisibly and badly.
It’s the same reasoning that made me stop reaching for MCP on anything I repeat: a script against the API can do the filtering, the mapping and the loop without a model in the middle, and MCP cannot, because the model is the middle.
Agents hide all four, which is exactly why it’s worth having built one by hand. When I’m in Claude Code and something feels slow or expensive, the thing I go looking for is the step that returned everything when I needed three fields. It’s nearly always there, and I only know to look because I once wired that step up myself and watched the token count.


