はじめに
n8n で LLM workflow を組むとき、最初から AI Agent node や専用 credential に寄せると、失敗したときの切り分けが少し重くなります。API key が違うのか、base URL が違うのか、model name が違うのか、node 側の設定なのかを同時に見ることになります。
今回は Flatkey AI の OpenAI 互換 endpoint を例に、n8n の HTTP Request node だけで chat/completions を叩きました。目的は、workflow に API key や model ID を直書きせず、最後に usage.total_tokens まで確認することです。かなり地味ですが、私はこの段階を飛ばすと後で迷いがちなので、検証メモとして残します。
3行まとめ
- HTTP Request node だけでも OpenAI 互換の
chat/completionsは確認できる - API key、base URL、model は workflow JSON に値を書かず、環境変数参照にした
- 成功時は
chat.completion、本文、usage.total_tokensを見ると次に進みやすい
環境
今回の確認環境です。n8n はローカル CLI で実行しました。UI で作る場合も考え方は同じですが、細かい表示名はバージョンで変わるかもしれません。
| 項目 | 値 |
|---|---|
| n8n | 2.27.4 |
| node | HTTP Request node + Code node |
| base URL | https://router.flatkey.ai/v1 |
| endpoint | /chat/completions |
| model | gpt-5.4-mini |
| response check | usage.total_tokens |
記事中の API key は出しません。workflow export 側にも実値は入れず、環境変数を参照する形にしました。
workflow に残す値と残さない値
今回の方針はこの表です。
| 種類 | workflow に残すか | 今回の扱い |
|---|---|---|
| API key | 残さない |
$env.FASTKEY_API_KEY 参照 |
| base URL | 実値を避ける |
$env.FLATKEY_BASE_URL 参照 |
| model ID | 実値を避ける |
$env.FLATKEY_MODEL 参照 |
| prompt | 残す | 検証用の固定文字列だけ |
| usage | 残す | token 数だけ summary node に出す |
実行時は次のように渡しました。環境変数名は自分の運用に合わせて変えてください。
export FLATKEY_BASE_URL="https://router.flatkey.ai/v1"
export FLATKEY_MODEL="gpt-5.4-mini"
export FASTKEY_API_KEY="sk-fk-..."
ここで大事なのは、workflow を export したときに key が混ざらないことです。model も変わりやすいので、私は最初から外に出しておく方が楽だと思います。
もう一つ意識したのは、後から workflow を見た人が「どの値を差し替えればよいか」をすぐ判断できることです。検証用 workflow でも、key だけ外に出して model を直書きしていると、別モデルで再確認したいときに JSON を編集する必要が出ます。n8n は画面で直しやすい反面、いつの間にか検証用の値が本番 workflow に残ることもありそうなので、最初から差し替え前提に寄せました。
HTTP Request node の中身
HTTP Request node は素朴に POST にしました。URL は base URL に /chat/completions を足します。
Method: POST
URL: ={{ $env.FLATKEY_BASE_URL + '/chat/completions' }}
Header Authorization: ={{ 'Bearer ' + $env.FASTKEY_API_KEY }}
Header Content-Type: application/json
Body Content Type: JSON
body はこうしました。
={{
{
model: $env.FLATKEY_MODEL,
messages: [
{ role: 'user', content: 'Return exactly n8n-flatkey-ok' }
],
temperature: 0,
max_completion_tokens: 16
}
}}
OpenAI 互換 API の設定記事でよく混ざるのは、base URL と endpoint URL だと思います。base URL には /v1 までを持たせ、HTTP Request node の URL で /chat/completions を足す、という分け方にしておくと読み返しやすいです。
n8n CLI で実行する
CLI では、workflow JSON を import してから ID 指定で実行しました。私の環境では --file は help に残っていましたが、実行時に --id has to be set になったため、素直に import する形にしました。
n8n import:workflow --input n8n_flatkey_chat_completions_smoke.workflow.json
n8n list:workflow
その後、ID を指定して実行します。
N8N_BLOCK_ENV_ACCESS_IN_NODE=false \
FLATKEY_BASE_URL="https://router.flatkey.ai/v1" \
FLATKEY_MODEL="gpt-5.4-mini" \
n8n execute --id qiitaIssue129Smoke --rawOutput
私のローカル CLI 実行では、最初に $env 参照が access to env vars denied で止まりました。自己ホスト環境で env 参照を使う場合は、n8n 側の環境変数アクセス設定を確認した方がよさそうです。n8n Cloud やチーム運用では、Credential や Variables を使う方が自然な場合もあると思います。
usage を見る
HTTP Request node の後ろに Code node を置き、必要な値だけ抜きました。全部の response をログに残すより、検証に必要な項目だけにしたかったからです。
const response = $input.first().json;
return [{
json: {
object: response.object,
model: response.model,
finish_reason: response.choices?.[0]?.finish_reason,
content: response.choices?.[0]?.message?.content,
usage_total_tokens: response.usage?.total_tokens,
usage_prompt_tokens: response.usage?.prompt_tokens,
usage_completion_tokens: response.usage?.completion_tokens,
},
}];
実行結果の抜粋です。
{
"object": "chat.completion",
"model": "gpt-5.4-mini",
"finish_reason": "stop",
"content": "n8n-flatkey-ok",
"usage_total_tokens": 24,
"usage_prompt_tokens": 14,
"usage_completion_tokens": 10
}
ここまで見えれば、少なくとも key、base URL、model、JSON body、非 stream の response 取得は通っています。次に AI Agent node や専用 credential に寄せるとしても、HTTP レイヤーの前提はかなり確認できた状態になります。
また、usage を小さく見るだけでも、課金や quota の話に進みやすくなります。本文そのものが返っているかだけを見ると、あとで「本当に token が計上されたのか」を別の画面で探すことになります。最小 workflow の段階で usage_total_tokens を残しておくと、n8n 側の実行ログと gateway 側の usage を突き合わせる入口になります。
ハマったところ
今回ハマったのは、n8n の workflow 自体より CLI 実行の周辺でした。
| 起きたこと | 対応 |
|---|---|
--file 実行が使えなかった |
workflow を import して execute --id にした |
| import 時に workflow id が必要だった | export JSON に top-level id を入れた |
$env が読めなかった |
N8N_BLOCK_ENV_ACCESS_IN_NODE=false を付けた |
特に $env の扱いは、環境によって方針が分かれそうです。検証用には便利ですが、チームで使う workflow なら n8n の credential store や Variables を使って、誰が見てもどこに secret があるかわかる形にした方が安全かもしれません。
まとめ
n8n から OpenAI 互換 chat/completions を呼ぶ最小確認は、HTTP Request node だけでもできました。
- workflow export に API key を入れない
- base URL と
/chat/completionsを分けて考える - model ID は外から渡し、変更しやすくする
- response は
contentとusage.total_tokensだけでもまず十分 - env 参照を使うなら n8n の実行環境側の制限を見る
Flatkey AI は OpenAI 互換の base URL と Bearer key で呼べるので、n8n の HTTP Request node からも同じ形で疎通できました。ただし、使える model name はアカウントや時期で変わるので、実運用では /models やダッシュボードで確認してから workflow に渡すのがよいと思います。
参考
- n8n HTTP Request node
- n8n CLI commands
- OpenAI Chat Completions API reference
- Flatkey AI
おわりに
最初は n8n の OpenAI 系 node から入ればよいかなと思っていたのですが、HTTP Request node で一回だけ薄く通すと、どこを信用して次に進めるかが見やすくなりました。私はこの手の検証で model name を普通に間違えるので、usage まで出る最小 workflow を残しておくのは意外と効きそうです。
UI や n8n の設定で違うところもあると思うので、間違いあったらコメントください。よろしくお願いします。