n8n-nodes-openrouter-token-telemetry
v0.2.0
Published
OpenRouter chat model for n8n that reports the full token usage the default node discards: cached input, billable input, reasoning tokens and cache hit ratio.
Maintainers
Readme
n8n-nodes-openrouter-token-telemetry
OpenRouter chat model para n8n com telemetria completa de tokens — irmão do
n8n-nodes-gemini-token-telemetry, para a era DeepSeek/OpenRouter do N1.
Por que existe
O node nativo (lmChatOpenRouter) entrega ao execution_data só
prompt/completion/total. O que se perde: cached_tokens, reasoning_tokens
e qualquer custo. Medido em 2026-09-21 com o prompt N1 v31 real (~25k
tokens): 84% das chamadas com 98,9% do prompt em cache, ~24x mais barato
por chamada — e nada disso aparecia na telemetria de fábrica.
Como resolve
Igual ao node Gemini: subclassa o modelo (ChatOpenAI do
@langchain/openai, apontado para https://openrouter.ai/api/v1) e
enriquece o llmOutput.tokenUsage dentro do _generate, lendo
generations[0].message.usage_metadata (que o LangChain preenche com
input_token_details.cache_read e output_token_details.reasoning, mas o
N8nLlmTracing destrói depois com o pick). Parser próprio copia os extras
para a saída persistida.
Campos que passam a existir
cacheReadTokens · inputTokensTotal · inputTokensBillable ·
cacheHitRatio · outputTokensVisible · reasoningTokens ·
reasoningDerived (false no caminho OpenRouter: o reasoning vem explícito) ·
outputTokensBillable · usageSource · cost* (só com preços no nó).
Session ID (o campo que mais importa)
Sem session_id, medimos 0% de hit — cada chamada pode cair num
provider diferente e o cache nunca esquenta. Com session_id estável por
conversa (ex.: o chat_id), 84%. O node envia como session_id top-level
(via modelKwargs, verificado na fonte do @langchain/openai instalado).
Vazio = omitido.
Custo
Preços só por parâmetro do nó (a OpenRouter tem overrides por horário; nada chumbado). Sem preço, sem campo de custo. Cache sem preço próprio cai no preço cheio (erra para cima, de propósito).
Guardas herdadas do node Gemini (não simplificar)
- Tudo em try/catch: require que lança em carga derruba o n8n no boot.
carrega()com resolução em 3 níveis (pacote → n8n rodando → store pnpm).Modelcomdefault: ""deliberado (gotcha 38).(tokens * preço) / 1e6, nunca(tokens / 1e6) * preço.- Cópia redundante em
generationInfo(gotcha 52).
