$npx -y skills add czlonkowski/n8n-skills --skill n8n-agentsDesign n8n AI agents the right way. Use when building or editing any @n8n/n8n-nodes-langchain.* AI node — an AI Agent, LLM chain, Text Classifier, or Information Extractor — and whenever the user mentions AI agents, LLM with tools, tool calling, $fromAI, system prompts, agent mem
| 1 | # n8n Agents |
| 2 | |
| 3 | The n8n AI Agent node (`@n8n/n8n-nodes-langchain.agent`) is a multi-turn LLM driver with sub-nodes for the model, memory, tools, and an optional output parser. This skill is the **deep** guide to designing agents and the LangChain family around them. For the high-level "where an agent fits in a workflow" picture, see **n8n-workflow-patterns** `ai_agent_workflow.md` — this skill goes one level down into *how to build it well*. |
| 4 | |
| 5 | For node-type formats: in workflow JSON the LangChain nodes use the long `@n8n/n8n-nodes-langchain.*` form (`.agent`, `.lmChatOpenAi`, `.memoryBufferWindow`, `.outputParserStructured`, `.toolWorkflow`, `.toolHttpRequest`, `.toolCode`). When you call `get_node` / `validate_node`, use the **short** form (`nodes-langchain.agent`). See **n8n-mcp-tools-expert** for the format rules. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## Pick the right node first |
| 10 | |
| 11 | Reaching for an Agent when the task is one-shot classification or extraction is the most common over-build. Decide before you wire anything: |
| 12 | |
| 13 | | You need to… | Use | Why | |
| 14 | |---|---|---| |
| 15 | | Call tools, reason over multiple turns, or hold memory | **AI Agent** (`.agent`) | The full loop: model + tools + memory + optional parser. Also a fine default when you'd rather standardize. | |
| 16 | | One-shot text in → text out, no tools | **Basic LLM Chain** (`.chainLlm`) | No agent loop, easier to debug. Still accepts an `outputParserStructured` sub-node. | |
| 17 | | Route a natural-language input to one of **N branches** | **Text Classifier** (`.textClassifier`) | ONE node, N output handles, downstream wires directly into each. Not Agent + Switch. | |
| 18 | | Pull structured fields out of free text | **Information Extractor** (`.informationExtractor`) | Purpose-built field extraction with a schema. | |
| 19 | | 3-way positive/neutral/negative split | **Sentiment Analysis** (`.sentimentAnalysis`) | Built-in branch outputs. | |
| 20 | | Condense a long document | **Summarization Chain** (`.chainSummarization`) | Map-reduce summarization built in. | |
| 21 | | Generate an image / audio / video | **The provider's native single-call node** (OpenAI, Gemini, ElevenLabs…) | NEVER wrap media generation in an Agent — see "Binary and the agent boundary". | |
| 22 | |
| 23 | **Text Classifier detail (the Agent + Switch anti-pattern):** every category needs both a **name AND a description**. The model routes against the *description*, not the name — a category with no description gets picked by coin-flip. Set `options.enableAutoFixing: true` for robustness on edge inputs. One node, N branches, done. Reaching for an Agent that "decides" then a Switch that "routes" is two nodes plus prompt boilerplate for what Text Classifier does natively. |
| 24 | |
| 25 | Chat-model nodes (`.lmChatOpenAi`, `.lmChatAnthropic`, `.lmChatOpenRouter`, …) are **sub-nodes** — they don't run standalone. They wire into a chain, agent, classifier, or extractor via the `ai_languageModel` connection. |
| 26 | |
| 27 | --- |
| 28 | |
| 29 | ## The sub-node pattern |
| 30 | |
| 31 | The Agent has a **main input** (the prompt / user message) and up to four **sub-node slots**, each wired by its own `ai_*` connection type: |
| 32 | |
| 33 | | Slot | Connection type | Required? | Node example | |
| 34 | |---|---|---|---| |
| 35 | | **model** | `ai_languageModel` | Yes | `.lmChatOpenAi`, `.lmChatAnthropic`, `.lmChatOpenRouter` | |
| 36 | | **memory** | `ai_memory` | Optional | `.memoryBufferWindow`, `.memoryPostgresChat` | |
| 37 | | **tools** | `ai_tool` | Optional (but the point of an agent) | `slackTool`, `.toolWorkflow`, `.toolHttpRequest`, `.toolCode` | |
| 38 | | **outputParser** | `ai_outputParser` | Optional | `.outputParserStructured` | |
| 39 | |
| 40 | A sub-node connects FROM itself TO the agent. In workflow JSON the connection lives on the **sub-node**, keyed by the `ai_*` type: |
| 41 | |
| 42 | ```json |
| 43 | "Main LLM": { |
| 44 | "ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]] |
| 45 | }, |
| 46 | "Simple Memory": { |
| 47 | "ai_memory": [[{ "node": "AI Agent", "type": "ai_memory", "index": 0 }]] |
| 48 | }, |
| 49 | "Search customer DB": { |
| 50 | "ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]] |
| 51 | } |
| 52 | ``` |
| 53 | |
| 54 | Multiple tools all connect into the same `ai_tool` index 0 — they stack, they don't fan into separate indices. With `n8n_update_partial_workflow` you wire each with an `addConnection` op using `sourceOutput: "ai_tool"`. The agent puts its final answer in **`$json.output`** (not `.text`, not `.response`) — downstream nodes read `{{ $json.output }}`. |
| 55 | |
| 56 | See **EXAMPLES.md** for a complete stateless agent-co |