Describe the problem/error/question
Hi everyone,
I’ve built an agentic customer service workflow in n8n that processes incoming customer messages from multiple platforms.
Setup
-
Each item represents one customer conversation (with many attributes like conversation_id, message text, metadata, etc.)
-
Some messages require a response, others don’t
Problem 1: Lineage break due to filtering
I filter out messages that don’t need a response early in the flow.
This causes:
-
Item count to change (N → M)
-
Loss of item lineage / mapping
-
Downstream nodes can no longer reliably reference the original item
Problem 2: Agent node destroys original data
The filtered items then pass through multiple Agent nodes:
However:
-
The Agent node output only contains { output: "..." }
-
All original fields (e.g. conversation_id, metadata) are lost
What I need
I want to enrich the original input item with:
-
intent
-
context
-
decisions
-
etc.
Current workaround (problematic)
I tried:
Problems:
-
LLM sometimes slightly alters the ID → merge fails
-
requires multiple Merge nodes → fragile
-
breaks easily with branching / async execution
-
not production-safe
Core challenge
After:
I no longer have a reliable way to map LLM output back to the original item
Question
What is the best practice in n8n to:
-
Preserve item identity through Agent nodes?
-
Enrich original items with LLM output reliably?
-
Handle cases where some items are filtered out (i.e. lineage is broken)?
Constraints
-
Agent node does not pass through input data
-
LLM output cannot be trusted for IDs
-
Workflow includes branching, MCP calls, multiple LLM steps
What I’m considering
-
Avoid filtering (tag instead?)
-
Wrapping original data before Agent nodes
-
Avoiding Merge completely
But I’d love to understand what the recommended pattern is for this kind of pipeline.
Goal
A production-safe pattern where:
Thanks a lot — this feels like a fundamental pattern issue with n8n + LLM workflows, so any guidance would be hugely appreciated 
What is the error message (if any)?
None, subsequent merges faisl silently if the llm does not pass the unique ID correctly.
Please share your workflow
(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
Share the output returned by the last node
No output, fails silently.
Information on your n8n setup
- n8n version: 2.15.0
- Database (default: SQLite): SQLite
- n8n EXECUTIONS_PROCESS setting (default: own, main): own
- Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
- Operating system: Linux
Hi @luxmediq you should be able to solve pretty much all the context leak and output matching problems just by upgrading your SYSTEM prompt and the AI model being used, but for the output structure consider using an Output Parser so that the AI agent knows exactly how to output and also in the output parser sample JSON give it kind of real world explanations of their own fields this works all the time, and if you have some kind of vector database where you store all the enrichment guidelines so consider using that instead of an MCP, also for the data you provide to the AI agent try to clearly classify it instead of actually dumping it down, basically curate your AI prompt and System prompt very precisely so that the AI agent knows what to follow, and things should be working fine after that.
Hey Benjamin, thank you for your response and great perspective! The core issue remains the “enrichment”, so bringing the tranformed information back to the originial input. The ref_id or any other value the LLM should return because subsequent logic (merge, lookup, etc..) builds upon it is not reliable enough for production use. Trigger for this thread is exactly this error happening, where the LLM has a “typo” in the ID and thus siltently fails the merge with the original message.
Looping (Split Items) would solve the “mapping issue” since there is only one item in the loop at a given time, but combined with a human in the loop step generate new challenges 
Hi Anschul, the prompt is super tight, output format is reliable, even defining the exact value to output, but the LLM still generates “typos” from time to time which is inacceptable in production automation.
@luxmediq can you show us the part i mean the flow where it causes errors, also the problem can be related to the AI model you are using so make sure you are using a capable model which could work with all that context.
I hope this visualizes the problem. The red circled node on the left is a Set Node that defines all field I need (incl. ID of the conversation with the customer). On the right the enhancement of the information from the set node with the additional fields from the Agent nodes via merge on Conversation ID.. The lineage is broken prior to the set node through a filter..
This is a really common pain point when building agentic workflows in production. I hit the same issue building a multi-platform customer service chatbot.
The pattern I use: “Context Envelope” via Set node before each Agent
Before each Agent node, use a Set node to wrap/preserve the original fields:
// Set node - add these fields:
original_conversation_id: {{ $json.conversation_id }}
original_metadata: {{ $json.metadata }}
original_platform: {{ $json.platform }}
// ... any fields you need downstream
Then after the Agent node output, use another Set node to merge:
conversation_id: {{ $('Set - Preserve Context').item.json.original_conversation_id }}
llm_output: {{ $json.output }}
metadata: {{ $('Set - Preserve Context').item.json.original_metadata }}
This works because $('NodeName').item still references the paired input item even through Agent nodes - as long as you’re processing one item at a time (which is usually the case with Loop Over Items).
For filtering (Problem 1): Instead of filtering items out, use an IF node but keep both branches alive. On the “no response needed” branch, just use a No-op (Set node that passes through), then merge both branches at the end. This preserves lineage without dropping items.
Key rule I follow: Never rely on the LLM to return IDs. Always store context before the Agent in a referenced node, then retrieve via $('nodeName').item.json.
“Nunca confie no LLM para devolver IDs” é o instinto correto — vale a pena tratar como uma regra arquitetural, não como um problema de prompt. Nenhuma quantidade de ajuste de prompt consegue que um gerador de tokens chegue a 100% na cópia literal de IDs, e em produção 99,9% ainda é uma falha de merge silenciosa a cada mil itens.
O padrão que corrige isso de forma definitiva: IDs circulam ao redor do modelo, nunca através dele. A abordagem context-envelope de @nguyenthieutoan é exatamente isso e funciona bem em n8n puro. A versão geral: encapsule cada item como {passthrough: {...ids, ...metadata}, payload: {...fields for the LLM}}, envie apenas payload para o agente, recoloque passthrough mecanicamente depois. A chave de merge nunca toca no modelo, então não pode ter um erro de digitação.
Pequena divulgação: eu enfrentei essa falha exata com frequência suficiente para construir isso em um produto (Entity Enricher — eu sou o fundador). Lá, campos marcados como preserve são restaurados aos seus valores de entrada originais após enriquecimento — o modelo pode escrever o que quiser, depois a verdade fundamental é reaplica mecanicamente, e os resultados retornam com suas chaves de entrada verbatim para que o merge de volta ao seu sistema seja um simples join. O mesmo princípio do envelope Set-node, apenas aplicado pelo pipeline em vez de por disciplina.
Para seu problema de filtragem/linhagem: tag em vez de filter (IF com ambos os ramos ativos) é o padrão mais limpo, como você suspeitava — a linhagem sobrevive, e o ramo “sem resposta necessária” apenas não faz nada.