)
1. 为什么我要把 AI 早报做成 N8N 自动化工作流每天手动刷十几个 AI 资讯站点复制标题、读正文、写摘要、排版、发邮件一套下来四十分钟起步。坚持三天还行一周之后必然摆烂。我试过用浏览器书签加稍后读结果稍后读变成了「永不读」。真正让我下决心改造的是发现这件事的每一步都能被拆成确定性动作定时触发、抓取 RSS、调用大模型摘要、拼装 HTML、发送邮件。既然都是确定性动作那就没有理由让人来做。这篇要聊的就是把这条链路完整落到 N8N 上用 Schedule Trigger 每天定时跑用 HTTP Request 拉取多源 RSS用 Code 节点清洗数据再通过 TaoToken 统一 Key 调用全球大模型做摘要最后生成 HTML 日报推送到邮箱。核心检索词先摆出来——N8N 自动化工作流、AiOnly 全球大模型服务、大模型 API 统一接入、AI 资讯早报自动生成。适合谁看适合已经会用 Docker 起服务、想让 AI 帮自己干重复活的开发者也适合想把多模型能力接进内部工具的技术负责人。真正麻烦的地方不在 N8N 本身而在模型接入。早期我在工作流里硬编码了好几家平台的 KeyOpenAI 一个、Claude 一个、DeepSeek 一个每个平台的 Base URL、鉴权头、模型 ID 命名规则都不一样。改一次摘要模型要翻三个控制台。后来我把这些统一收敛到 TaoToken 的 OpenAI 兼容接口上一个 Base URL、一个 Key、一套模型 ID工作流里只改一个字符串就能换模型。下面按「问题场景 → 前置准备 → 可复制配置 → 验证请求 → 报错排查 → 后续接入」的顺序展开每一步都给到能直接粘贴的片段。2. TaoToken 统一 Key 前置准备与 AiOnly 模型接入先说清楚这一层要解决什么。N8N 的 HTTP Request 节点本质上只会发一个 POST 请求它不关心你后面接的是哪家模型。所以只要有一个「OpenAI 兼容」的入口N8N 就能无差别调用。TaoToken 提供的就是这个入口一个 Base URL 指向https://taotoken.net/api一个 API Key 完成鉴权模型 ID 用标准字符串指定。你不需要在 N8N 里为每家模型写不同的鉴权逻辑。前置准备分三件事拿到 Key、确认 Base URL、选定模型 ID。Key 在控制台的 API Keys 页面创建创建时给它起个能认出来的名字比如n8n-daily-brief方便以后按用途吊销。Base URL 固定为https://taotoken.net/api注意这里不带任何路径后缀OpenAI 兼容的/v1/chat/completions由 SDK 或请求体自己拼。模型 ID 建议先用一个便宜且稳定的做摘要比如deepseek-v3.2-exp这类文本模型摘要任务对推理深度要求不高稳定和低延迟更重要。这里有个容易踩的坑很多人把 Base URL 写成https://taotoken.net/api/v1然后在 N8N 里又拼一次/v1/chat/completions结果变成/api/v1/v1/chat/completions直接 404。记住一个原则——Base URL 只到/api路径由调用方补全。如果你用的是 OpenAI SDKbase_url填https://taotoken.net/apiSDK 会自动补/v1/chat/completions如果你在 N8N 里手写 HTTP Request那 URL 就要写全https://taotoken.net/api/v1/chat/completions。模型 ID 的获取方式有两种一种是在模型广场里浏览找到目标模型后复制它的 ID另一种是直接调/v1/models接口列出当前 Key 可用的模型。后者更适合写进自动化脚本因为模型上下线时你能第一时间感知。下面这段 curl 可以先在本地验证 Key 是否有效确认没问题再往 N8N 里搬。curl https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json返回体里会有一个data数组每个元素包含id字段那就是你可以直接填进 N8N 的模型 ID。如果这一步返回 401说明 Key 不对或者请求头格式错了如果返回 200 但data为空说明这个 Key 还没有被授权任何模型需要去控制台确认权限范围。把 Key 存进 N8N 的 Credentials 里不要硬编码在节点 JSON 中后面配置片段里我会用{{ $credentials.taotokenApiKey }}这种引用方式。3. 可复制的 N8N 工作流 JSON 与鉴权配置片段这一节是全文最干的部分直接给可导入的配置。N8N 的工作流可以整体导出为 JSON你也可以只复制单个节点的配置。我建议先导入完整工作流再按自己的邮箱和 Key 改两处。先看鉴权配置。N8N 里推荐用「Header Auth」类型的 Credential名字填TaoToken APIHeader Name 填AuthorizationHeader Value 填Bearer 你的Key。这样所有 HTTP Request 节点都能复用同一个 Credential换 Key 时只改一处。如果你更习惯在节点里直接写表达式那就用下面这种形式把 Key 放在环境变量里{ nodes: [ { parameters: { rule: { interval: [ { field: cronExpression, expression: 0 9 * * * } ] } }, name: Schedule Trigger, type: n8n-nodes-base.scheduleTrigger, typeVersion: 1.2, position: [220, 300] }, { parameters: { url: https://api.rss2json.com/v1/api.json, options: { response: { response: { fullResponse: false } } }, sendQuery: true, queryParameters: { parameters: [ { name: rss_url, value: https://36kr.com/feed }, { name: count, value: 10 } ] } }, name: Fetch RSS, type: n8n-nodes-base.httpRequest, typeVersion: 4.2, position: [440, 300] }, { parameters: { jsCode: const data $input.first().json;\nif (data.status ! ok) {\n throw new Error(RSS 获取失败: data.message);\n}\nreturn data.items.map(item ({\n json: {\n title: item.title,\n link: item.link,\n contentSnippet: item.description.replace(/[^]*/g, ).substring(0, 300),\n pubDate: item.pubDate,\n author: item.author || 未知\n }\n})); }, name: Parse RSS, type: n8n-nodes-base.code, typeVersion: 2, position: [660, 300] }, { parameters: { method: POST, url: https://taotoken.net/api/v1/chat/completions, sendHeaders: true, headerParameters: { parameters: [ { name: Authorization, value: Bearer {{ $env.TAOTOKEN_API_KEY }} }, { name: Content-Type, value: application/json } ] }, sendBody: true, specifyBody: json, jsonBody: {{ JSON.stringify({ model: deepseek-v3.2-exp, messages: [{ role: system, content: 你是科技资讯摘要助手用一到两句话总结核心要点。 }, { role: user, content: 标题 $json.title \\n内容 $json.contentSnippet }], temperature: 0.3, max_tokens: 150 }) }}, options: {} }, name: Summarize via TaoToken, type: n8n-nodes-base.httpRequest, typeVersion: 4.2, position: [880, 300] } ], connections: { Schedule Trigger: { main: [[{ node: Fetch RSS, type: main, index: 0 }]] }, Fetch RSS: { main: [[{ node: Parse RSS, type: main, index: 0 }]] }, Parse RSS: { main: [[{ node: Summarize via TaoToken, type: main, index: 0 }]] } } }这段 JSON 里有三个关键点。第一Schedule Trigger用的是 cron 表达式0 9 * * *意思是每天 9 点触发你可以改成任意时间。第二Summarize via TaoToken节点的 URL 是完整的https://taotoken.net/api/v1/chat/completions因为这里是手写 HTTP Request路径必须补全。第三鉴权头用的是$env.TAOTOKEN_API_KEY所以你要在 N8N 的容器环境变量里注入这个值而不是把 Key 写死在 JSON 里。如果你用的是 Docker 部署 N8N环境变量这样加services: n8n: image: n8nio/n8n ports: - 5678:5678 environment: - N8N_BASIC_AUTH_ACTIVEtrue - N8N_BASIC_AUTH_USERadmin - N8N_BASIC_AUTH_PASSWORDchange_me - TAOTOKEN_API_KEYsk-你的实际Key volumes: - n8n_data:/home/node/.n8n volumes: n8n_data:注意TAOTOKEN_API_KEY这个变量名要和 JSON 里的$env.TAOTOKEN_API_KEY完全一致大小写敏感。改完 compose 文件后docker compose up -d重建容器环境变量才会生效。如果你不想用环境变量也可以在 N8N 的 Credentials 里建一个 Header Auth然后在节点里引用两种方式都行选一种坚持用就好。4. 手动触发验证摘要与推送是否成功配置导入之后不要急着等定时触发先手动跑一次把每个节点的输出看清楚。手动触发的方式是打开工作流点右上角的「Execute Workflow」按钮N8N 会从 Schedule Trigger 开始逐节点执行。执行完成后每个节点下方会显示绿色对勾和输出条数点开就能看到实际数据。第一步验证Fetch RSS节点。点开它的输出应该能看到一个items数组长度等于你设置的count。如果items为空说明 RSS 源本身没有返回内容换一个源试试比如把rss_url换成https://www.ithome.com/rss/。如果返回体里status不是okParse RSS节点会直接抛错错误信息里会带上message字段照着改就行。第二步验证Summarize via TaoToken节点。这是最容易出问题的一步因为涉及网络请求和鉴权。点开输出正常应该看到choices[0].message.content里有中文摘要。如果看到的是401说明 Key 没生效检查环境变量是否注入成功可以在 N8N 容器里执行printenv | grep TAOTOKEN确认。如果看到404八成是 URL 拼错了确认是不是写成了/api/v1/v1/chat/completions。如果看到429说明触发了限流把max_tokens调小或者加个 Wait 节点错峰。第三步验证摘要内容质量。deepseek-v3.2-exp在temperature: 0.3下输出比较稳定但偶尔会把标题原样复述。如果你发现摘要太啰嗦把 system prompt 改成「用一句话总结不超过 40 字」同时把max_tokens压到 80。如果你发现摘要太干缺少关键信息把contentSnippet的截断长度从 300 提到 500给模型更多上下文。第四步验证推送。如果你接了 Send Email 节点手动执行后去收件箱看有没有收到 HTML 邮件。163 邮箱的 SMTP 授权码不是登录密码要去设置里单独开启 POP3/SMTP 服务后生成。QQ 邮箱类似在账户设置里生成授权码。Gmail 需要先开两步验证再生成应用专用密码。邮件没收到先看垃圾箱再看 N8N 执行日志里 Send Email 节点有没有报EAUTH错误那通常是授权码填错了。手动跑通之后把工作流右上角的 Active 开关打开它才会按 cron 定时执行。建议第一次开启后第二天早上检查一下执行历史N8N 会记录每次执行的成败和耗时方便你判断是否需要调整触发时间。5. 本篇常见报错排查401、local proxy failed 与 reading choices这一节把我在搭建过程中真实撞到的报错列出来对照着改能省不少时间。401 Unauthorized。这是最高频的报错原因通常有三个Key 本身无效、请求头格式不对、环境变量没注入。先确认 Key 在本地 curl 能通再确认 N8N 里 Header 是Authorization: Bearer sk-xxx注意Bearer和 Key 之间有一个空格。如果用的是环境变量进容器printenv看一眼很多时候是 compose 文件改了但没重建容器。local proxy failed / connection refused。这个报错说明 N8N 容器发不出请求通常是容器网络配置问题。如果你在 compose 里给 N8N 配了HTTP_PROXY之类的变量先去掉再试。如果 N8N 跑在受限网络里确认它能解析taotoken.net这个域名可以在容器里curl -I https://taotoken.net/api/v1/models测一下连通性。注意这里说的是容器自身的网络出口配置不是让你去搞什么特殊通道正常云主机和本地 Docker 都能直连。Cannot read properties of undefined (reading choices)。这个报错说明 HTTP Request 节点返回的 JSON 里没有choices字段但你后面的 Code 节点直接取了choices[0]。原因可能是请求失败返回了错误体也可能是返回结构和你预期的不一样。排查方法是在 Code 节点前加一个「IF」节点判断$json.choices是否存在不存在就输出原始响应体方便定位。更稳妥的做法是在 Code 节点里写防御性代码const res $input.first().json; if (!res.choices || !res.choices[0]) { throw new Error(模型返回异常: JSON.stringify(res).substring(0, 200)); } return { json: { summary: res.choices[0].message.content.trim() } };OAuth / token expired。如果你用的是某些需要 OAuth 的模型服务可能会遇到 token 过期。但走 TaoToken 的 API Key 模式不存在这个问题Key 长期有效除非你主动吊销。如果你看到 OAuth 相关报错先确认自己是不是误用了别的鉴权方式把 Header 改回Authorization: Bearer即可。模型 ID 不存在。报错信息通常是model not found。这时候去调/v1/models列出可用模型确认你填的 ID 在列表里。注意模型 ID 大小写敏感deepseek-v3.2-exp和DeepSeek-V3.2-Exp可能不是同一个。复制的时候别手打直接从返回体里拷。邮件发送成功但内容为空。这通常是 HTML 模板里的变量引用错了。检查 Send Email 节点的 HTML 字段是不是{{ $json.html }}而生成 HTML 的 Code 节点确实返回了html字段。如果中间经过了 Loop 节点注意$json指向的是当前循环项不是全局数据需要用$(节点名).item.json来取。6. 从早报工作流延伸到长期编码与 Agent 场景早报工作流跑通之后你会发现这套模式可以复用到很多地方。核心结构是「定时触发 → 数据抓取 → 模型处理 → 结果分发」把中间的模型处理换掉就能变成代码审查摘要、竞品动态监控、工单自动分类。而这一切的前提是模型接入层足够简单——一个 Base URL、一个 Key、一套模型 ID换模型只改一个字符串。如果你打算把这类工作流长期跑下去建议把模型调用从单次 HTTP Request 升级成更结构化的方式。比如在 N8N 里封装一个子工作流专门负责「调模型」输入是 prompt 和模型 ID输出是文本主工作流只负责编排。这样以后换模型、加重试、加缓存都只改子工作流一处。模型 ID 也可以做成参数早报用便宜模型代码审查用推理更强的模型按场景切换。对于需要长期编码辅助或 Agent 编排的场景单次 API 调用就不够用了需要考虑额度、并发和模型切换策略。这类需求可以看 Coding Plan 相关的方案它更适合持续性的开发工作流而不是一次性的摘要任务。如果你只是想先验证模型对话效果可以直接在模型对话页面里试几个 prompt确认输出风格符合预期再写进工作流。接入文档里有完整的鉴权和参数说明遇到本文没覆盖的报错可以去那里对照。API Keys 页面用来创建和管理 Key建议给每个工作流单独建一个 Key方便按用途追踪用量和吊销。把 Key 管好、把 Base URL 记牢、把模型 ID 存成变量这套早报工作流就能稳定跑下去每天早上九点准时把摘要送到你邮箱。