n8n-agents
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesen8n Agents
n8n AI Agent
The n8n AI Agent node () 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 — this skill goes one level down into how to build it well.
@n8n/n8n-nodes-langchain.agentai_agent_workflow.mdFor node-type formats: in workflow JSON the LangChain nodes use the long form (, , , , , , ). When you call / , use the short form (). See n8n-mcp-tools-expert for the format rules.
@n8n/n8n-nodes-langchain.*.agent.lmChatOpenAi.memoryBufferWindow.outputParserStructured.toolWorkflow.toolHttpRequest.toolCodeget_nodevalidate_nodenodes-langchain.agentn8n AI Agent节点()是一个多轮LLM驱动节点,包含模型、记忆、工具以及可选的输出解析器等子节点。本指南是关于设计Agent及其周边LangChain生态的深度教程。如需了解“Agent在工作流中的定位”等宏观内容,请查看n8n-workflow-patterns的——本指南将深入讲解如何构建高质量的Agent。
@n8n/n8n-nodes-langchain.agentai_agent_workflow.md关于节点格式:在工作流JSON中,LangChain节点使用完整的格式(如、、、、、、)。调用 / 时,请使用简写格式()。格式规则请参考n8n-mcp-tools-expert。
@n8n/n8n-nodes-langchain.*.agent.lmChatOpenAi.memoryBufferWindow.outputParserStructured.toolWorkflow.toolHttpRequest.toolCodeget_nodevalidate_nodenodes-langchain.agentPick the right node first
先选择正确的节点
Reaching for an Agent when the task is one-shot classification or extraction is the most common over-build. Decide before you wire anything:
| You need to… | Use | Why |
|---|---|---|
| Call tools, reason over multiple turns, or hold memory | AI Agent ( | The full loop: model + tools + memory + optional parser. Also a fine default when you'd rather standardize. |
| One-shot text in → text out, no tools | Basic LLM Chain ( | No agent loop, easier to debug. Still accepts an |
| Route a natural-language input to one of N branches | Text Classifier ( | ONE node, N output handles, downstream wires directly into each. Not Agent + Switch. |
| Pull structured fields out of free text | Information Extractor ( | Purpose-built field extraction with a schema. |
| 3-way positive/neutral/negative split | Sentiment Analysis ( | Built-in branch outputs. |
| Condense a long document | Summarization Chain ( | Map-reduce summarization built in. |
| 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". |
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 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.
options.enableAutoFixing: trueChat-model nodes (, , , …) are sub-nodes — they don't run standalone. They wire into a chain, agent, classifier, or extractor via the connection.
.lmChatOpenAi.lmChatAnthropic.lmChatOpenRouterai_languageModel当任务是单次分类或提取时就使用Agent,是最常见的过度设计。在搭建任何节点前,请先明确需求:
| 你需要…… | 使用 | 原因 |
|---|---|---|
| 调用工具、多轮推理或保留对话记忆 | AI Agent( | 完整闭环:模型+工具+记忆+可选解析器。当你希望标准化实现时,也是不错的默认选择。 |
| 单次文本输入→文本输出,无需工具 | 基础LLM链( | 无Agent循环,更易调试。仍支持接入 |
| 将自然语言输入路由至N个分支之一 | 文本分类器( | 单个节点,N个输出端口,可直接连接下游节点。无需使用Agent+Switch组合。 |
| 从自由文本中提取结构化字段 | 信息提取器( | 专为字段提取设计,支持自定义Schema。 |
| 三元情感划分(正面/中性/负面) | 情感分析( | 内置分支输出。 |
| 浓缩长文档 | 摘要链( | 内置Map-Reduce摘要逻辑。 |
| 生成图片/音频/视频 | 服务商原生单次调用节点(OpenAI、Gemini、ElevenLabs等) | 切勿将媒体生成封装在Agent中——详见“二进制数据与Agent边界”部分。 |
文本分类器细节(Agent+Switch反模式):每个分类类别都需要名称和描述。模型会根据描述进行路由,而非名称——没有描述的类别会被随机选择。设置可提升边缘输入场景的鲁棒性。单个节点即可实现N分支路由,无需使用“Agent做决策+Switch做路由”的组合,后者需要两个节点及额外的提示词模板,而文本分类器可原生实现该功能。
options.enableAutoFixing: true聊天模型节点(、、等)是子节点——无法独立运行。它们需通过连接方式接入链、Agent、分类器或提取器。
.lmChatOpenAi.lmChatAnthropic.lmChatOpenRouterai_languageModelThe sub-node pattern
子节点模式
The Agent has a main input (the prompt / user message) and up to four sub-node slots, each wired by its own connection type:
ai_*| Slot | Connection type | Required? | Node example |
|---|---|---|---|
| model | | Yes | |
| memory | | Optional | |
| tools | | Optional (but the point of an agent) | |
| outputParser | | Optional | |
A sub-node connects FROM itself TO the agent. In workflow JSON the connection lives on the sub-node, keyed by the type:
ai_*json
"Main LLM": {
"ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]]
},
"Simple Memory": {
"ai_memory": [[{ "node": "AI Agent", "type": "ai_memory", "index": 0 }]]
},
"Search customer DB": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
}Multiple tools all connect into the same index 0 — they stack, they don't fan into separate indices. With you wire each with an op using . The agent puts its final answer in (not , not ) — downstream nodes read .
ai_tooln8n_update_partial_workflowaddConnectionsourceOutput: "ai_tool"$json.output.text.response{{ $json.output }}See EXAMPLES.md for a complete stateless agent-core node-object snippet.
Agent拥有一个主输入(提示词/用户消息)和最多四个子节点插槽,每个插槽通过专属的连接类型接入:
ai_*| 插槽 | 连接类型 | 是否必填 | 节点示例 |
|---|---|---|---|
| model | | 是 | |
| memory | | 否 | |
| tools | | 否(但这是Agent的核心价值) | |
| outputParser | | 否 | |
子节点需从自身连接至Agent。在工作流JSON中,连接信息存储在子节点中,以类型作为键:
ai_*json
"Main LLM": {
"ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]]
},
"Simple Memory": {
"ai_memory": [[{ "node": "AI Agent", "type": "ai_memory", "index": 0 }]]
},
"Search customer DB": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
}多个工具可接入同一个索引0——它们会堆叠,而非分散到不同索引。使用时,可通过操作,指定来连接每个工具。Agent的最终结果会输出到****(不是或)——下游节点需读取。
ai_tooln8n_update_partial_workflowaddConnectionsourceOutput: "ai_tool"$json.output.text.response{{ $json.output }}完整的无状态Agent核心节点代码片段请参考EXAMPLES.md。
Two non-negotiables
两项不可妥协的规则
- Tool names and descriptions ARE part of the prompt. The model picks a tool by reading its name and description — nothing else. A tool named with an empty description is invisible to the model: it skips it, mis-selects it, or hallucinates parameters. There's usually no error — just an agent that "won't use my tool". Treat both like API design. → TOOLS.md
tool1 - Structured output must parse AND autoFix. An with
outputParserStructuredand a coding-capable fixer model is the production pattern. Without autoFix, one malformed JSON response halts the whole workflow. → STRUCTURED_OUTPUT.mdautoFix: true
- 工具名称和描述是提示词的一部分。模型通过读取工具的名称和描述来选择工具——无其他依据。命名为且描述为空的工具对模型来说是“不可见”的:模型会跳过它、错误选择它,或生成虚假参数。通常不会报错——只会出现“Agent不使用我的工具”的问题。请像设计API一样对待工具名称和描述。→ TOOLS.md
tool1 - 结构化输出必须支持解析和自动修复。配置的
autoFix: true节点,搭配具备编码能力的修复模型,是生产环境的标准方案。如果没有自动修复,一次格式错误的JSON响应就会导致整个工作流中断。→ STRUCTURED_OUTPUT.mdoutputParserStructured
Strong defaults
推荐默认配置
- Per-tool usage goes in the tool description, not the system prompt. Anything about how to call this specific tool belongs with the tool, so it travels across agents and keeps the system prompt focused. → SYSTEM_PROMPT.md
- Sub-workflow tools () for anything multi-step. Any workflow becomes a tool with typed
.toolWorkflowinputs, and composes with branching, error handling, and reuse. Default here when in doubt. → SUBWORKFLOW_AS_TOOL.md and n8n-subworkflows.$fromAI() - Wrap tools with user-visible side effects in human review. Sends, payments, refunds, account changes get gated behind an approval node so a human signs off before the tool fires. → HUMAN_REVIEW.md
- Raise . The default tool-call cap is low (single digits on most versions) — fine for a one-tool agent, far too low for a multi-tool agent that chains several calls per turn. It surfaces as "max iterations reached" or empty output. Set
maxIterationsto a realistic ceiling (15 for a focused sub-agent, 50-200 for a broad orchestrator).options.maxIterations - Put the current date in the system prompt via (or
{{ $now }}). A hardcoded date is stale immediately.{{ $now.format('DDDD') }}
- 工具的使用说明应放在工具描述中,而非系统提示词。任何与“如何调用该特定工具”相关的内容都应与工具绑定,这样工具可在不同Agent间复用,同时保持系统提示词的简洁性。→ SYSTEM_PROMPT.md
- 多步骤任务使用子工作流工具()。任何工作流都可通过带类型的
.toolWorkflow输入转换为工具,支持分支、错误处理和复用。不确定时优先选择此方案。→ SUBWORKFLOW_AS_TOOL.md和n8n-subworkflows。$fromAI() - 对有用户可见副作用的工具添加人工审核。发送消息、支付、退款、账户变更等操作需通过审批节点,确保工具执行前需人工确认。→ HUMAN_REVIEW.md
- 提高值。默认的工具调用次数上限非常低(大多数版本为个位数)——适合单工具Agent,但远不足以支撑多工具Agent的多轮调用。问题表现为“达到最大迭代次数”或输出为空。将
maxIterations设置为合理的上限(专注型子Agent设为15,通用编排型设为50-200)。options.maxIterations - 在系统提示词中通过(或
{{ $now }})添加当前日期。硬编码的日期会立即失效。{{ $now.format('DDDD') }}
The four tool types
四种工具类型
Pick the lightest option that covers the job:
| Tool type | Node | Use when |
|---|---|---|
| Native tool node | | The capability maps to one existing node + one operation. Lowest overhead. |
| Sub-workflow as tool | | More than one node, reusable logic, or you want independent testability. The canonical n8n way — default when in doubt. |
| HTTP Request Tool | | A single external HTTP API the agent should orchestrate directly. Reuse the service's predefined credential to cover operations a native node doesn't expose. |
| MCP Client Tool | | A maintained MCP server already covers it, or you want one published workflow to serve many agents. |
There is also a Custom Code Tool () for pure inline computation — but its runtime contract (string in / string out, no , no ) is owned by the n8n-code-tool skill. Read that before writing one. Rule of thumb: if you find yourself reaching for inside the code, you want instead.
.toolCode$fromAI$helpers$fromAI().toolWorkflow选择能满足需求的最轻量方案:
| 工具类型 | 节点 | 使用场景 |
|---|---|---|
| 原生工具节点 | | 功能对应单个现有节点+单个操作。开销最低。 |
| 子工作流工具 | | 需要多个节点、可复用逻辑或独立可测试性。n8n的标准方案——不确定时优先选择。 |
| HTTP请求工具 | | Agent需直接编排单个外部HTTP API。复用服务预定义的凭证,可覆盖原生节点未暴露的操作。 |
| MCP客户端工具 | | 已有维护中的MCP服务器,或希望单个发布的工作流为多个Agent提供服务。 |
还有自定义代码工具()用于纯内联计算——但其运行时约定(字符串输入/输出,不支持、)由n8n-code-tool技能负责。编写前请先阅读该技能。经验法则:如果需要在代码中使用,则应选择。
.toolCode$fromAI$helpers$fromAI().toolWorkflow$fromAI()
: how the agent fills tool parameters
$fromAI()$fromAI()
:Agent如何填充工具参数
$fromAI()Tool parameters the agent should decide are wrapped in . It is a real n8n expression helper, used inside a tool node's parameter expressions:
$fromAI()={{ $fromAI('paramName', 'what to put here — be specific: format, range, example', 'string') }}- paramName — the name the model uses internally (snake_case or camelCase, be consistent).
- description — tells the model what value to produce. It is part of the prompt — write it like JSDoc.
- type (optional) — (default),
'string','number','boolean'. A wrong-typed value fails the call.'json' - defaultValue (optional) — used when the model omits it.
$fromAI()$fromAIuserIdsessionIdAgent需要决定的工具参数需用包裹。这是一个真实的n8n表达式助手,用于工具节点的参数表达式中:
$fromAI()={{ $fromAI('paramName', '此处需明确:格式、范围、示例', 'string') }}- paramName —— 模型内部使用的参数名称(蛇形命名或驼峰命名,保持一致)。
- description —— 告知模型需要生成的值。这是提示词的一部分——请像编写JSDoc一样描述。
- type(可选)—— (默认)、
'string'、'number'、'boolean'。类型错误的值会导致调用失败。'json' - defaultValue(可选)—— 模型未提供参数时使用的默认值。
$fromAI()$fromAIuserIdsessionIdSystem prompt vs tool description
系统提示词 vs 工具描述
| Belongs in the system prompt | Belongs in the tool's description |
|---|---|
| Persona, role, voice | What this specific tool does |
| Global output/format rules ("respond in markdown") | When to use it vs other tools |
| Refusal / safety behavior | What each parameter means and its shape |
Display protocols ( | Examples of good vs bad invocations |
Universal context (current date via | Tool-specific gotchas (rate limits, edge cases) |
| Inter-tool flow ("after generating, always display") | Tool-specific input transformations |
Why split it: a well-described tool works in any agent that drops it in, tool details only "load" when the model considers that tool (token efficiency), and you update one tool description instead of a paragraph buried in a 5000-token prompt. → SYSTEM_PROMPT.md
| 属于系统提示词的内容 | 属于工具描述的内容 |
|---|---|
| 角色设定、职责、语气 | 该特定工具的功能 |
| 全局输出/格式规则(如“用Markdown回复”) | 何时使用该工具而非其他工具 |
| 拒绝/安全行为 | 每个参数的含义及格式 |
展示协议(如图片使用 | 正确/错误调用示例 |
通用上下文(如通过 | 工具特定注意事项(速率限制、边缘场景) |
| 工具间流程(如“生成后始终展示”) | 工具特定输入转换规则 |
拆分原因:描述清晰的工具可在任何Agent中复用,工具细节仅在模型考虑使用该工具时才会“加载”(提升Token效率),且只需更新工具描述,无需修改嵌入在5000Token提示词中的段落。→ SYSTEM_PROMPT.md
Structured output: when and how
结构化输出:场景与实现
Add an sub-node (wired ) when downstream needs strict JSON, not free-form text. Two rules:
outputParserStructuredai_outputParser- Use with a real JSON Schema, not
schemaType: 'manual'. An example can't express required-vs-optional, enums, numeric ranges, or array constraints — you outgrow it the first time the shape gets non-trivial. Reach forjsonSchemaExample+ an example only for throwaway shapes.fromJson - with a coding-capable fixer model. Wire a second model into the parser's
autoFix: trueslot. Reconciling broken JSON against a schema is a coding task — a weak fixer just produces another malformed retry and burns tokens.ai_languageModel
→ STRUCTURED_OUTPUT.md for the schema patterns, the load-bearing "DO NOT wrap in markdown" retry line, and the parse-failure cookbook.
当下游需要严格的JSON而非自由文本时,添加子节点(通过连接)。需遵循两条规则:
outputParserStructuredai_outputParser- 使用并配置真实的JSON Schema,而非
schemaType: 'manual'。示例无法表达必填/可选字段、枚举值、数值范围或数组约束——当结构变得复杂时,示例方案会立即失效。仅在临时结构场景下使用jsonSchemaExample+示例。fromJson - 开启并搭配具备编码能力的修复模型。将第二个模型接入解析器的
autoFix: true插槽。根据Schema修复错误JSON是编码任务——弱修复模型只会生成另一个格式错误的重试结果,浪费Token。ai_languageModel
→ STRUCTURED_OUTPUT.md查看Schema模式、关键的“请勿用Markdown包裹”重试语句,以及解析失败解决方案。
Memory: brief mental model
记忆:简要模型
Memory is a sub-node (). Without it, every call is stateless — correct for one-shot tasks (classify, summarize). With it, the agent holds a conversation, keyed by whatever expression you bind to .
ai_memorysessionKey- — keeps the last N exchanges per key and persists across executions via n8n's store. The default for chat.
memoryBufferWindowdefaults to 5, which is very low — 50 is a saner starting point. Messages past the window are gone entirely.contextWindowLength - /
memoryPostgresChat— only when memory must be read outside the agent (your own UI, analytics, cross-system). Not needed just to survive restarts; BufferWindow already does that.memoryRedisChat
Plumb a stable key from the trigger to memory consistently. Chat triggers fill automatically; for other surfaces derive one (Slack , a webhook conversation ID). Never hardcode and never put behind (the model will fabricate a UUID). → MEMORY.md
sessionIdthread_tssessionId: 'default'sessionId$fromAI记忆是一个子节点()。没有记忆时,每次调用都是无状态的——适合单次任务(分类、摘要)。开启记忆后,Agent可通过绑定到的表达式来维持对话状态。
ai_memorysessionKey- —— 为每个键保留最近N次对话,并通过n8n存储跨执行持久化。是聊天场景的默认选择。
memoryBufferWindow默认值为5,非常低——建议从50开始设置。超出窗口的消息会被完全丢弃。contextWindowLength - /
memoryPostgresChat—— 仅当记忆需要在Agent外部读取时使用(如自定义UI、分析、跨系统调用)。仅为了重启后保留记忆无需使用该方案;BufferWindow已支持持久化。memoryRedisChat
从触发器稳定传递键到记忆节点。聊天触发器会自动填充;其他场景需自行生成(如Slack的、Webhook的对话ID)。切勿硬编码,也不要将放在之后(模型会生成虚假的UUID)。→ MEMORY.md
sessionIdthread_tssessionId: 'default'sessionId$fromAIBinary and the agent boundary
二进制数据与Agent边界
This is the seam that trips people up:
- The model CAN see uploaded images (vision) via on the agent.
options.passthroughBinaryImages: true - Tools CANNOT receive binary. is JSON-only — no base64, no bytes, even through non-AI bindings.
$fromAI() - The agent's output is text-shaped (or structured-text with a parser). When a model returns image/audio/video bytes, the Agent doesn't surface them at all — there's nothing to recover downstream.
Workaround: pre-stage uploads to storage before the agent runs, inject the storage keys into the system prompt, and let tools accept the key as a string parameter and re-fetch internally. For one-shot media generation, skip the agent and call the provider's native single-call node directly.
The binary mechanics (which storage, how to stage, how to re-fetch) are owned by n8n-binary-and-data — see its agent-tool binary reference. This skill only marks the boundary; don't re-derive the mechanics here.
这是最容易出错的环节:
- 模型可查看上传的图片(视觉能力),需在Agent上设置。
options.passthroughBinaryImages: true - 工具无法接收二进制数据。仅支持JSON——不支持base64、字节,即使通过非AI绑定也不行。
$fromAI() - Agent的输出为文本格式(或通过解析器输出结构化文本)。当模型返回图片/音频/视频字节时,Agent不会输出任何内容——下游无法恢复这些数据。
解决方案:在Agent运行前将文件上传到存储服务,将存储密钥注入系统提示词,让工具接收密钥作为字符串参数并在内部重新获取文件。对于单次媒体生成任务,跳过Agent直接调用服务商的原生单次调用节点。
二进制数据的具体机制(选择哪种存储、如何上传、如何重新获取)由n8n-binary-and-data技能负责——请查看其Agent工具二进制参考文档。本指南仅界定边界,不重复推导具体实现。
Human review (gate destructive tools)
人工审核(限制高风险工具)
When a tool's effect needs human sign-off before execution (sends, payments, refunds, account changes), wrap it with a review tool node — , , , , etc. (n8n names these "Hitl" / human-in-the-loop). The review node sits between the wrapped tool and the agent on the connection: wrapped tool → review node → Agent.
slackHitlTooldiscordHitlTooltelegramHitlToolgmailHitlToolai_toolWhether sign-off is needed is a product/policy call — surface the question to the user, recommend based on blast radius, and let them decide.
The critical rule: show the actual parameters the wrapped tool will receive. Use the literal in the approval message, never a paraphrase — otherwise the human approves text the model made up, not the call about to fire. → HUMAN_REVIEW.md
{{ $tool.parameters.<name> }}$fromAI()当工具执行的操作需要人工确认时(如发送消息、支付、退款、账户变更),请使用审核工具节点包裹——如、、、等(n8n将这些命名为“Hitl”/人工介入)。审核节点需位于被包裹工具与Agent之间的连接链中:被包裹工具→审核节点→Agent。
slackHitlTooldiscordHitlTooltelegramHitlToolgmailHitlToolai_tool是否需要确认属于产品/政策决策——需向用户明确该问题,根据影响范围给出建议,由用户决定。
关键规则:展示被包裹工具将接收的真实参数。在审批消息中使用字面量,切勿使用生成的转述——否则人工审核的是模型生成的文本,而非即将执行的真实调用。→ HUMAN_REVIEW.md
{{ $tool.parameters.<name> }}$fromAI()Chat agents (Slack, Discord, Teams, Telegram)
聊天Agent(Slack、Discord、Teams、Telegram)
The one non-negotiable, regardless of complexity: any chat-triggered workflow that posts a reply MUST filter out the bot's own user ID, or its own replies re-trigger it in an infinite loop that burns runs and tokens. Prefer trigger-level filtering when available (Slack Trigger's is an exclusion list — put the bot ID there); otherwise filter in the first node after the trigger.
options.userIds$json.user !== '<BOT_USER_ID>'Beyond the filter, a simple bot (trigger → agent → reply) lives fine in one workflow. Split into shell + core + sub-agents only once you need loading UX, sub-agents, multi-surface reuse, or robust error handling:
- Shell — trigger, anti-loop filter, event-type Switch, loading/error UX, renders the reply. No LLM.
- Core — stateless agent, +
chatInputinputs, memory keyed onthreadId, tools and sub-agents.threadId - Sub-agents — one narrow domain each, called via , stateless (full context in
.toolWorkflow).chatInput
→ CHAT_AGENT_PATTERNS.md for per-surface semantics, threading-as-session, and the full topology.
无论复杂度如何,必须遵守的规则:任何发送回复的聊天触发工作流都必须过滤机器人自身的用户ID,否则机器人的回复会触发无限循环,消耗运行次数和Token。优先使用触发器级别的过滤(如Slack触发器的是排除列表——将机器人ID加入其中);否则在触发器后的第一个节点中过滤。
options.userIds$json.user !== '<BOT_USER_ID>'除过滤规则外,简单机器人(触发器→Agent→回复)可在单个工作流中实现。仅当需要加载态UI、子Agent、多渠道复用或健壮的错误处理时,才拆分为外壳+核心+子Agent:
- 外壳——触发器、防循环过滤、事件类型Switch、加载/错误UI、回复渲染。无LLM。
- 核心——无状态Agent,输入为+
chatInput,记忆以threadId为键,包含工具和子Agent。threadId - 子Agent——每个负责一个细分领域,通过调用,无状态(完整上下文在
.toolWorkflow中)。chatInput
→ CHAT_AGENT_PATTERNS.md查看各渠道语义、会话线程化以及完整拓扑结构。
RAG (retrieval augmented generation)
RAG(检索增强生成)
n8n ships the LangChain RAG primitives (document loaders, splitters, embeddings, vector stores, retrievers). Two opinions worth stating up front:
- Rule out cheaper lookups first. Exact lookups → a database or Data Table query, not RAG. Freshness → a live search tool. A small/structured doc set → give the agent list/fetch tools. Reach for a vector store only when there are too many docs to list and queries are semantic.
- Wire the vector store as a retrieval tool (,
mode: 'retrieve-as-tool') so the agent decides when retrieval is relevant and can phrase the query itself. Embed query and documents with the same model.ai_tool
→ RAG.md (intentionally thin — defaults depend on data shape and scale).
n8n内置了LangChain的RAG原语(文档加载器、拆分器、嵌入模型、向量存储、检索器)。先明确两个观点:
- 优先排除更廉价的查询方案。精确查询→使用数据库或数据表查询,而非RAG。实时数据→使用实时搜索工具。小型/结构化文档集→为Agent提供列表/查询工具。仅当文档数量过多无法列出且查询为语义查询时,才使用向量存储。
- 将向量存储作为检索工具接入(,
mode: 'retrieve-as-tool'),让Agent自行决定何时需要检索,并可自行构造查询语句。查询和文档需使用相同的嵌入模型。ai_tool
→ RAG.md(内容简洁,因默认配置取决于数据格式和规模)。
Reference files
参考文档
| File | Read when |
|---|---|
| TOOLS.md | Adding tools, choosing among the four types, writing names/descriptions, |
| SUBWORKFLOW_AS_TOOL.md | Wiring a sub-workflow as a tool via |
| SYSTEM_PROMPT.md | Writing/refactoring a system prompt, the system-prompt-vs-tool-description split |
| STRUCTURED_OUTPUT.md | Forcing JSON output, configuring autoFix, the fixer model, parse-failure fixes |
| MEMORY.md | Choosing a memory type, persistence, sessionId handling |
| HUMAN_REVIEW.md | Adding human approval, approval-message content, multi-channel approver |
| CHAT_AGENT_PATTERNS.md | Building a Slack/Discord/Teams/Telegram bot, shell + core + sub-agents topology |
| RAG.md | Retrieval-augmented agents (thin by design) |
| EXAMPLES.md | Concrete node-object snippets: stateless agent core, Slack router shell, domain sub-agent |
| 文件 | 阅读场景 |
|---|---|
| TOOLS.md | 添加工具、选择工具类型、编写名称/描述、 |
| SUBWORKFLOW_AS_TOOL.md | 通过 |
| SYSTEM_PROMPT.md | 编写/重构系统提示词、系统提示词与工具描述的拆分规则 |
| STRUCTURED_OUTPUT.md | 强制JSON输出、配置自动修复、修复模型选择、解析失败解决方案 |
| MEMORY.md | 选择记忆类型、持久化配置、sessionId处理 |
| HUMAN_REVIEW.md | 添加人工审核、审核消息内容、多渠道审核人配置 |
| CHAT_AGENT_PATTERNS.md | 构建Slack/Discord/Teams/Telegram机器人、外壳+核心+子Agent拓扑 |
| RAG.md | 检索增强型Agent(内容简洁) |
| EXAMPLES.md | 具体节点代码片段:无状态Agent核心、Slack路由外壳、领域子Agent |
Anti-patterns
反模式
| Anti-pattern | What goes wrong | Fix |
|---|---|---|
Generic tool names ( | Model can't tell which tool to pick — skips them or hallucinates params | Verb-first specific names: |
| Empty or one-line tool descriptions | Model has no idea when to invoke; bad selection, no error | Write a real description: what it does, when to use, what each param means |
| Cramming per-tool instructions into the system prompt | Bloated prompt, no reuse, per-tool guidance buried | Move tool-specific instructions into tool descriptions |
| Agent + Switch to route on natural language | Two nodes + prompt boilerplate where Text Classifier is one node | Use Text Classifier — each category gets its own output handle (name and description) |
| Wrapping image/audio/video generation in an Agent | Binary doesn't flow through tools or out of the agent output | Use the provider's native single-call node directly |
| One malformed response halts the workflow | |
| Passing binary directly to a tool | Doesn't work — binary can't cross the tool boundary | Pre-stage to storage, pass keys; see n8n-binary-and-data |
Hardcoded | Conversations cross, or the model fabricates a UUID | Plumb a stable key from the trigger to memory and tools |
| Two near-identical tools | Selection is non-deterministic, model gets confused | One tool with internal branching driven by a parameter |
| Chat bot with no bot-user filter | Its own replies re-trigger it → infinite loop | Exclude the bot user ID at the trigger or first node |
| "Max iterations reached" / empty output | Raise |
Filling the human-review message via | Approver signs off on a paraphrase, not the real call | Use literal |
| 反模式 | 问题 | 修复方案 |
|---|---|---|
通用工具名称( | 模型无法区分工具——跳过工具或生成虚假参数 | 使用动词开头的具体名称: |
| 工具描述为空或仅一行 | 模型不知道何时调用工具;选择错误,无报错 | 编写完整描述:功能、使用场景、参数含义 |
| 将工具专属指令塞入系统提示词 | 提示词臃肿、无法复用、工具相关指引被淹没 | 将工具专属指令移至工具描述 |
| 使用Agent+Switch处理自然语言路由 | 需要两个节点+提示词模板,而文本分类器可单个节点实现 | 使用文本分类器——每个类别拥有独立输出端口(需配置名称和描述) |
| 将图片/音频/视频生成封装在Agent中 | 二进制数据无法通过工具或Agent输出传递 | 直接调用服务商的原生单次调用节点 |
| 一次格式错误的响应会中断整个工作流 | 开启 |
| 直接向工具传递二进制数据 | 无法生效——二进制数据无法跨越工具边界 | 先上传至存储服务,传递密钥;参考n8n-binary-and-data |
硬编码 | 会话混乱,或模型生成虚假UUID | 从触发器稳定传递键到记忆和工具节点 |
| 两个几乎相同的工具 | 模型选择不确定,易混淆 | 合并为一个工具,通过参数驱动内部分支 |
| 聊天机器人未过滤自身用户ID | 自身回复触发无限循环 | 在触发器或第一个节点中排除机器人用户ID |
多工具Agent保留默认的低 | 出现“达到最大迭代次数”/输出为空 | 提高 |
通过 | 审核人确认的是转述内容,而非真实调用 | 使用字面量 |
What's NOT available via the community MCP
社区MCP不支持的功能
| Want to do | Reality |
|---|---|
| Run / chat-test the agent end-to-end with live tokens | |
| Set credentials' actual secret values | |
| Assign a workflow's Error Workflow | UI only — see n8n-error-handling. Build the catch-all, then hand the user the UI step. |
| Pin the exact model availability per instance | Model lists shift between versions — |
What the MCP can do: search and inspect every LangChain node (, ), validate node config and the whole graph (, ), build and patch the agent and its sub-nodes ( with on outputs), test (), and pull the saved JSON to verify wiring (). The deep AI-agent guide also lives in .
search_nodesget_nodevalidate_nodevalidate_workflown8n_update_partial_workflowaddConnectionai_*n8n_test_workflown8n_get_workflowtools_documentation({topic: "ai_agents_guide", depth: "full"})| 需求 | 现状 |
|---|---|
| 使用真实Token端到端运行/测试Agent聊天会话 | |
| 设置凭证的实际密钥值 | |
| 为工作流分配错误工作流 | 仅支持UI操作——参考n8n-error-handling。先构建全局错误处理,再指导用户完成UI步骤。 |
| 固定实例的精确模型可用性 | 模型列表会随版本变化—— |
MCP支持的功能:搜索和查看所有LangChain节点(、)、验证节点配置和整个图谱(、)、构建和修补Agent及其子节点(搭配输出的操作)、测试()、以及拉取已保存的JSON验证连接()。深度AI Agent指南也可通过获取。
search_nodesget_nodevalidate_nodevalidate_workflown8n_update_partial_workflowai_*addConnectionn8n_test_workflown8n_get_workflowtools_documentation({topic: "ai_agents_guide", depth: "full"})Integration with other skills
与其他技能的集成
- n8n-workflow-patterns () — the high-level "agent in a workflow" shape. This skill is the deep dive; start there for architecture.
ai_agent_workflow.md - n8n-mcp-tools-expert — node-type formats (short form for , long form in JSON) and tool-selection guidance. Consult before any MCP call.
get_node - n8n-node-configuration — -driven fields on the agent and sub-nodes; Slack/Block Kit message shapes (
displayOptions, Slack section).NODE_FAMILY_GOTCHAS.md - n8n-expression-syntax — ,
{{ }},$json.output, and$now/$fromAIall rely on correct expression syntax.$tool.parameters - n8n-code-tool — the Custom Code Tool's runtime contract (string in/out, no ). Read it before writing a
$fromAI..toolCode - n8n-subworkflows — the sub-workflow primitive that builds on (Execute Workflow Trigger inputs/outputs, naming, search-before-build).
.toolWorkflow - n8n-binary-and-data — owns the agent-tool binary boundary mechanics (staging uploads, returning generated files).
- n8n-validation-expert — interpreting results, including AI-connection issues (a tool wired into
validate_workflowinstead ofmainflags as disconnected).ai_tool - n8n-error-handling — on tool sub-workflows and the agent-core call; error UX on chat shells.
onError: 'continueErrorOutput' - n8n-code-javascript / n8n-code-python — for Code-node logic inside a tool sub-workflow (different sandbox from the Code Tool).
- n8n-workflow-patterns()——“Agent在工作流中定位”的宏观内容。本指南是深度教程;架构设计请先参考该文档。
ai_agent_workflow.md - n8n-mcp-tools-expert——节点格式(使用简写,JSON中使用完整格式)和工具选择指引。调用任何MCP前请参考该技能。
get_node - n8n-node-configuration——Agent及其子节点的驱动字段;Slack/Block Kit消息格式(
displayOptions的Slack章节)。NODE_FAMILY_GOTCHAS.md - n8n-expression-syntax——、
{{ }}、$json.output、$now/$fromAI都依赖正确的表达式语法。$tool.parameters - n8n-code-tool——自定义代码工具的运行时约定(字符串输入/输出,不支持)。编写
$fromAI前请阅读该技能。.toolCode - n8n-subworkflows——基于的子工作流原语(Execute Workflow Trigger输入/输出、命名、构建前搜索)。
.toolWorkflow - n8n-binary-and-data——负责Agent工具二进制边界的具体实现(上传预存、返回生成文件)。
- n8n-validation-expert——解读结果,包括AI连接问题(如工具接入
validate_workflow而非main会标记为未连接)。ai_tool - n8n-error-handling——工具子工作流和Agent核心调用的配置;聊天外壳的错误UI。
onError: 'continueErrorOutput' - n8n-code-javascript / n8n-code-python——工具子工作流内部的代码节点逻辑(与代码工具的沙箱不同)。
Quick reference checklist
快速检查清单
Before shipping an agent:
- Right node: Agent for tools/memory/multi-turn; Text Classifier for routing; Information Extractor for fields; native node for media
- Model wired via
ai_languageModel - Every tool has a verb-first specific name AND a real description
- descriptions are specific (format, range, example); identity/limits/sessionId plumbed deterministically, not via
$fromAI()$fromAI - Per-tool guidance lives in tool descriptions, not the system prompt
- in the system prompt (no hardcoded date)
$now - raised for multi-tool agents
maxIterations - Memory keyed on a stable from the trigger (not
sessionKey, not'default');$fromAIraised from 5contextWindowLength - Structured output: +
schemaType: 'manual'+ a coding-capable fixer modelautoFix: true - Destructive tools wrapped in human review; approval message uses , not
$tool.parameters$fromAI - Chat bots filter the bot's own user ID (trigger-level or first node)
- Binary: model vision via ; tools get storage keys, never bytes
passthroughBinaryImages - Validated with and verified with
validate_workflow(sub-nodes onn8n_get_workflow, notai_*)main
Remember: an agent is only as good as its tool names, descriptions, and system-prompt discipline. The model can't see your wiring — it sees a system prompt and a list of named, described tools. Design those like an API and most "the agent won't behave" problems disappear.
上线Agent前请确认:
- 节点选型正确:工具/记忆/多轮任务用Agent;路由用文本分类器;字段提取用信息提取器;媒体生成本地用原生节点
- 模型已通过连接
ai_languageModel - 每个工具都有动词开头的具体名称和完整描述
- 描述明确(格式、范围、示例);身份/权限/sessionId为确定性传递,未使用
$fromAI()$fromAI - 工具专属指引在工具描述中,而非系统提示词
- 系统提示词包含(无硬编码日期)
$now - 多工具Agent已提高值
maxIterations - 记忆以触发器传递的稳定为键(非
sessionKey,非'default');$fromAI已从5提高contextWindowLength - 结构化输出:+
schemaType: 'manual'+ 具备编码能力的修复模型autoFix: true - 高风险工具已包裹人工审核;审核消息使用,而非
$tool.parameters$fromAI - 聊天机器人已过滤自身用户ID(触发器级别或第一个节点)
- 二进制数据:模型视觉能力已开启;工具接收存储密钥,而非字节
passthroughBinaryImages - 已验证:通过验证,并通过
validate_workflow确认连接(子节点通过n8n_get_workflow连接,而非ai_*)main
记住:Agent的性能取决于工具名称、描述和系统提示词的规范性。模型无法看到你的连接配置——它只能看到系统提示词和一组带名称、描述的工具。像设计API一样设计这些内容,大多数“Agent行为不符合预期”的问题都会迎刃而解。