AI-skillGratis

n8n AI-agents

Gebaseerd op czlonkowski/n8n-skills @ 72470a0, licentie MIT

Bijgewerkt 30 augustus 2026

Dit bestand is door ToolBrain vertaald en inhoudelijk gewijzigd op 2026-08-30, op basis van n8n-agents SKILL.md uit czlonkowski/n8n-skills (MIT), zie de bron_url hierboven en ../LICENSES/n8n-skills-MIT.txt.

De n8n AI Agent-node (@n8n/n8n-nodes-langchain.agent) is een meerstaps-LLM-motor met sub-nodes voor model, memory, tools en een optionele output-parser. Dit is de diepgaande gids voor het goed ontwerpen van agents en de bijbehorende LangChain-familie. Voor het grotere plaatje van waar een agent past binnen een workflow: zie het item over n8n workflow-patronen (het AI-agent-patroon). Deze gids gaat een niveau dieper: hoe bouw je een agent die daadwerkelijk goed werkt.

Let op de nodenotatie: in workflow-JSON gebruiken de LangChain-nodes de lange vorm (@n8n/n8n-nodes-langchain.agent, .lmChatOpenAi, .memoryBufferWindow, .outputParserStructured, .toolWorkflow, .toolHttpRequest, .toolCode). Bij het opzoeken of valideren van een nodetype gebruik je juist de korte vorm (nodes-langchain.agent).

Kies eerst de juiste node

De Agent-node pakken voor een taak die eigenlijk one-shot classificatie of extractie is, is de meest voorkomende overbouw. Beslis vooraf:

Je hebt nodig…GebruikWaarom
Tools aanroepen, over meerdere beurten redeneren, of memoryAI Agent (.agent)De volledige lus: model + tools + memory + optionele parser.
One-shot tekst in → tekst uit, geen toolsBasic LLM Chain (.chainLlm)Geen agentlus, makkelijker te debuggen.
Vrije tekst routeren naar één van N takkenText Classifier (.textClassifier)Eén node, N outputs, downstream direct aangesloten op elke tak. Niet Agent + Switch.
Gestructureerde velden uit vrije tekst halenInformation Extractor (.informationExtractor)Speciaal gebouwd voor veldextractie met een schema.
3-weg positief/neutraal/negatief-splitSentiment Analysis (.sentimentAnalysis)Ingebouwde tak-outputs.
Lang document samenvattenSummarization Chain (.chainSummarization)Map-reduce-samenvatting ingebouwd.
Afbeelding/audio/video genererenDe native single-call-node van de provider (OpenAI, Gemini, ElevenLabs…)Wikkel mediageneratie NOOIT in een Agent — zie "Binaire data en de agent-grens" hieronder.

Text Classifier in detail (het Agent+Switch-antipatroon): elke categorie heeft zowel een naam ALS een beschrijving nodig. Het model routeert op basis van de beschrijving, niet de naam — een categorie zonder beschrijving wordt in feite met een muntje gekozen. Zet options.enableAutoFixing: true aan voor robuustheid bij randgevallen. Eén node, N takken, klaar. Een Agent laten "beslissen" gevolgd door een Switch die "routeert" is twee nodes plus prompt-overhead voor iets wat Text Classifier native doet.

Chatmodel-nodes (.lmChatOpenAi, .lmChatAnthropic, .lmChatOpenRouter, …) zijn sub-nodes — ze draaien niet zelfstandig. Ze worden bedraad in een chain, agent, classifier of extractor via de ai_languageModel-verbinding.

Het sub-node-patroon

De Agent heeft een hoofdinput (de prompt/het gebruikersbericht) en tot vier sub-node-slots, elk bedraad via zijn eigen ai_*-verbindingstype:

SlotVerbindingstypeVerplicht?Voorbeeldnode
modelai_languageModelJa.lmChatOpenAi, .lmChatAnthropic, .lmChatOpenRouter
memoryai_memoryOptioneel.memoryBufferWindow, .memoryPostgresChat
toolsai_toolOptioneel (maar wel het hele punt van een agent)slackTool, .toolWorkflow, .toolHttpRequest, .toolCode
outputParserai_outputParserOptioneel.outputParserStructured

Een sub-node verbindt VAN zichzelf NAAR de agent — in de workflow-JSON zit de verbinding op de sub-node, gesleuteld op het ai_*-type. Meerdere tools verbinden allemaal naar dezelfde ai_tool-index 0 — ze stapelen, ze splitsen niet naar aparte indices. Het eindantwoord van de agent komt in $json.output terecht (niet .text, niet .response) — downstream-nodes lezen {{ $json.output }}.

Twee niet-onderhandelbare regels

  1. Tool-namen en -beschrijvingen ZIJN onderdeel van de prompt. Het model kiest een tool uitsluitend op basis van naam en beschrijving. Een tool genaamd tool1 met een lege beschrijving is voor het model onzichtbaar: het slaat 'm over, kiest verkeerd, of verzint parameters. Er is meestal geen foutmelding — gewoon een agent die "mijn tool niet gebruikt". Behandel dit als API-ontwerp.
  2. Gestructureerde output moet parsen ÉN auto-fixen. Een outputParserStructured met autoFix: true en een code-vaardig fix-model is het productiepatroon. Zonder autoFix stopt één misvormde JSON-respons de hele workflow.

Sterke standaardkeuzes

  • Per-tool-gebruiksinstructies horen in de toolbeschrijving, niet in de systeemprompt. Alles over hoe je deze specifieke tool aanroept hoort bij de tool zelf, zodat het meereist naar andere agents en de systeemprompt gefocust blijft.
  • Sub-workflow-tools (.toolWorkflow) voor alles wat meerdere stappen kost. Elke workflow wordt een tool met getypeerde $fromAI()-inputs, en combineert met vertakking, foutafhandeling en hergebruik. Kies dit als standaard bij twijfel.
  • Wikkel tools met gebruikers-zichtbare effecten in menselijke review. Verzendacties, betalingen, terugbetalingen, accountwijzigingen — hang er een goedkeuringsnode voor zodat een mens akkoord geeft voordat de tool afvuurt.
  • Verhoog maxIterations. De standaard tool-call-limiet is laag — prima voor een agent met één tool, veel te laag voor een multi-tool-agent die meerdere calls per beurt aan elkaar rijgt. Dit uit zich als "max iterations reached" of lege output. Zet options.maxIterations op een realistisch plafond (15 voor een gefocuste sub-agent, 50-200 voor een brede orkestrator).
  • Zet de actuele datum in de systeemprompt via een dynamische datumexpressie. Een hardgecodeerde datum is meteen verouderd.

De vier toolsoorten

Kies de lichtste optie die de klus klaart:

ToolsoortNodeGebruik wanneer
Native tool-nodeslackTool, gmailTool, toolCalculator, …De capaciteit komt overeen met precies één bestaande node + operatie. Laagste overhead.
Sub-workflow als tool.toolWorkflowMeer dan één node, herbruikbare logica, of je wilt onafhankelijk kunnen testen. De kanonieke n8n-manier — standaardkeuze bij twijfel.
HTTP Request Tool.toolHttpRequestEén externe HTTP-API die de agent zelf moet orkestreren. Hergebruik de vooraf gedefinieerde credential van de dienst.
MCP Client Tool.mcpClientToolEen onderhouden MCP-server dekt het al, of je wilt één gepubliceerde workflow laten dienen voor meerdere agents.

Er is ook een Custom Code Tool (.toolCode) voor pure inline berekeningen — maar zijn runtime-contract (string in / string uit, geen $fromAI, geen $helpers) is een apart onderwerp. Vuistregel: grijp je in de code naar $fromAI(), dan wil je eigenlijk .toolWorkflow.

$fromAI(): hoe de agent tool-parameters invult

Toolparameters die de agent zelf moet bepalen worden gewikkeld in $fromAI() — een echte n8n-expressiehelper, gebruikt binnen de parameterexpressies van een tool-node:

Code
={{ $fromAI('paramName', 'wat hier moet komen — wees specifiek: formaat, bereik, voorbeeld', 'string') }}
  • paramName — de naam die het model intern gebruikt.
  • description — vertelt het model welke waarde te produceren. Dit is onderdeel van de prompt — schrijf het als JSDoc.
  • type (optioneel) — 'string' (default), 'number', 'boolean', 'json'. Een verkeerd type laat de aanroep falen.
  • defaultValue (optioneel) — gebruikt als het model het weglaat.

$fromAI() draagt alleen JSON — geen binaire data (geen base64, geen bestandsbytes). En niet elke parameter hoeft $fromAI te zijn: geef identiteit, bevoegdheidsgrenzen en correlatie-ID's (userId, terugbetalingsplafond, sessionId) deterministisch mee vanuit de workflowcontext, zodat de agent ze niet fout kan invullen of zelfs maar kan zien.

Systeemprompt versus toolbeschrijving

Hoort in de systeempromptHoort in de toolbeschrijving
Persona, rol, stemWat déze specifieke tool doet
Globale output-/formaatregels ("antwoord in markdown")Wanneer gebruik je deze tool versus andere
Weigerings-/veiligheidsgedragWat elke parameter betekent en welke vorm die heeft
Universele context (huidige datum, gebruikersrol)Tool-specifieke valkuilen (rate limits, edge cases)
Flow tussen tools ("na het genereren altijd tonen")Tool-specifieke inputtransformaties

Waarom deze splitsing: een goed beschreven tool werkt in elke agent die 'm erin zet, tooldetails "laden" alleen als het model die tool overweegt (tokenefficiëntie), en je update één toolbeschrijving in plaats van een alinea diep in een prompt van duizenden tokens.

Gestructureerde output: wanneer en hoe

Voeg een outputParserStructured-sub-node toe (bedraad via ai_outputParser) zodra downstream strikte JSON nodig heeft, geen vrije tekst. Twee regels: gebruik schemaType: 'manual' met een echt JSON Schema, geen voorbeeld — een voorbeeld kan verplicht-versus-optioneel, enums, numerieke bereiken of array-beperkingen niet uitdrukken. En zet autoFix: true met een apart, code-vaardig fix-model bedraad op de parser's eigen ai_languageModel-slot: kapotte JSON tegen een schema herstellen is een codeertaak, een zwak fix-model produceert alleen een nieuwe misvormde poging.

Memory: kort mentaal model

Memory is een sub-node (ai_memory). Zonder memory is elke aanroep stateloos — correct voor one-shot-taken. Met memory houdt de agent een gesprek vast, gesleuteld op een expressie die je aan sessionKey bindt.

  • memoryBufferWindow — houdt de laatste N uitwisselingen per sleutel vast, blijft bewaard over executies heen via de eigen opslag van n8n. De default voor chat. De vensterlengte staat standaard erg laag — 50 is een verstandiger startpunt. Berichten buiten het venster zijn helemaal weg.
  • memoryPostgresChat / memoryRedisChat — alleen wanneer memory ook buiten de agent gelezen moet worden (eigen UI, analytics, ander systeem). Niet nodig om enkel een herstart te overleven — BufferWindow doet dat al.

Geef consequent een stabiele sleutel mee van trigger naar memory. Chattriggers vullen sessionId automatisch; voor andere kanalen leid je er zelf een af (Slack thread_ts, een webhook-gesprek-ID). Hardcodeer nooit sessionId: 'default' en zet sessionId nooit achter $fromAI (het model verzint dan een willekeurige UUID).

Binaire data en de agent-grens

Dit is de naad waar het vaak misgaat:

  • Het model KAN geüploade afbeeldingen zien (vision) via een agent-instelling die binaire afbeeldingen doorlaat.
  • Tools KUNNEN GEEN binaire data ontvangen. $fromAI() is JSON-only — geen base64, geen bytes, ook niet via non-AI-koppelingen.
  • De output van de agent is tekstvormig (of gestructureerde tekst met een parser). Geeft een model image/audio/video-bytes terug, dan geeft de Agent die helemaal niet door — er is downstream niets te herstellen.

Omweg: upload eerst naar opslag voordat de agent draait, geef de opslagsleutels mee in de systeemprompt, en laat tools die sleutel als stringparameter accepteren en zelf intern opnieuw ophalen. Voor eenmalige mediageneratie sla je de agent gewoon over en roep je de native single-call-node van de provider direct aan.

Menselijke review (blokkeer destructieve tools)

Als het effect van een tool menselijke goedkeuring nodig heeft (verzendacties, betalingen, terugbetalingen, accountwijzigingen), wikkel de tool dan in een review-node die tussen de tool en de agent op de ai_tool-verbinding zit: gewikkelde tool → review-node → Agent.

Of goedkeuring nodig is, is een product-/beleidskeuze — leg de vraag voor aan de gebruiker, adviseer op basis van de impact, en laat hen beslissen.

De kritieke regel: toon de daadwerkelijke parameters die de gewikkelde tool zal ontvangen. Gebruik de letterlijke toolparameterwaarde in het goedkeuringsbericht, nooit een $fromAI()-parafrase — anders keurt de mens tekst goed die het model verzon, niet de aanroep die echt gaat plaatsvinden.

Chat-agents (Slack, Discord, Teams, Telegram)

De ene niet-onderhandelbare regel, ongeacht complexiteit: elke chat-getriggerde workflow die een antwoord post MOET het eigen gebruikers-ID van de bot uitfilteren, anders triggeren de eigen antwoorden zichzelf opnieuw in een oneindige lus die runs en tokens opsoupeert. Filter bij voorkeur op triggerniveau (een uitsluitingslijst op de trigger); filter anders in de eerste node na de trigger.

Voorbij dat filter kan een simpele bot (trigger → agent → antwoord) prima in één workflow. Splits pas op in shell + core + sub-agents zodra je laad-UX, sub-agents, hergebruik over meerdere kanalen, of robuuste foutafhandeling nodig hebt:

  • Shell — trigger, anti-loop-filter, event-type-Switch, laad-/foutUX, rendert het antwoord. Geen LLM.
  • Core — stateless agent, chatinput + threadId als input, memory gesleuteld op threadId, tools en sub-agents.
  • Sub-agents — elk één smal domein, aangeroepen via .toolWorkflow, stateless (volledige context zit in de chatinput).

Persistente n8n Agents

Een persistente n8n Agent is een ander artefact dan de AI Agent-node hierboven: een zelfstandig assistent-record (model, instructies, tools, skills, taken, memory, kanalen) opgeslagen en geversioneerd door n8n zelf, beheerd via de instantie-brede agentbeheertool — geen node binnen de JSON van één workflow.

Je hebt nodig…Gebruik
Een redeneerstap binnen een workflow, bedraad met ai_*-sub-nodesAI Agent-node (hierboven)
Een zelfstandige assistent met eigen levenscyclus — concept, valideren, publiceren, versies, kanalen — los van één workflowPersistente Agent

Vereisten: een apart toegangstoken geconfigureerd en n8n 2.34+ met de agentmodule ingeschakeld. Zonder dat token werkt niets, ook niet de alleen-lezen acties.

Bouwvolgorde: eerst het configuratieschema en de exacte muteeracties opvragen, dan de beschikbare koppelbare middelen (modellen, integraties, workflows, sub-agents, MCP-servers) opvragen, dan aanmaken, dan muteren (steeds de laatste configuratiehash meenemen), dan valideren, en pas op expliciet verzoek van de gebruiker publiceren — nooit uit eigen beweging.

Een live aanroep van de agent gebruikt echte credentials en echte tools — geen dry run. Een resultaat kan goedkeuringsverzoeken voor toolaanroepen bevatten; keur die nooit namens de gebruiker goed — leg ze voor en ga pas verder na een expliciete keuze.

Custom tools zijn een derde coderuntime — niet de Code-node (JavaScript/Python) en niet de Custom Code Tool van de AI-agent (string in/uit, geen $fromAI()). Lees eerst het schema voordat je er een schrijft.

Testen zonder rommel achter te laten: geef wegwerp-agents een herkenbaar testprefix in de naam en verwijder ze na afloop — een persistente Agent overleeft het gesprek dat 'm maakte, in tegenstelling tot een workflow die je gewoon inactief kunt laten staan.

RAG (retrieval augmented generation)

n8n biedt de LangChain RAG-bouwstenen (document loaders, splitters, embeddings, vector stores, retrievers). Twee vuistregels:

  1. Sluit goedkopere opzoekmethoden eerst uit. Exacte opzoekingen → een database- of tabelquery, geen RAG. Actualiteit → een live zoektool. Een klein/gestructureerd documentsetje → geef de agent list/fetch-tools. Grijp pas naar een vector store als er te veel documenten zijn om op te sommen en de vragen semantisch van aard zijn.
  2. Bedraad de vector store als een retrieval-tool (modus retrieve-as-tool, ai_tool) zodat de agent zelf beslist wanneer opvragen relevant is en de zoekvraag zelf kan formuleren. Embed query en documenten met hetzelfde model.

Antipatronen

AntipatroonWat er misgaatFix
Generieke toolnamen (tool1, doStuff, runQuery)Model kan niet zien welke tool te kiezen — slaat over of verzint parametersWerkwoord-eerst, specifieke namen: "Zoek klantendatabase", "Genereer afbeelding met Veo"
Lege of ééndelige toolbeschrijvingenModel heeft geen idee wanneer te gebruiken; slechte selectie, geen foutmeldingSchrijf een echte beschrijving: wat, wanneer, welke parameters
Per-tool-instructies in de systeemprompt proppenOpgeblazen prompt, geen hergebruik, richtlijnen verstoptVerplaats per-tool-richtlijnen naar de toolbeschrijving
Agent + Switch om op natuurlijke taal te routerenTwee nodes + promptoverhead waar Text Classifier één node isGebruik Text Classifier — elke categorie een eigen output (naam én beschrijving)
Afbeelding/audio/video-generatie in een Agent wikkelenBinaire data stroomt niet door tools of uit de agent-outputGebruik de native single-call-node van de provider direct
outputParserStructured zonder autoFixEén misvormde respons stopt de workflowautoFix: true + een code-vaardig fix-model
Binaire data direct naar een tool sturenWerkt niet — binaire data kan de toolgrens niet overstekenEerst opslaan, sleutels doorgeven
Hardgecodeerde/ontbrekende/$fromAI-gestuurde sessionIdGesprekken lopen door elkaar, of het model verzint een UUIDGeef een stabiele sleutel mee vanuit de trigger
Twee bijna-identieke toolsSelectie wordt onvoorspelbaar, model raakt in de warEén tool met interne vertakking op een parameter
Chatbot zonder bot-userfilterEigen antwoorden triggeren zichzelf opnieuw → oneindige lusSluit het bot-gebruikers-ID uit bij trigger of eerste node
maxIterations op de lage default bij een multi-tool-agent"Max iterations reached" / lege outputVerhoog options.maxIterations
Menselijke-review-bericht gevuld via $fromAI()Goedkeurder tekent een parafrase af, niet de echte aanroepGebruik de letterlijke toolparameterwaarde

Integratie met andere onderdelen

De workflow-patronen-skill geeft het grotere plaatje van waar een agent past in een workflow. De validatie-skill legt uit hoe je AI-connectieproblemen interpreteert (een tool bedraad op main in plaats van ai_tool toont als losgekoppeld). De foutafhandelingsskill behandelt onError: 'continueErrorOutput' op tool-sub-workflows en de agent-core-aanroep zelf. De expression-syntax-skill onderbouwt {{ }}, $json.output, en $fromAI.

Checklist vóór je een agent uitrolt

Juiste node gekozen (Agent voor tools/memory/multi-turn; Text Classifier voor routering; Information Extractor voor velden; native node voor media); model bedraad via ai_languageModel; elke tool heeft een werkwoord-eerst-specifieke naam ÉN een echte beschrijving; $fromAI()-beschrijvingen zijn specifiek; per-tool-richtlijnen staan in de toolbeschrijving; huidige datum in de systeemprompt; maxIterations verhoogd voor multi-tool- agents; memory gesleuteld op een stabiele sessiesleutel met verhoogde venstergrootte; gestructureerde output met schemaType: 'manual' + autoFix: true + fix-model; destructieve tools in menselijke review met letterlijke parameters; chatbots filteren het eigen bot-ID; binaire data via vision resp. opslagsleutels; gevalideerd en geverifieerd (sub-nodes op ai_*, niet op main).

Praktijkvoorbeeld (NL)

Een Nederlandse verzekeringstussenpersoon bouwt een AI Agent die inkomende klantvragen via WhatsApp beantwoordt over lopende polissen. De agent krijgt drie tools: een sub-workflow-tool die polisgegevens opzoekt op klantnummer, een HTTP Request-tool naar de schadeportal, en een menselijke-review-tool voor het daadwerkelijk indienen van een schadeclaim — want dat laatste mag de agent nooit zelfstandig afvuren. De sessiesleutel voor memory wordt afgeleid van het WhatsApp-threadnummer, niet hardgecodeerd, zodat gesprekken van verschillende klanten nooit door elkaar lopen. Bij de eerste testronde bleek maxIterations te laag ingesteld: bij een vraag die zowel een polisopzoek als een schade-check vereiste, liep de agent tegen de limiet aan voordat hij een antwoord kon geven, en is de waarde verhoogd naar 30.