⚠️ 本記事は Jev の実運用結果ではなく、n8n へ組み込む際の設計検証記事です。
OpenRouter / Cloudflare Workers AI / TypeSafe 直 API への接続試行を行いましたが、2026-09-19 時点では成功レスポンスを取得できていません(認証・資格情報未配置)。それでも 差し込み位置・質問設計・confidence ゲートは n8n 実装のたたき台として使えます。n8n 本番ワークフローへの常時接続は未実施です。
2026-09-19|JevはLLMの代替ではない。「返信文を書くAI」ではなく、LLMを呼ぶべきか・人間に回すべきかを決める前段レイヤーとして効く。n8nのSwitch/IFをJev(Choice / Score / Noul + confidence)に置き換えると、問い合わせ分類やSNS投稿承認の判断コストを下げつつ、確信度が低いときだけLLM再判定やTelegram承認にフォールバックできる。
結論
JevはLLMの置き換えではなく、LLMの前段・後段に置く判断レイヤーとして効く。n8nのSwitch/IFでキーワード分岐している箇所を、Choice・Score・Noul+confidenceのゲートに差し替えると、「分類だけ安く速く」「確信度が低いときだけ人間 or LLM」という実務向きの形になる。
| 論点 | 設計の要点 |
|---|---|
| 差し込み位置 | Webhook受信直後。生成(返信文・投稿文)は後段のLLMノードに任せる |
| 1リクエストで聞くこと |
category(Choice)・urgency(Score 1–5)・needs_reply(Noul)を同時に投げる(公式は並列評価) |
| 分岐の軸 | 答え(choice / score / noul)+ 確信度(Choice/Scoreのconfidence)。Noulは確率そのものが信号 |
| 実装の正本 | TypeSafe POST /v1/systemone(API reference)。n8n からは Cloudflare Workers AI typesafe/jev や OpenRouter Decisions も選択肢 |
| コスト感(公開価格) | 入力 $0.042 / 1M tokens、出力 $0(Vercel AI Gateway: Jev、OpenRouter: jev-1.13) |
| 本記事の検証度 | 設計検証+API実測試行(2026-09-19)。Jev の成功レスポンスは未取得。n8n 本番常時接続は未 |
既にQiitaには「Jevとは」「LLMとの違い」「速度比較」系が並んでいる(例:Jevってなんだ?、みんなの使い方調査)。本記事はn8nの業務フローにどこを差し替えるかと、確信度ゲート付きの分岐表に絞る。
なぜn8nのIFをJevにするのか
問い合わせ自動化やSNS自動投稿では、だいたい次の流れになる。
[フォーム / メール / Webhook]
→ 分類(営業?請求?スパム?)
→ 緊急度
→ 返信が要るか
→ (要るなら)FAQ検索 or LLMで下書き
→ 人間承認(Telegram ✅)
→ 送信
キーワードIFは安いが、言い回しの揺れと否定(「返金は要らない」等)に弱い。LLM分類は柔らかいが、毎回JSONを生成・パースするコストと、想定外フィールドの防御コードが乗る。
TypeSafeの説明では、Jevは文章生成ではなく型付きの判断を返す System One モデルで、複数質問を1回にまとめてもコンテキストが腐りにくい(Introduction)。Intent routing パターンも公式にある(Intent routing)。
つまり n8n では 「Switchの中身をHTTP Request + Codeにする」 のが自然。
SNS投稿前のAI判定(X/note・Telegram承認ゲート)
自分の運用で差が出やすいのは、問い合わせより SNS自動投稿の公開直前 だ。生成(LLM)は別ノードのまま、出す/止める/人間に回すだけをJevに任せる。
[LLM: 投稿文案生成]
│
▼
[HTTP Request: Jev — post_verdict]
│
▼
[Code: confidence ゲート]
│
├─ ok + HIGH conf ─→ [X/note 投稿ノード]
├─ review / MEDIUM ─→ [Telegram: ✅承認待ち]
└─ block / LOW ─→ [キュー停止・ログ]
post_verdict の Choice 例(state に生成済み文案を渡す):
"post_verdict": {
"type": "choice",
"instructions": "この文案をそのまま公開してよいか",
"criteria": {
"ok": "問題なし・通常の告知",
"review": "誤解・強い断定・競合言及があり人間確認が妥当",
"block": "炎上・法務・差別・個人情報の懸念"
}
}
post_verdict.choice === 'ok' かつ confidence >= 0.9 のときだけ投稿ノードへ。それ以外は Telegram 承認ゲート(下書き: cloudflare-workers-telegram-approval-gate.md)に合流させる。炎上リスクは「生成の質」より 公開ゲート の問題なので、n8n × 承認WFと相性が良い。
全体アーキテクチャ(問い合わせ triage)
[Webhook: 問い合わせ受信]
│
▼
[Set: state 文字列を整形]
│
▼
[HTTP Request: Jev systemone]
│
▼
[Code: route_by_confidence]
│
├─ HIGH ─→ [Switch: category] ─→ 定型処理 / スプレッドシート / 低コスト自動
│
├─ MEDIUM ─→ [LLM: 再判定 or 下書き生成] ─→ [Telegram: 承認待ち]
│
└─ LOW ─→ [Telegram: 人間キュー](ラベルだけ付けて終了でも可)
問い合わせ側も、上記SNSと同じ 「Jev → 確信度ゲート → LLM/人間」 の型に揃える。
Jevに投げる質問設計(コピペ用ペイロード)
state は問い合わせ本文(件名+本文を連結で十分)。model はピン留めするなら jev-1.13 相当(OpenRouterは typesafe/jev-1.13、モデル一覧)。
{
"state": "{{ $json.body.message }}",
"model": "jev-latest",
"questions": {
"category": {
"type": "choice",
"instructions": "この問い合わせを担当チームに振り分ける",
"criteria": {
"sales": "見積・導入・機能の質問・デモ希望",
"support": "使い方・障害・設定・バグ報告",
"billing": "請求・支払い・プラン変更・返金",
"spam": "営業メール・無関係・スパム",
"other": "上記に当てはまらない"
}
},
"urgency": {
"type": "score",
"instructions": "対応の緊急度(1=低、5=高)",
"criteria": [
"1: 情報提供のみ・急ぎではない",
"2: 数日以内でよい",
"3: 通常の業務影響",
"4: 本日中の対応が望ましい",
"5: サービス停止・金銭・法務に直結"
]
},
"needs_reply": {
"type": "noul",
"instructions": "担当者からの返信が必要か",
"criteria": {
"true": "質問・依頼・不満・確認が必要",
"false": "通知のみ・お礼・返信不要が明示"
}
}
}
}
Scoreの返り値はレベル番号の確率加重平均(例: 1.6)なので、n8n側では Math.round(score) か、レベルごとの probabilities を見る(Score primitive)。
n8nノード設定
1. HTTP Request(TypeSafe 直)
| 項目 | 値 |
|---|---|
| Method | POST |
| URL | https://api.typesafe.ai/v1/systemone |
| Authentication | Header Auth:Authorization: Bearer <TYPESAFE_API_KEY>
|
| Body | JSON(上記ペイロード。state は式で差し込み) |
2. HTTP Request(OpenRouter Decisions API)
Jevはチャット補完ではなく Decisions API(state + questions)で叩く(OpenRouter: Submit Decisions)。
| 項目 | 値 |
|---|---|
| Method | POST |
| URL | https://openrouter.ai/api/alpha/decisions |
| Authentication | Header Auth:Authorization: Bearer <OPENROUTER_API_KEY>
|
| Body | TypeSafe と同形の JSON(model / state / questions) |
| モデル例 |
typesafe/jev-1.13 または ~typesafe/jev-latest(OpenRouter) |
n8n では TypeSafe 直 (/v1/systemone) と OpenRouter のどちらを使うかを Credentials で分ける。ペイロード形状は同じで、本稿の正本は TypeSafe ドキュメント、実運用で Waitlist を避けるなら OpenRouter 経由が現実的。
3. Cloudflare Workers AI(未検証)
執筆時点では Cloudflare 経由のリクエストは未送信。 以下は 公式ドキュメント に沿った n8n 直叩きの設定例のみ。
REST から叩く場合:
| 項目 | 値 |
|---|---|
| Method | POST |
| URL | https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/run |
| Authentication | Header Auth:Authorization: Bearer <CLOUDFLARE_API_TOKEN>
|
| Body | JSON:{ "model": "typesafe/jev", "input": { "state": "...", "questions": { ... } } }
|
Workers 内なら env.AI.run('typesafe/jev', { state, questions }) と同形。プロキシ Worker を挟む構成も可。
4. Code ノード:確信度ゲート(机上ロジック)
Jevレスポンスを items[0].json にある想定。閾値は最初は保守的に。公式も「操作の危険度で変える」としている(Confidence)。
const ans = $input.first().json.answers;
const cat = ans.category;
const urg = ans.urgency;
const reply = ans.needs_reply;
// 閾値(要チューニング・未実測)
const HIGH = 0.85;
const LOW = 0.55;
function band(confidence) {
if (confidence >= HIGH) return 'high';
if (confidence >= LOW) return 'medium';
return 'low';
}
const categoryBand = band(cat.confidence);
// urgency も Choice 同様 confidence あり
const urgencyBand = band(urg.confidence);
// Noul: 0.5 から離れているほどはっきり
const replyStrength = Math.abs(reply.noul - 0.5) * 2; // 0..1 の粗い指標
let route = 'human';
if (categoryBand === 'high' && urgencyBand !== 'low') {
route = 'auto';
} else if (categoryBand === 'low' || urgencyBand === 'low') {
route = 'human';
} else {
route = 'llm_review';
}
return [{
json: {
route,
category: cat.choice,
category_confidence: cat.confidence,
category_probabilities: cat.probabilities,
urgency_score: urg.score,
urgency_confidence: urg.confidence,
needs_reply: reply.noul >= 0.5,
needs_reply_noul: reply.noul,
reply_strength: replyStrength,
raw: $input.first().json,
},
}];
その後 Switch で route === auto | llm_review | human を分岐する。
擬似データでの分岐イメージ(APIレスポンス未取得)
OpenRouter への接続試行は 2026-09-19 に HTTP 401(詳細は次節)。以下は公式ドキュメントのレスポンス形状に沿った架空の3ケースで、n8n 分岐表のイメージだけ示す。
※以下の confidence 値は説明用の架空値です。
| # | 問い合わせ(要約) | category / conf | urgency / conf | needs_reply (noul) | 想定 route |
|---|---|---|---|---|---|
| A | 「請求書の宛名が違う。今月中に直したい」 | billing / 0.91 | 3.2 / 0.88 | 0.93 | auto → 請求ラベル+テンプレ通知 |
| B | 「解約したのに引き落としがある。返金は不要、確認だけ」 | billing / 0.72 | 4.1 / 0.65 | 0.81 | llm_review(否定・引用の取りこぼし注意) |
| C | 「資料請求の件で、御社のAI製品を代理販売しませんか」 | spam / 0.48 | 1.0 / 0.52 | 0.12 | human(confidence低) |
Bのような文は、第三者の日本語検証でも「否定や間接表現でズレる」例が報告されている(Zenn: 48回試した)。自動返金・自動投稿には HIGH 閾値+人間ゲートが前提。
LLM分類 vs Jev判断レイヤー(概念+公開情報)
| 観点 | LLM(分類プロンプト) | Jev(System One) |
|---|---|---|
| 出力 | 自由テキスト → JSON化 | 型付き choice / score / noul(スキーマ外は出ない) |
| 確信度 | 自前で logprobs 等を設計 | Choice/Score に confidence(Confidence) |
| レイテンシ | 用途依存(生成トークン分) | 第三者実測: 日本語16文×3問で中央値 286ms(同上Zenn)※本記事未再現 |
| コスト(公開価格) | モデルにより入力+出力課金 | 入力 $0.042/1M、出力 $0(上記 Gateway / OpenRouter) |
| JSONパース | 必須・リトライ設計が要る | 不要(HTTP JSONをそのまま分岐) |
| 想定外ラベル | プロンプト逸脱で起きうる | Choiceは定義済み criteria 内(other を足すのが実務的) |
| 曖昧入力 | それっぽいJSONを返すことがある |
confidence 低下+Noulが0.5付近 → human へ |
| 説明文生成 | 向いている | 向かない(生成は後段LLM) |
発表ブログでは LLM 比較の注記(ルーティングバイアス・スキーマ一致は保証等)もある(Introducing Jev)。自社案件で使うときは自分の文面セットで閾値を再校正する。
API接続試行ログ(2026-09-19)
| 項目 | 内容 |
|---|---|
| データセット | 問い合わせ分類 10件 + SNS post_verdict 10件(自作短文・計20リクエスト) |
| 再現スクリプト |
~/qiita-backup/ops/jev-bench-2026-09-19.py(--provider cloudflare / openrouter / typesafe) |
| 優先経路(方針) |
Cloudflare Workers AI typesafe/jev → 取得できなければ設計検証として公開 |
試行履歴(捏造なし)
| 日時(UTC) | 経路 | 結果 |
|---|---|---|
| 2026-09-18T23:57Z | OpenRouter Decisions | 20/20 401(キー未設定/無効) |
| 2026-09-19T12:22Z | OpenRouter / TypeSafe 直 | 401(OpenAI 系キーは Jev 経路と非互換) |
| 2026-09-19T13:56Z | Cloudflare Workers AI |
未実行 — 端末に CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN(CF_* 可)が未配置 |
OpenRouter は都合により優先せず、再現手順の正は Cloudflare(公式)。TypeSafe 直 API の Waitlist はキャンペーン優先で待たない — 必要なら typesafe.ai から後日申請。
cd ~/qiita-backup
export CLOUDFLARE_ACCOUNT_ID=...
export CLOUDFLARE_API_TOKEN=...
python3 ops/jev-bench-2026-09-19.py --provider cloudflare \
--out ops/jev-bench-2026-09-19-result.json
| 指標 | 問い合わせ10件 | SNS判定10件 | 備考 |
|---|---|---|---|
| 成功率 | 未取得 | 未取得 | CF 資格情報未配置 |
| レイテンシ中央値 | 未取得 | 未取得 | 第三者引用 286ms(Zenn)※未再現 |
| 正解率 | 未取得 | 未取得 | accuracy_vs_gold |
confidence 中央値 |
未取得 | 未取得 | Choice のみ |
| コスト | 未取得 | 未取得 | CF usage / ダッシュボード |
実装チェックリスト
-
categoryにotherとspamを入れ、想定外を「無理やり最寄り」にしない - 自動実行する枝(返金・投稿・メール送信)ごとに 別の confidence 閾値を持つ
- MEDIUM は LLM に「Jevの候補と確率」を渡し、再判定だけさせる(全文生成はまだしない)
-
LOW は人間キュー。Slack/Telegram に
probabilitiesを添えて判断を速くする - APIキーは n8n Credentials のみ。記事・Gitに載せない
-
公開前
bash ops/confidentiality-scan.sh public/<basename>.md(qiita-backup 標準ゲート)
失敗パターン
パターン1: Jevを返信生成まで任せる
→ 向いていない。生成はLLM。Jevは triage とゲート。
パターン2: confidence 閾値を1つだけ
→ 請求ラベル付けと自動返金で同じ 0.8 など、事故りやすい。公式の voice banking 例のように操作別に変える。
パターン3: キーワードIFを全削除
→ スパムの明らかなパターンはルールの方が安い。ルール → Jev → LLM の段階が現実的。
パターン4: jev-latest のまま本番
→ モデル更新で分布が変わる。本番はバージョン固定(jev-1.13 等)を検討(Jev 1.13 jaggedness)。
参考リンク
- TypeSafe Docs: Introduction
- API reference(systemone)
- Confidence-gated routing
- Qiitaキャンペーン: 判断特化AI「Jev」で遊ぼう!(公開後に Qiita UI で「参加する」+公開設定でキャンペーン選択)
- Vercel AI Gateway: typesafe-ai/jev
- OpenRouter: ~typesafe/jev-latest
- Cloudflare Workers AI: typesafe/jev
この記事を書いた人✏️@YushiYamamoto
ITPRODX.com代表 / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。