自动化与脚本
在 n8n 中设计 AI Agent 时如何选对节点…
构建或修改 n8n LangChain AI 节点(Agent、LLM Chain、Text Classifier、Information Extractor)时,按此流程选型、接线、写提示词与工具描述并规避常见反模式。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 n8n 中设计 AI Agent 时特定
解决思路
- 先选对节点:需要调用工具、多轮推理或记忆用 AI Agent(`.agent`);一次性文本进文本出、无工具用 Basic LLM Chain(`.chainLlm`);把自然语言路由到 N 个分支之一用 Text Classifier(`.textClassifier`);从自由文本抽取结构化字段用 Information Extractor(`.informationExtractor`);三分类情感用 Sentiment Analysis(`.sentimentAnalysis`);长文档压缩用 Summarization Chain(`.chainSummarization`);生成图像/音频/视频用提供商的原生单次调用节点,绝不用 Agent 包裹。
- Text Classifier 的每个类别必须同时有 name 和 description,模型是按 description 路由的;设置 `options.enableAutoFixing: true` 增强鲁棒性;不要用 Agent + Switch 组合替代它。
- Chat 模型节点(`.lmChatOpenAi`、`.lmChatAnthropic`、`.lmChatOpenRouter` 等)是子节点,不能独立运行,必须通过 `ai_languageModel` 连接接入 chain、agent、classifier 或 extractor。
- 按子节点模式接线:Agent 有主输入(prompt/用户消息)和最多四个子节点槽位——model(`ai_languageModel`,必需)、memory(`ai_memory`,可选)、tools(`ai_tool`,可选)、outputParser(`ai_outputParser`,可选)。子节点从自身连向 Agent,连接写在子节点上并以 `ai_*` 类型为键。
- 多个工具都连到同一个 `ai_tool` index 0,它们会堆叠而不是分散到不同 index;用 `n8n_update_partial_workflow` 时每个工具用 `addConnection` 操作并设 `sourceOutput: "ai_tool"`。
- Agent 的最终答案在 `$json.output`(不是 `.text` 也不是 `.response`),下游节点用 `{{ $json.output }}` 读取。
- 把工具名和描述当作提示词的一部分来设计:模型只靠名字和描述选工具,`tool1` 加空描述等于对模型不可见,会跳过、误选或幻觉参数,且通常不报错。
- 结构化输出必须能解析且开启 autoFix:`outputParserStructured` 配 `autoFix: true` 和一个有编码能力的修复模型,否则一次畸形 JSON 就会中断整个工作流。
- 把每个工具的使用说明放进工具描述而不是系统提示词,这样工具可跨 Agent 复用、按需加载节省 token,且只需改一处。
- 多步骤逻辑优先用子工作流工具(`.toolWorkflow`):任何工作流都能变成带类型化 `$fromAI()` 输入的工具,并可与分支、错误处理、复用组合;拿不准时默认用它。
- 对有用户可见副作用的工具(发送、支付、退款、账户变更)加人工审核节点,让人在工具触发前签字确认。
- 提高 `maxIterations`:默认工具调用上限很低(多数版本是个位数),多工具 Agent 会报 "max iterations reached" 或输出为空;聚焦子 Agent 设 15,宽泛编排器设 50-200。
- 在系统提示词里用 `{{ $now }}`(或 `{{ $now.format('DDDD') }}`)放入当前日期,不要硬编码日期。
- 按最轻量原则选四种工具类型:原生工具节点(`slackTool`、`gmailTool`、`toolCalculator` 等)用于单一节点单一操作;子工作流工具(`.toolWorkflow`)用于多节点、可复用或需独立测试,拿不准时默认;HTTP Request Tool(`.toolHttpRequest`)用于单个外部 HTTP API;MCP Client Tool(`.mcpClientTool`)用于已有维护的 MCP 服务器。
- 写 Custom Code Tool(`.toolCode`)前先读 n8n-code-tool 技能了解其运行时契约(字符串进字符串出、无 `$fromAI`、无 `$helpers`);如果发现要在代码里用 `$fromAI()`,应改用 `.toolWorkflow`。
- 用 `$fromAI()` 让 Agent 填工具参数:`={{ $fromAI('paramName', '具体说明格式、范围、示例', 'string') }}`;paramName 是模型内部使用的名字(snake_case 或 camelCase,保持一致),description 是提示词的一部分要像 JSDoc 一样写,type 可选 `'string'`(默认)、`'number'`、`'boolean'`、`'json'`,defaultValue 可选。
- `$fromAI()` 只能传 JSON,不能传二进制(无 base64、无文件字节);身份、权限上限、关联 ID(`userId`、退款上限、`sessionId`)应从工作流上下文确定性注入,不要让 Agent 经手。
- 按系统提示词 vs 工具描述的分工来写:系统提示词放人设/角色/语气、全局输出格式规则、拒绝与安全行为、展示协议(如图片的 `![]()`)、通用上下文(`$now`、用户角色)、工具间流程;工具描述放该工具做什么、何时用与其他工具的区别、每个参数含义与形状、好坏调用示例、工具特有的坑(限流、边界情况)、工具特有的输入转换。
- 需要严格 JSON 时加 `outputParserStructured` 子节点(连 `ai_outputParser`):用 `schemaType: 'manual'` 配真实 JSON Schema,不要用 `jsonSchemaExample`(示例无法表达必填/可选、枚举、数值范围、数组约束);只有一次性形状才用 `fromJson` 加示例。
- 结构化输出配 `autoFix: true` 并给解析器接第二个有编码能力的模型到其 `ai_languageModel` 槽位,因为对账破损 JSON 是编码任务,弱修复模型只会再产出一个畸形重试并烧 token。
- 记忆用子节点(`ai_memory`):无记忆则每次调用无状态,适合一次性任务;有记忆则按绑定到 `sessionKey` 的表达式保存对话。`memoryBufferWindow` 保留每个 key 最近 N 轮并通过 n8n 存储跨执行持久化,是聊天默认,但 `contextWindowLength` 默认 5 太低,50 是更合理的起点,超出窗口的消息会彻底丢失。
- 只有记忆需要在 Agent 之外读取(自己的 UI、分析、跨系统)时才用 `memoryPostgresChat` / `memoryRedisChat`;仅为了跨重启存活不需要它们,BufferWindow 已能做到。
- 从触发器到记忆一致地注入稳定 key:聊天触发器自动填 `sessionId`,其他入口自行派生(Slack `thread_ts`、webhook 会话 ID);绝不硬编码 `sessionId: 'default'`,也绝不把 `sessionId` 放在 `$fromAI` 后面(模型会编造 UUID)。
- 处理二进制边界:模型可通过 Agent 的 `options.passthroughBinaryImages: true` 看到上传的图片(视觉);工具不能接收二进制,`$fromAI()` 只传 JSON;Agent 输出是文本形状,模型返回的图像/音频/视频字节不会浮现。变通做法是 Agent 运行前把上传预存到存储,把存储 key 注入系统提示词,让工具以字符串参数接收 key 并在内部重新取回;一次性媒体生成直接调提供商原生单次调用节点。
- 人工审核破坏性工具:用审核工具节点(`slackHitlTool`、`discordHitlTool`、`telegramHitlTool`、`gmailHitlTool` 等)包裹,审核节点在 `ai_tool` 连接上位于被包裹工具与 Agent 之间(被包裹工具 → 审核节点 → Agent);是否需要签字是产品/政策决定,应向用户提出并按其影响面给建议。
- 审核消息里必须展示被包裹工具实际将收到的参数,用字面量 `{{ $tool.parameters.<name> }}`,绝不用 `$fromAI()` 的转述,否则人批准的是模型编的文本而不是即将发出的调用。
- 聊天 Agent(Slack、Discord、Teams、Telegram)无论多简单都必须过滤掉机器人自己的用户 ID,否则自己的回复会再次触发它形成无限循环烧掉运行次数和 token;优先在触发器层过滤(Slack Trigger 的 `options.userIds` 是排除列表,把机器人 ID 放进去),否则在触发器后第一个节点过滤 `$json.user !== '<BOT_USER_ID>'`。
- 简单机器人(触发器 → Agent → 回复)可放在一个工作流里;只有需要加载 UX、子 Agent、多入口复用或健壮错误处理时才拆成 shell + core + sub-agents:shell 负责触发器、防循环过滤、事件类型 Switch、加载/错误 UX、渲染回复,不含 LLM;core 是无状态 Agent,输入 `chatInput` + `threadId`,记忆以 `threadId` 为键,含工具和子 Agent;sub-agents 每个只负责一个窄领域,通过 `.toolWorkflow` 调用且无状态(完整上下文放在 `chatInput`)。
- 区分持久化 n8n Agent 与 AI Agent 节点:工作流内带 `ai_*` 子节点的推理步骤用 AI Agent 节点;独立助手(有自己的生命周期——草稿、校验、发布、版本、渠道,独立于任何工作流)用 Persisted Agent(`n8n_manage_agents`)。
- 使用持久化 Agent 的前置条件:配置 `N8N_MCP_ACCESS_TOKEN`(与 Public API key 不同)且 n8n 2.34+ 并启用 agents 模块;该 token 对每个操作都必需,包括 `reference`/`search`;`reference` 和 `search` 对任何 Agent 都可用,其他操作需要目标 Agent 暴露给 MCP(通过此工具创建的 Agent 自动暴露)。
- 持久化 Agent 的构建顺序:先 `action: "reference"` 读配置 schema 和确切的 mutate 操作;再 `action: "discover_assets"` 列出可接线的资源(传 `projectId`(来自 `n8n_list_catalog({kind: "projects"})`)和 `kind`:`models`(带 `provider`)、`integrations`、`workflows`、`subagents` 或 `mcpServers`,每种 kind 一次调用);再 `action: "create"` 传 `projectId`、`name`、`config`;再 `action: "mutate"` 每次调用一个资源(`config.patch`、`skill.upsert`/`delete`、`task.upsert`/`delete`、`customTool.upsert`/`delete`),始终带上最新 hash(n8n 返回为 `configHash`,需以 `args.baseConfigHash` 传回;`args` 原样转发给 n8n,字段名稍有偏差会返回 `INVALID_ARGS`;hash 过期返回 `STALE_CONFIG`,需重新 `get` 后用新 hash 重试);再 `action: "validate"`;最后 `action: "publish"`,且仅在用户明确要求时发布,绝不主动发布。
- `action: "call"` 会用真实凭证和真实工具运行 Agent,是真实执行而非试运行;结果可能带 `approvals[]` 表示需要人工决定的工具调用,绝不代替用户批准,只呈现并在用户决定后恢复。
- 自定义工具是第三种代码运行时,不要复用另外两种:`customTool.upsert` 的 body 是 TypeScript,只允许 import `@n8n/agents` 和 `zod`;它既不是 Code 节点(JavaScript/Python,返回 `[{json: …}]`),也不是 n8n-code-tool 覆盖的 AI Agent Custom Code Tool(`@n8n/n8n-nodes-langchain.toolCode`,返回字符串,无 `$fromAI()`);写之前先从 `action: "reference"` 读形状,编译失败或未知 `agentId` 会返回 `AGENT_TOOL_ERROR`。
- 注意凭证限制:n8n 2.36.x 上 agents 运行时拒绝 `azureOpenAiApi` 和 `aws` 凭证(报 `missing: ["credential"]`),响应里的 `hint` 会给出可接受的类型。
- 测试不留垃圾:临时 Agent 命名为 `[TEST] …` 并在完成后 `delete`,因为持久化 Agent 比创建它的对话活得更久,不像工作流可以留着不激活。
- RAG 先排除更便宜的查询方式:精确查找用数据库或 Data Table 查询而非 RAG;新鲜度用实时搜索工具;小而结构化的文档集给 Agent 列表/获取工具;只有文档多到无法列举且查询是语义性时才用向量存储。
- 把向量存储接成检索工具(`mode: 'retrieve-as-tool'`、`ai_tool`),让 Agent 自己决定何时检索并自行组织查询;查询和文档必须用同一个模型做嵌入。
- 避免反模式:不要用泛化工具名(`tool1`、`doStuff`、`runQuery`),改用动词开头的具体名字(`Search customer database`、`Generate image with Veo`);不要空描述或一行描述;不要把每个工具的说明塞进系统提示词;不要用 Agent + Switch 做自然语言路由;不要用 Agent 包裹媒体生成;不要用没有 `autoFix` 的 `outputParserStructured`;不要把二进制直接传给工具;不要硬编码 `sessionId`、不给 sessionId 或把 sessionId 放在 `$fromAI` 后面;不要有两个几乎相同的工具(应合并为一个工具用参数内部分支);聊天机器人不要不加机器人用户过滤;多工具 Agent 不要把 `maxIterations` 留在低默认值;人工审核消息不要用 `$fromAI()` 填充。
- 发布前按清单自检:选对节点;model 通过 `ai_languageModel` 接线;每个工具有动词开头的具体名字和真实描述;`$fromAI()` 描述具体(格式、范围、示例)且身份/上限/sessionId 确定性注入;每个工具的指引在工具描述里;系统提示词含 `$now`;多工具 Agent 提高了 `maxIterations`;记忆以触发器来的稳定 `sessionKey` 为键且 `contextWindowLength` 从 5 提高;结构化输出用 `schemaType: 'manual'` + `autoFix: true` + 有编码能力的修复模型;破坏性工具包了人工审核且审批消息用 `$tool.parameters`;聊天机器人过滤了机器人自身用户 ID;二进制方面模型视觉用 `passthroughBinaryImages`、工具只拿存储 key;用 `validate_workflow` 校验并用 `n8n_get_workflow` 确认子节点接在 `ai_*` 而非 `main`。
- 了解社区 MCP 做不到的事:无法对工作流 AI Agent 节点做真正的多轮交互式聊天测试(那是 UI 的画布聊天测试器;持久化 Agent 可通过 `n8n_manage_agents` 的 `call` 实跑);无法设置凭证的真实密钥值(在 UI 输入/验证);无法分配工作流的 Error Workflow(仅 UI);无法钉住每个实例的确切模型可用性(用 `search_nodes`/`get_node` 反映已安装内容并在目标实例上核实)。
- MCP 能做的:用 `search_nodes`、`get_node` 搜索和检查每个 LangChain 节点;用 `validate_node`、`validate_workflow` 校验节点配置和整个图;用 `n8n_update_partial_workflow` 的 `addConnection` 在 `ai_*` 输出上构建和修补 Agent 及其子节点;用 `n8n_test_workflow` 测试;用 `n8n_get_workflow` 拉取保存的 JSON 验证接线;深度 AI Agent 指南在 `tools_documentation({topic: "ai_agents_guide", depth: "full"})`。
适用边界 · 注意事项
- 不使用 n8n 或不做 n8n LangChain AI 节点开发时(本技能针对 n8n 的 `@n8n/n8n-nodes-langchain.*` 节点体系)。
- 没有配置 `N8N_MCP_ACCESS_TOKEN` 或 n8n 版本低于 2.34 / 未启用 agents 模块时,不要尝试使用持久化 Agent(`n8n_manage_agents`),所有操作都会失败。
- 任务只是精确查找、需要新鲜度或文档集小而结构化时,不要上 RAG/向量存储,先用数据库查询、实时搜索工具或列表/获取工具。