给 n8n 工作流装成本账本:LLM 调用逐次计价实战

在每个 LLM 调用后写入一行成本记录,用日支出与自身中位数的比值告警,把月度账单盲盒变成每日可行动信号。
文章针对多工作流调用大模型时成本不可见的问题,提出一套轻量级成本账本方案。n8n 原生只按单次执行记录 token 用量,缺少按工作流的聚合与归因,导致提示词或重试策略的小改动可能悄悄使成本翻倍,却要等月底发票才能发现。方案在每个模型调用节点后接一个统一结构的 Cost 节点,把模型、token 数、美元成本和执行 id 写入 cost_log 表,价格表内嵌在节点中以避免拖慢工作流。每日定时查询计算各工作流当日支出与其 7 天中位数的比值,spike_ratio >= 2.0 即发 Slack 告警。一个真实案例中,放宽重试策略导致某工作流成本比值达 3.1,账本让作者次日早晨就收紧条件。账本只提供可见性,不解释原因,也不做精确核算;超大规模下可采样并同步调整告警分母。
当账单成为唯一线索
同时跑着十一个调用大模型的工作流,月底只收到一张 API 总账单,中间什么都没记录。作者的经历很有代表性:某次“优化”分类提示词之后,模型开销一夜翻了三倍,但直到三十天后收到发票才发现问题。

这不是个例。n8n 的执行日志确实记录了部分 AI 节点的 token 用量,但藏在单次运行的执行数据里,必须一条一条点开看。没有聚合、没有按节点归因、没有趋势线。发票告诉你总数,却没人告诉你分布。而分布恰恰是意外发生的地方——问题很少出在总量上涨,而是某个工作流在悄悄变贵。
作者的 inbox triage agent 就从每天 0.4 美元慢慢爬到了 1.3 美元。原因:所谓“改进”后的分类提示词变长了 2.4 倍,还为“边界情况”加了第二次模型调用。工作流运行正常,只是正常得很贵。
账本设计:每次 LLM 调用后接一个 Cost 节点
核心设计刻意做得无聊:每一个调用模型的节点——OpenAI 节点、Anthropic 节点,或者指向推理端点的 HTTP 请求——后面都紧跟着一个 Cost 节点。它是一个结构统一的 Code 节点,每次调用写入一行记录:
// Cost node: append one row per LLM call
const call = $input.first().json;
const PRICE = {
'gpt-4o-mini': { in: 0.15, out: 0.60 }, // USD per 1M tokens
'gpt-4o': { in: 2.50, out: 10.00 },
'claude-3-5-sonnet': { in: 3.00, out: 15.00 },
'claude-3-5-haiku': { in: 0.80, out: 4.00 },
};
const p = PRICE[call.model];
const row = {
run_id: $execution.id, // n8n execution id
event_id: call.event_id, // my own correlation key
workflow: $workflow.name,
node: call.node_name,
model: call.model,
in_tokens: call.usage.prompt_tokens,
out_tokens: call.usage.completion_tokens,
usd: (call.usage.prompt_tokens * p.in +
call.usage.completion_tokens * p.out) / 1e6,
ts: new Date().toISOString()
};
// insert into cost_log (run_id, event_id, workflow, node, model, in_tokens, out_tokens, usd, ts)
有三个关键细节:
价格表放在节点里,不放在配置里。 价格变动很少,改一次共享的 Code 片段就行(它被做成一个共享子工作流,到处导入)。作者不想在模型调用和日志写入之间插入一次数据库查询——账本绝不能拖慢或中断它所观察的工作流。
记录的是真实的模型调用,而不是估算。 token 数量来自 API 响应的 usage 字段,不是数提示词里的词。如果某个提供商不返回 usage(有些代理端点就不返回),节点会写入 in_tokens: null 并打上 usd_estimated 标记,估算行永远不会进入告警查询,只进仪表盘。
每个 AI 工作流都得配一个,没有例外。 那些“几乎不调用模型”的工作流,恰恰是改一次提示词就悄悄让 token 数量翻倍的典型。
n8n 是一个开源的工作流自动化平台,通过可视化节点连接的方式编排任务,并支持条件分支、循环、重试等控制流。在 AI 场景中,它可以调用 OpenAI、Anthropic 等节点,或通过 HTTP Request 节点访问任意推理端点。每个工作流的一次运行称为一个 execution,n8n 会为其分配一个 execution id,并记录每个节点的输入输出。本文的 Cost 节点正是利用 $execution.id、$workflow.name 等内置变量,把调用上下文与成本行绑定在一起。由于 n8n 原生的执行日志只按单次运行存储 token 用量,无法跨运行聚合,所以需要把数据外写到数据库表 cost_log 中,才能做按工作流的趋势与异常分析。
每日查询:和自己的中位数比
一个定时工作流每天 07:00 运行以下查询,把结果发到 Slack:
-- daily spend per workflow, vs its own 7-day median
WITH daily AS (
SELECT workflow, DATE(ts) AS d, SUM(usd) AS spend
FROM cost_log WHERE ts >= NOW() - INTERVAL 14 DAY
GROUP BY workflow, DATE(ts)
),
medians AS (
SELECT workflow, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY spend) AS med
FROM daily WHERE d < CURRENT_DATE GROUP BY workflow
)
SELECT d.workflow, d.spend, m.med,
ROUND(d.spend / NULLIF(m.med, 0), 2) AS spike_ratio
FROM daily d JOIN medians m ON d.workflow = m.workflow
WHERE d.d = CURRENT_DATE - 1;
告警规则只有一行:spike_ratio >= 2.0 就发 Slack 告警,附带工作流名称和昨日支出。
注意比的不是总支出,而是跟自己中位数的比值。一个平时 0.3 美元、突然变成 0.9 美元的工作流,和一个平时 30 美元、突然变成 90 美元的工作流,是同一类问题——都意味着有东西变了,但没人审查过。
早晨的摘要是一张表,不是图表:工作流、昨日支出、7 天中位数、比值。作者配着咖啡三十秒读完。图表留给季度回顾,表格留给周二早上。
PERCENTILE_CONT(0.5) 是 SQL 标准中的连续百分位函数,0.5 即中位数。与平均值相比,中位数对极端值不敏感:如果某天工作流因异常重试而支出飙升,平均值会被拉高,导致后续告警阈值失真;中位数则能稳定代表“典型日”的支出水平。查询中 WITHIN GROUP (ORDER BY spend) 指定排序依据,配合 GROUP BY workflow 为每个工作流单独计算。此外,WHERE d < CURRENT_DATE 排除了当天数据,避免不完整的当日支出拉低基线;限定 14 天窗口则是在样本量与时效性之间取平衡,既能容纳周末波动,又能跟上近期的使用模式变化。
一次让整套系统回本的告警
接好账本两周后,告警在 repurposing 工作流上触发:spike_ratio 为 3.1,当日 2.10 美元,中位数 0.68 美元。
原因是前一天改的重试策略——把重试范围放宽到了更大一类失败。更宽的重试意味着工作流会在原本直接终止的失败上,重跑它最贵的两次模型调用。这个重试改动对可靠性来说是正确的,但它同时悄悄地带来了 3 倍的成本变化。
没有账本,这件事要等下个月发票才能知道;有了账本,作者是在喝咖啡时发现,当天早上就收紧了重试条件。
这就是整个价值主张:账本不降低成本,它把“发票涨了”(月度、无法行动)转换成“这个工作流昨天行为变了”(每日、可行动)。成本控制来自可见性,而可见性就是账本做的全部事情。
在自动化工作流中,重试策略通常指定“当某类错误发生时,自动重新执行失败节点”。把重试范围从窄集合放宽到更大一类失败,会显著提高重试次数。如果失败发生在调用大模型之后,重试往往需要重新执行该调用,而大模型调用按 token 计费,因此每一次额外重试都意味着真实的美元成本。特别是当失败发生在工作流的后半段时,重试可能需要重跑前面最贵的两次调用,成本会成倍叠加。这种“为了可靠性而放宽重试”的改动,在功能测试中通常不会暴露成本问题,因为测试很少覆盖高频失败场景。只有按工作流维度、对比历史中位数的成本账本,才能把这类隐性成本变化转化为可行动告警。
账本不能做什么
它不是精确核算。来自 usage 的 token 数量是精确的,但价格表是一个快照,会随提供商调价而漂移。账本回答的是“哪个工作流、大致多少、趋势朝哪走”——它是仪表盘,不是纳税申报单。
它不是提示词优化器。它永远不会告诉你某个工作流为什么变贵——重试那次事件,还是得靠人去读 diff。账本把搜索范围缩小到一个工作流、一天。诊断仍然是人的工作。
它也不是免费的:每次模型调用现在都要写一行数据库记录。以作者的量级,每天几百行,可以忽略。如果你每天要跑几百万次调用,就采样(记录百分之一,然后乘以倍数)。这个模式经得起采样,只要在告警规则的分母里带上采样率。
把成本变成可行动的信号
这套方案的启发不在于非要用 n8n,而在于一个更通用的思路:在模型调用和账单之间,必须存在一个观测层。 只靠供应商发票做成本管理,本质上是月度盲盒;而在每个调用点写一行结构化成本记录,就能把不可行动的账单转成每日可行动的异常。
对个人开发者和小团队来说,在自建 Agent 编排、自动化流水线时,值得在架构里预留一个类似的 Cost 节点位。它不需要复杂,几百行代码就够,但它能把“这个月怎么这么贵”变成“昨天这个工作流为什么变贵了”。
相关推荐

花旗14000名工程师用Devin,技术外包账单砍掉30%
花旗集团14000名工程师使用AI编程智能体Devin,一年内将技术供应商账单削减30%,产品发布提速30-40%。但30%仅限单一成本项,摩根大通同期表示AI收益尚未体现在财报中,揭示企业AI落地的真实分化。

AI写代码,程序员要失业?Devin自主编程真相
Devin等自主AI编程代理正改变软件开发:从Copilot辅助编码到全自动工程代理,程序员角色从写代码转向系统设计与监督。本文分析AI编程对就业、代码安全、初级开发者培养的影响,以及效率悖论下程序员需求的真实走向。

AGENTS.md 实战指南:让编程 Agent 真正好用
AGENTS.md 和 CLAUDE.md 能显著提升编程 Agent 表现,但研究发现用错反而让成本上升 20%。本文详解该写什么、该删什么、200 行与 32KB 的硬边界、Monorepo 嵌套规则及安全提醒。