关于 n8n-agents
面向 n8n Agent 节点使用者的构建指南,涵盖模型、记忆、工具和结构化输出等配置,并帮助按任务选择合适的节点与触发方式。
主要功能
- 01配置模型、记忆、工具和输出解析器
- 02比较 Agent 与单次调用节点
- 03为工具设计名称与描述
- 04将子工作流用作工具
- 05为副作用操作加入人工审核
- 06说明触发器与会话连续性
适用场景
- 01搭建需要多轮推理和工具调用的流程
- 02为单次文本生成选择轻量节点
- 03将多步骤流程封装为 Agent 工具
- 04在发送或付款前设置人工审批
MCP 相关
说明已通过 MCP 提供的工作流可作为 Agent 工具使用,并引导参考 n8n-extending-mcp。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ n8n-io/ skills --skill n8n-agents安装后在 Claude Code 中输入/n8n-agents确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/CHAT_AGENT_PATTERNS.mdHUMAN_REVIEW.mdMEMORY.mdRAG.mdSTRUCTURED_OUTPUT.mdSUBWORKFLOW_AS_TOOL.mdSYSTEM_PROMPT.mdTOOLS.mdreferences/examples/agent-core.jsonnotion-ideas-subagent.jsonslack-router.json详细介绍
n8n Agent
n8n Agent 节点(@n8n/n8n-nodes-langchain.agent)是一个多轮大模型驱动器,配有用于模型、记忆、工具和可选输出解析器的子节点。
何时使用 Agent 节点,何时使用原始聊天补全
选择建议:
- 需要工具调用、多轮推理或记忆? 使用 Agent。如果不想费心选择,它也是不错的默认选项:在整个工作流中统一使用 Agent 是合理的,也能让后续升级更简单。
- 想要尽可能轻量的单次文本输出调用? 使用 Basic LLM Chain(
@n8n/n8n-nodes-langchain.chainLlm),并搭配聊天模型子节点(OpenRouter Chat Model、OpenAI Chat Model、Anthropic Chat Model等)。没有 Agent 循环,也没有工具、记忆或解析器插槽,因此更易于调试。注意:聊天模型节点是子节点,不能独立运行。它们需要连接到链或 Agent。如果更愿意统一使用 Agent,这里也可以使用 Agent。 - 要根据自然语言输入路由到 N 个输出分支之一(由 AI 选择分支)? 使用 Text Classifier 节点(
@n8n/n8n-nodes-langchain.textClassifier)。它为每个类别提供一个输出端口,下游路径可直接连接到各个端口。每个类别都需要同时设置名称和描述(模型依据描述进行选择,仅有名称是不够的)。设置options.enableAutoFixing: true,以增强对边缘输入的处理能力。搭配聊天模型子节点(OpenRouter Chat Model、OpenAI Chat Model等)使用。不要用 Agent + Switch 来实现这一功能。Text Classifier 是专为此用途设计的单节点。 - 需要结构化输出,但不需要工具? 考虑未来扩展时,Agent 是更简单的默认选项。Basic LLM Chain 也支持
outputParserStructured子节点;如果需要更轻量的节点,它同样适用。 - 图像/音频/视频生成? 直接调用时,使用对应服务商的原生单次调用节点(OpenAI Image、Gemini Image、ElevenLabs 等)。通过聚合服务路由时(OpenRouter、Together 等),使用 HTTP Request,因为没有原生聚合服务节点,而且原生节点会在媒体操作中将服务商的基础 URL 写死。不要用 Agent 包装媒体生成,请参见下文“二进制数据与 Agent 边界”。
对于范围较窄的任务,还有其他 LangChain“链”/实用工具节点:Information Extractor(从文本中提取结构化字段)、Sentiment Analysis(三路分支)、Summarization Chain、Basic LLM Chain。
对于大多数大模型步骤,Agent 是一个合理的默认选项。如果你明确需要一个更轻量的节点来进行单次文本调用,且不需要工具、记忆或迭代,则使用 Basic LLM Chain。如果 Information Extractor/Sentiment Analysis/Summarization Chain/Text Classifier 这类专用节点恰好与任务完全匹配,则使用对应节点。
不容妥协的要求
- 工具名称和描述都是提示词的一部分。 模型会根据名称和描述选择工具。含糊的工具节点名称(如
doStuff)或较弱的描述(“用数据做点事”)会导致悄无声息的失败:模型会跳过工具、选错工具,或幻觉出参数。请将两者都视为 API 设计。参见references/TOOLS.md。 - 结构化输出:解析并自动修复。 生产环境中的标准做法是使用
outputParserStructured,设置autoFix: true,并搭配具备编码能力的修复模型(例如 Claude Sonnet 4.6)。
推荐默认做法
- 工具描述是模块化的提示词片段。 任何与如何调用此工具相关的内容都应放在工具的描述中,而不是系统提示词中。这样可以让系统提示词保持聚焦,也让工具能在不同 Agent 间复用。参见
references/SYSTEM_PROMPT.md。 - 任何多步骤流程都使用子工作流工具(
toolWorkflow)。 将任何工作流变成带有类型化fromAi()输入的工具,并支持与分支、错误处理和子工作流组合使用。参见references/SUBWORKFLOW_AS_TOOL.md。 - 对具有用户可见副作用的工具加入人工审核。 发送消息、付款、退款、账户变更等操作,应通过 Slack / Chat / Discord / Telegram 审批节点设置关卡,确保工具运行前由人工批准。参见
references/HUMAN_REVIEW.md。
子节点模式
Agent 节点有一个主输入(提示词或用户消息)和子节点输入:
const aiAgent = node({
type: '@n8n/n8n-nodes-langchain.agent',
config: {
name: 'Customer Support Agent',
parameters: {
promptType: 'define',
text: '={{ $json.userMessage }}',
options: {
systemMessage: '...',
passthroughBinaryImages: true, // for vision / multimodal
},
},
subnodes: {
model: openRouterModel,
memory: simpleMemory,
tools: [generateImage, editImage, searchKnowledgeBase],
outputParser: structuredParser, // optional
},
},
})
四个子节点槽位:
model(必需):大模型。OpenAI、Anthropic、OpenRouter 等。请使用聊天模型变体,而不是补全模型变体。memory(可选):对话记忆。如果没有,每次调用都是无状态的。参见references/MEMORY.md。tools(可选,但这是使用 Agent 的意义所在):Agent 可以调用的工具。参见references/TOOLS.md。outputParser(可选):强制输出结构化 JSON。参见references/STRUCTURED_OUTPUT.md。
触发器
不同的触发器会以不同方式构造输入:
-
Chat Trigger(
@n8n/n8n-nodes-langchain.chatTrigger) 配合availableInChat: true:启用画布聊天测试器,让你在构建 Agent 时试用它。输入为{ chatInput, sessionId, files[] }。记忆以sessionId为键,因此需要保持对话连续性的地方都要传递它。文件通过files[]传入,参见下文的二进制部分。这不是生产环境的交互入口;生产环境请使用 Slack / Discord / Teams / Telegram / webhook。 -
Webhook:输入形状任意,默认没有会话。可以在请求正文中传递会话 ID / 对话 ID,并将其转发给记忆节点,以管理对话连续性。
-
外部聊天入口(Slack、Discord、Teams、Telegram):每个会发布回复的聊天触发工作流都必须过滤掉机器人自身的用户 ID,否则可能陷入无限循环,甚至导致 n8n 崩溃。如果入口支持,优先在触发器层面过滤(Slack 的
options.userIds是一个排除列表);否则就在触发器后的第一个节点中进行过滤。不同入口的语义各异,参见references/CHAT_AGENT_PATTERNS.md。除防循环过滤外,简单的机器人流程(触发器 → Agent → 回复)可以放在一个工作流中。一旦需要加载状态提示、子 Agent、跨入口复用或稳健的错误处理,就拆分成“外壳”工作流和 Agent 核心子工作流。 -
手动 / 计划:用于临时调用。除非要明确延续先前的运行,否则记忆很少有用。
-
Execute Workflow Trigger(子工作流):当 Agent 本身是另一个 Agent 的工具时使用。将触发器声明的输入视为接口契约。
二进制数据与 Agent 边界
通过 passthroughBinaryImages: true,模型可以看到上传的文件(视觉)。但工具无法接收二进制数据,而且 fromAi() 参数仅支持 JSON。工具也不接受 Base64,即使通过非 AI 绑定传入也不行。
解决方法:在 Agent 运行前,先将上传内容存入存储,然后把存储键注入系统提示词;工具接受字符串形式的键作为参数,并在内部重新获取内容。完整模式见 n8n-binary-and-data references/AGENT_TOOL_BINARY.md。
在输出端:Agent 的输出格式化器以文本为主(如果接入了 outputParser,则为结构化文本)。当模型返回二进制数据(图像字节、音频字节、视频)时,Agent 完全不会输出这些内容。下游没有任何内容可供提取,而且尝试在 Agent 后通过 Code 或 Set 节点恢复也行不通。对于一次性媒体生成,请直接使用提供商的原生单次调用节点,例如 @n8n/n8n-nodes-langchain.googleGemini 或 @n8n/n8n-nodes-langchain.openAi。
例外情况:当媒体处理步骤确实属于 Agent 的工作(它是多个工具之一,根据对话上下文选择,或用于编辑之前生成的图像)时,可以使用工具子工作流,将结果上传到存储并返回键或 URL。模式见 n8n-binary-and-data references/AGENT_TOOL_BINARY.md。不要默认采用这种方式。上传、返回键和重新获取的流程会增加节点,也会引入原本不需要的存储依赖。只有在编排确实需要 Agent 选择工具时才这样做。
系统提示词与工具描述分别应包含什么
| 应放在系统提示词中 | 应放在工具描述中 |
|---|---|
| 角色设定、职责、语气 | 此工具具体做什么 |
| 输出格式规则(“以 Markdown 回复”) | 何时使用此工具而非其他工具 |
| 拒绝/安全行为 | 各参数的含义及其预期格式 |
展示协议(“通过 ![]() Markdown 展示图像”) | 良好与不良调用示例 |
| 通用上下文(当前日期、用户角色) | 工具特有的注意事项(速率限制、边缘情况) |
| 工具间流程(“生成后,始终通过展示协议呈现”) | 工具特有的输入转换 |
优势:工具可以重复使用。描述完善的工具可在任何接入它的 Agent 中正常工作。系统提示词则能专注于职责和共同行为。
如需更深入的指导和示例,请参阅 references/SYSTEM_PROMPT.md 和 references/TOOLS.md。
工具选择:四种类型
选择能够完成任务的最轻量方案:
- 是否有原生 n8n 工具节点?(例如
slackTool、gmailTool、calculatorTool)使用它。配置开销最低。- 原生节点缺少某项操作或需要自定义参数(例如节点未提供的 Notion 端点、非标准标头、不同的分页格式)?使用 HTTP Request Tool,并选择该服务的“Predefined Credential Type”。这样可以复用现有的 OAuth/API 密钥凭据,完整访问 API,且无需自定义身份验证代码。
- 是否有多步骤逻辑,或需要复用项目中已有的子工作流? 将子工作流作为工具(
toolWorkflow)。任何可以构建成工作流的内容,都可以通过类型化的fromAi()输入变成工具。这是 n8n 中功能最强大的选项,因此不确定时优先选择它。请参阅references/SUBWORKFLOW_AS_TOOL.md。 - 是否要让 Agent 直接编排对外部 HTTP API 的调用? 使用 HTTP Request Tool。它也适用于通过长轮询回调处理缓慢的异步任务。
- 该工具是否已经是已发布且可通过 MCP 访问的工作流? 使用 MCP 工具。适用于跨工作流的 Agent 能力。请参阅
n8n-extending-mcp。
如需深入了解各个选项及 fromAi() 参数的连接方式,请参阅 references/TOOLS.md。
人工审核
在决定是否为某个工具添加人工审核或跳过审核之前,请先询问用户。是否需要审批属于产品/策略决策(影响范围、审计要求,以及他们对模型的信任程度),用户比你更适合做出判断。提出这个问题,根据以下标准给出建议,然后让用户决定。
当工具执行前需要人工批准其操作(发送消息、付款、退款、账户变更、面向客户的操作)时,请使用审核工具节点将其包装起来:slackHitlTool、discordHitlTool、telegramHitlTool、gmailHitlTool 等。(n8n 的节点名称使用 Hitl 表示人机协同模式,而 UI 中称其为“人工审核”。)审核节点位于被包装的工具与 Agent 之间,通过 ai_tool 连接:被包装工具的 ai_tool 输出连接到审核节点,审核节点的 ai_tool 输出连接到 Agent。Agent 发出调用后,审核节点会暂停并等待批准;批准后,被包装的工具才会运行。
以下情况默认添加/建议进行人工审核:
- 工具会发送消息、付款、退款,或以其他方式更改用户可见的状态。
- 审批人和发起对话的人不是同一人(例如,经理审批面向客户的操作,或支持团队审批由客户触发的退款)。
- 触发器是非交互式的(订单、表单、计划任务),但工具的操作需要人工签字批准。
审批消息应显示被包装工具将实际接收的参数,而不是模型转述的文本。直接使用 $tool.parameters.<name>,或遍历 $tool.parameters 列出所有参数。不要使用 fromAi() 填写审批文本,否则审批的将是转述内容,而非实际调用内容。请根据实际值自定义按钮标签,例如 Approve {{ $tool.parameters.amount }} refund。
完整配置模式、各平台设置以及多渠道审批人模式,请参阅 references/HUMAN_REVIEW.md。
输出解析:何时以及如何使用
当下游需要结构化数据而非自由文本时,添加 outputParser 子节点。
const parser = outputParser({
type: '@n8n/n8n-nodes-langchain.outputParserStructured',
config: {
parameters: {
schemaType: 'manual',
inputSchema: JSON.stringify({
type: 'object',
properties: {
score: { type: 'integer', minimum: 1, maximum: 5 },
category: { type: 'string', enum: ['bug', 'feature', 'question'] },
reason: { type: 'string' },
tags: { type: 'array', items: { type: 'string' } },
},
required: ['score', 'category', 'reason'],
}),
autoFix: true,
customizeRetryPrompt: true,
prompt: '...retry instructions...', // generally leave as default
},
subnodes: {
languageModel: fixerModel, // coding-capable model, e.g. Claude Sonnet 4.6
},
},
})
- 使用
schemaType: 'manual'和真实的 JSON schema,而不是jsonSchemaExample。 示例无法表达可选字段、枚举、取值范围或数组约束,因此数据结构一旦稍微复杂,你很快就会发现它不够用。Schema 可以标记必填字段和可选字段、定义枚举、限制数字取值和字符串格式,并为模型提供更明确的规则。只有在一次性使用且确定结构永远不会增加约束时,才考虑使用带示例的schemaType: 'fromJson'。 autoFix: true会在解析失败时重试。 将具备编码能力的模型连接为修复器子节点(例如 Claude Sonnet 4.6 或类似模型)。根据 Schema 修复格式错误的 JSON 属于结构化输出/编码任务;能力较弱或通用型模型往往会再次生成格式错误的重试结果,反而达不到预期效果。
包含自定义重试提示词的完整模式,请参阅 references/STRUCTURED_OUTPUT.md。
记忆:简要概念模型
- 无记忆: 无状态。适用于一次性任务(分类、摘要)。
memoryBufferWindow: 为每个记忆键保留最近的 N 条消息,并通过 n8n 的内部存储跨执行持久化。键由绑定到sessionKey的表达式决定。聊天触发器会自动填入sessionId,但你也可以使用任何值作为键(Slack 的thread_ts、webhook 对话 ID,或多租户组合键)。这是聊天记忆的默认选项。“窗口”限制的是保留在上下文中的消息数量,而不是持久化范围。memoryPostgres/memoryRedis/ 类似方案: 当你需要在 Agent 之外查询或读取记忆时,使用这些方案:在自有 UI 中显示对话历史、分析过往聊天,或与其他系统共享记忆。否则,memoryBufferWindow就足够了。
请始终将触发器中的稳定键传递给记忆,否则不同对话可能会串在一起。请参阅 references/MEMORY.md。
RAG(检索增强生成)
n8n 提供了 LangChain 的 RAG 基础组件:文档加载器、文本拆分器、嵌入、向量存储、检索器和重排器。这些组件都能正常工作,但端到端的推荐方案(例如“选哪种向量存储、如何拆分文本、何时进行重排”)在很大程度上取决于数据形态和规模。
本技能刻意不对 RAG 提供太多主观建议。有关 RAG 的更多详情,请参阅 references/RAG.md。
参考文件
| 文件 | 何时阅读 |
|---|---|
references/TOOLS.md | 为 Agent 添加工具、在四种工具类型中进行选择、编写工具名称和描述时 |
references/SUBWORKFLOW_AS_TOOL.md | 通过 toolWorkflow 将子工作流接入为 Agent 工具、映射 fromAi 覆盖项时 |
references/SYSTEM_PROMPT.md | 编写或重构系统提示词、决定哪些内容应放在系统提示词中,哪些应放在工具描述中时 |
references/STRUCTURED_OUTPUT.md | 强制输出 JSON、配置 autoFix 重试、验证下游数据时 |
references/MEMORY.md | 选择记忆类型、处理持久化和 sessionId 时 |
references/RAG.md | 构建检索增强型 Agent;该文件有意仅作占位 |
references/HUMAN_REVIEW.md | 为工具添加人工审批、配置审批消息、设置多渠道审批人模式时 |
references/CHAT_AGENT_PATTERNS.md | 在 Slack、Discord、Teams、Telegram 或任何自定义聊天界面上构建聊天 Agent,设置多工作流 shell + core + sub-agents 拓扑时 |
反模式
| 反模式 | 问题所在 | 修复方法 |
|---|---|---|
通用工具名称(doStuff、runQuery) | 模型无法判断该选哪个工具,因而跳过它们或臆造参数 | 使用动词开头的具体名称:Search customer database、Generate image with Veo |
| 工具描述为空或只有一行 | 模型不清楚何时调用工具,难以正确选择 | 撰写完整描述:说明工具的功能、使用时机和参数含义 |
| 把所有内容都塞进系统提示词 | 提示词臃肿,无法复用,各工具的指导信息也被埋没 | 将各工具专属的说明移到工具描述中,系统提示词仅保留角色设定和全局规则 |
| 本可以使用子工作流,却用了代码节点工具 | 无法复用、无法独立测试,也无法与分支组合 | 使用带有合适子工作流的 toolWorkflow |
| 直接向工具传递二进制数据 | 无法正常工作,二进制数据无法跨越工具边界 | 预先将数据存入存储空间,通过 fromAi 传递键,由工具在内部获取。参见 n8n-binary-and-data |
使用不带 autoFix 的 outputParserStructured | 一次模型输出错误就会导致工作流失败 | 设置 autoFix: true,并使用成本较低的修正模型 |
sessionId 写死或缺少 sessionId | 对话相互串扰,或记忆无法匹配 | 将 sessionId 从触发器一致地传递给记忆和工具 |
| 使用两个近乎相同的工具,而不是一个带分支的工具 | 模型会困惑,选择结果不确定 | 使用一个由参数驱动内部逻辑分支的工具 |
| 将系统提示词写死,且在多个工作流中复用或经常迭代 | 编辑后需要重新发布,无法在工作流间共享,调整内容散落在节点 JSON 中 | 将提示词存储在 Data Table 中,并在运行时加载 |
| 用 Agent 封装图像、音频或视频生成 | 二进制数据无法通过工具或输出格式化器传递,Agent 增加节点却没有收益 | 直接使用服务提供商的原生单次调用节点(OpenAI Image、Gemini Image、ElevenLabs);仅在经由聚合器时使用 HTTP Request |
| 为了根据自然语言输入进行路由而使用 Agent + Switch | Text Classifier 只需一个节点,内置 N 个输出分支;这种做法却需要两个节点和额外的提示词模板 | 使用 Text Classifier(@n8n/n8n-nodes-langchain.textClassifier),每个类别都有独立的输出句柄,可直接连接下游路径 |
| 会更改用户可见状态(发送、付款、退款)的工具未经过人工审核 | Agent 可能因推断错误而执行不可逆操作 | 使用适合相应渠道的审核工具节点(Slack/Chat/Discord/Telegram)进行封装,并通过 $tool.parameters 显示实际参数 |
使用 fromAi() 填写审核批准消息 | 模型会改写内容,导致你批准的是文本而非具体值 | 直接使用 $tool.parameters.<name>,以便显示实际调用内容 |
| 聊天触发的 Agent 工作流在发布回复前,未过滤掉机器人自身的用户 ID | 机器人自己的消息会再次触发工作流,造成无限循环,持续消耗运行次数和令牌,直到触发速率限制或 n8n 并发限制 | 如有条件,优先在触发器层进行过滤(Slack Trigger 的 options.userIds 是排除列表,将机器人 ID 加入其中)。否则,在触发器后的第一个节点中筛选 $json.user !== '<BOT_USER_ID>'(或相应平台的等效字段)。任何会发送回复的聊天触发工作流(Slack、Discord、Teams、Telegram)都必须这样做,无论工作流复杂程度如何。有关各平台语义,参见 references/CHAT_AGENT_PATTERNS.md |
Agent 返回 Block Kit 时,向 Slack 节点的 blocksUi 传入未经封装的 blocks 数组 | Slack 节点会静默接受输入,却不发送富内容消息;既没有错误,也没有警告 | 将值封装为 { "blocks": [...] },并确保值是真正的数组,而不是字符串化的数组。表达式:={{ { "blocks": $('Agent').item.json.output.blocks } }}。参见 n8n-node-configuration 中的 references/COMMS_NODES.md “Block Kit messages” |