Book a free call
← All articles
ain8nautomationAI agents

The Script Didn't Hate AI. It Hated the @ Character.

Correcting our own number: 3,977 nodes across 759 files, erased by a package-name rule rather than an AI filter, and where the original types still exist.

Adrian Hunia

Adrian Hunia Owner, leads the technical side

Builds the systems described here and runs deployments from the first call to go-live at the client.

11 min read

Two columns of n8n package names: unscoped n8n-nodes names intact on the left, scoped names beginning with the @ character struck out on the right

Every node type this dataset lost begins with the same character: @. Every node type that survived begins with n8n-nodes-. There is no third group, no overlap and no exception anywhere in the commit. What removed n8n's AI nodes was not a filter that recognised AI. It was a rule that could not read a scoped npm package name.

This piece does three things. It corrects a number we published ourselves, it shows the actual rule, and it says where the original node types still exist and under what conditions you can use them.

The number we got wrong

Start with the correction, because the rest of the article is built on it.

In our previous piece we wrote that 92.6% of AI nodes in this corpus had been erased: 1,457 out of 1,573. The arithmetic was correct and the finding underneath it was correct. The denominator was too narrow to carry the sentence we hung on it.

1,573 was the number of nodes whose name reads as AI-related: anything a human had called "AI Agent", "OpenAI Chat Model", "Embeddings" and so on. That was the only signal we had at the time, because in the snapshot our analysis was pinned to, the type fields were already gone. So the honest reading of that figure is narrow: of the nodes we could still identify by name, 92.6% had lost their type. It does not answer the question a reader will reasonably assume it answers, which is how many nodes were erased in total. A percentage whose denominator is a naming heuristic means less than it looks like, and this series only works if every number in it has a denominator you can argue with.

The right measurement does not need names at all.

Measuring it node by node

We took the workflows/ tree at two commits with git archive: baf2dfff (the parent) and 3c0a92c4 (the commit that changed them). 2,057 files on each side, 2,057 present in both. For every node in every file we matched the node across the two trees by its id field, then compared the type field of the same node before and after. No name matching, no heuristic, no sampling. Every node in the corpus, on both sides of one commit.

3,977 nodes whose type began with @ were changed to n8n-nodes-base.noOp, across 759 of the 2,057 files (36.9%, denominator: workflow files present in both trees). Two more nodes were changed from a CUSTOM. prefix, CUSTOM.klicktipp and CUSTOM.klicktippTrigger. 3,979 nodes in total.

By npm scope, the nodes replaced were:

npm scopeNodes replaced
@n8n3,951
@custom-js15
@horka.tv4
@calcslive3
@searchapi2
@muench-dev1
@watzon1

And these are the twelve LangChain node types that lost the most nodes:

LangChain node typeNodes replaced
lmChatOpenAi632
agent461
openAi295
chainLlm256
memoryBufferWindow217
lmChatGoogleGemini194
chatTrigger181
toolWorkflow180
outputParserStructured177
toolHttpRequest142
embeddingsOpenAi130
documentDefaultDataLoader101

That is 461 agent nodes, 632 chat model nodes and 217 memory nodes that stopped being agents, chat models and memory in a single commit, while keeping the names their authors gave them.

What survived, and why that is the whole finding

Then we ran the comparison the other way round. Not what changed, but what did not.

Type prefixNodes surviving the commit
n8n-nodes-base35,492
n8n-nodes-mcp27
n8n-nodes-klicktipp26
n8n-nodes-hdw11
n8n-nodes-brightdata3
n8n-nodes-document-generator3
n8n-nodes-dataforseo3
n8n-nodes-evolution-api3
n8n-nodes-youtube-transcription-dmr2
n8n-nodes-nostrobots2

The list of prefixes that were replaced has exactly two entries: @ followed by anything, and CUSTOM..

Not one node type beginning with @ survived the commit. Not one node type beginning with n8n-nodes- was replaced. No prefix appears in both lists. Given nothing but a node's type string, you can predict whether this commit kept it or replaced it, without knowing what the node did, what it was named, or which file it sat in. That is the difference between a rule and a mess, and this is a rule.

Left column: node types beginning with n8n-nodes- pass through the commit unchanged. Right column: node types beginning with @ all become n8n-nodes-base.noOp

What the rule was actually doing

npm has two ways of naming a package. An unscoped name looks like n8n-nodes-mcp. A scoped name looks like @n8n/n8n-nodes-langchain, where the part before the slash is an organisation namespace and the leading @ is mandatory syntax, not decoration. An n8n node type is written as the package name, a dot, and the node's own name, so a scoped node type carries that @ at the front of the string.

A validator written as "accept a package name matching n8n-nodes-*, otherwise substitute a placeholder" produces exactly the two tables above. It is not looking at what a node does. It is looking at the first character.

Here is the part worth sitting with. n8n ships all of its own official AI nodes inside one scoped package, @n8n/n8n-nodes-langchain. Community nodes written by individual authors are usually published unscoped, as n8n-nodes-<something>. So the rule deleted every official n8n AI node in the corpus and left every community node in place: n8n-nodes-mcp, n8n-nodes-klicktipp, n8n-nodes-hdw and the rest, written by people with no connection to n8n the company. The packages that followed npm's convention for organisation-owned code were the packages that got erased. The ones that did not follow it came through untouched.

@n8n accounts for 3,951 of the 3,977 replaced nodes whose type began with @, which is 99.3% (denominator: nodes with an @-prefixed type replaced in this commit). That is the entire reason the damage looks like an attack on AI. It is not a fact about AI. It is a fact about where n8n keeps its AI nodes.

We did not arrive at this reading on our own. After the previous piece went up, a commenter on r/n8n, user LennyFromCurly, suggested the cause was a package resolver rather than anything AI-specific. We went back to the trees to check it, and the prefix tables above are that check. The hypothesis is theirs and it holds.

Where the four copies stand today

We ran a type census on the current head of four repositories carrying this corpus.

RepositoryNodes typed noOpNodes with a LangChain type
Zie619/n8n-workflows4,3831
JustInCache/n8n-workflows4,3820
44510/n8n-workflow3933,959
Danitilahun/n8n-workflows3933,944

One methodological note before anyone reuses that first column. 393 noOp nodes also appear in copies that predate the defect. n8n's noOp node is a real node that people put in workflows on purpose, as a join point, a stub, or a labelled branch that intentionally does nothing. Counting noOp nodes is therefore not a corruption test: on this corpus, 393 of them are somebody's design choice and not damage. That is the trap in the obvious check, and it is why we measured the difference across one commit instead of counting placeholders in a snapshot.

Getting the original types back

44510/n8n-workflow still carries the original node types. Its HEAD, 578cbef8, is a git object that exists inside Zie619's own history, which makes it a fork taken before the defect rather than an independent scrape of the same workflows. That is a stronger provenance claim than a commit date, because a date is metadata anyone can write and a shared object is not.

Everything below is a condition on that sentence, not a footnote to it.

  • We are not calling that repository clean, and we are not calling it working. The claim we can defend is narrower: it is not affected by the two defects described in this series. We have not audited it for anything else.
  • It has no license detected at HEAD. With no license, full copyright applies by default. Read it, diff against it, use it to recover the original type of a node you already have. It is not a redistribution source and we are not pointing you at it as one.
  • It carries a problem of its own: 48 connection references that resolve to nothing, entirely separate from the 27,525 we reported from commit 5ffee225 in the first piece in this series. This looks like an earlier and unrelated defect. We have not traced its cause and we are not proposing one.
  • The date of the last commit predicts nothing here. What predicts whether a copy is affected is the provenance of its git tree, or a SHA you can check against a known one. If you are picking a copy to work from, that is the question to ask about it.
  • Four repositories is not a survey. Zie619/n8n-workflows has roughly 7,600 forks. We looked at four repositories in total, so we have no picture of the rest and we are not extrapolating to them.

If you only need one node back, you do not need any of this: the type string is short, and once you know a node named "AI Agent" was @n8n/n8n-nodes-langchain.agent, you can retype it by hand. The reason to go to a pre-defect tree at all is when you want the parameters too, and those went with the type.

We are not the first to notice

Worth being precise about who found what, because this series is partly an argument about sourcing.

We are not the first people to notice that something is wrong with this corpus. Issue #123 in the repository, opened on 9 October 2025, reports workflows arriving with empty connections. A comment on that thread dated 5 November 2025 states that the problem is still present after the fix that was meant to close it, which matches what we found in the file history: commit 5ffee225, dated 3 November 2025, is the commit that announced the fix and left the references pointing at nodes that were no longer there. Issue #125, opened on 20 October 2025, reports workflows that do not run after import.

So users have been reporting the symptoms for close to a year. What was missing was never the observation. It was a denominator, and a mechanism. Nobody had counted how many nodes were affected and nobody had named the rule that did it. That is the part we are adding, and it is a smaller contribution than "we discovered this", which is a sentence we are deliberately not writing.

What we are not claiming

  • Intent, by anyone. We can state which node types changed, in which commit, in which direction. We cannot state why the rule existed, whether it was meant to run over this data, or whether anyone read the diff. That applies to the humans and to the tooling equally.
  • That the rule knew what AI was. The evidence says the opposite: it keyed on the first character of a package name and hit LangChain because that is where n8n's AI nodes live.
  • A picture of the fork network. Four repositories out of roughly 7,600 forks is four repositories.
  • That any copy is clean. We tested for two specific defects and reported what those tests returned.
  • A cause for the 48 dangling references in 44510/n8n-workflow. We found them, we did not trace them.

Reproduce this yourself

The tree comparison, the prefix census and the four-repository type count are in the same open-source pipeline as the previous two pieces: github.com/adix65/n8n-reliability.

python3 -m n8n_reliability.cli fetch-corpus --dest data/corpus/n8n-workflows
python3 -m n8n_reliability.cli analyze --corpus-dir data/corpus/n8n-workflows --out-dir out

Every number in this article has a numerator, a denominator and a plain-language definition of that denominator, including the one we came back to correct. If a percentage here cannot be traced to those three things, treat it as a bug in the article rather than a fact about n8n. That standard is the reason the 92.6% had to be revisited in public rather than quietly edited, and we would rather publish the correction than keep a number that reads better than it measures.

If you run n8n in your company and want to know which of your own flows go quiet when they fail, get in touch. We will go through them on your data, on a free call.

SEVENEDGE builds and runs self-hosted n8n automation for production clients, alongside custom business software. This piece is static analysis of publicly shared workflow files and publicly available commit history, not a claim about any specific client system, and not an evaluation of any specific coding agent's general reliability.

Frequently asked questions

What actually erased the AI nodes in n8n's most-cited workflow dataset?

A rule keyed on the syntax of the node's type string. Every node whose type began with the @ character, which is how npm writes a scoped package name, became n8n-nodes-base.noOp: 3,977 nodes across 759 files in one commit, plus two more with a CUSTOM. prefix. Nothing whose type began with n8n-nodes- was touched.

Why does this article correct the 92.6% figure from the previous one?

Because that percentage used a narrow denominator. 1,457 of 1,573 was counted over nodes whose NAME looked AI-related, which was the only signal available at the time. The arithmetic was right, the denominator was not the population a reader would assume. Comparing every node by its id field between the parent commit and the commit itself gives 3,977 nodes in 759 files.

Why did n8n's official AI nodes get erased while community nodes survived?

Because n8n publishes its official AI nodes inside one scoped npm package, @n8n/n8n-nodes-langchain, and scoped names start with @. Community packages such as n8n-nodes-mcp or n8n-nodes-klicktipp are published unscoped and match the n8n-nodes- pattern. The rule removed the packages that follow npm's convention for organisation-owned code and kept the ones that do not.

Can the original node types be recovered?

Partly. The fork 44510/n8n-workflow still carries the original types, and its HEAD is a git object that exists inside Zie619's own history, which makes it a pre-defect fork rather than a separate scrape. It has no license detected at HEAD, so full copyright applies by default and it is not a redistribution source. It also carries 48 unresolvable connection references of its own.

How do I tell whether a copy of this corpus is affected?

Not by the date of the last commit, which predicts nothing here. Check the provenance of the git tree, or count node types beginning with @: a copy with none at all has been through the rule. Do not use the count of noOp nodes as the test, because 393 of them appear in copies that predate the defect and are the workflow authors' own design choice.

Want a real number for your project?

Book a free call. You'll leave with a fixed scope, a fixed price, and a timeline.

Book a free call
7SVENUsually replies right away
Hi! I'm SVEN from SEVENEDGE. We build apps, SaaS and AI automations. How can I help?
SVEN, the SEVENEDGE mascot, looking through a requestSVEN, the SEVENEDGE mascot, thinking over a coffeeSVEN, the SEVENEDGE mascot, working at a laptop
Got an app idea?