MCP ツールの「既知の失敗と回避策」を集める Failure KB に、判断特化 AI の Jev を組み込みました。Jev に任せたのは、投稿の振り分け、ツール呼び出しの観測、呼ぶ前の失敗の予知の 3 つです。前の 2 つは 2026 年 10 月 7 日から、予知は 10 月 9 日から本番で動いています。一方で、レコードを「検証済み」にする判断と、数字や日付の判定は任せていません。
この記事では、Jev を生成モデルの代わりではなく前後に置く判定層として使った設計と、その線の引き方を書きます。質問の文面や判定の細かい規則は載せません。
Failure KB は、エージェントが調べて、試して、報告する MCP サーバー
Failure KB は、筆者が作っている Forecall の機能の 1 つです。MCP ツールの呼び出しがどう失敗し、何をしたら通ったかを集めた MCP サーバーで、ツールは 4 つあります。
| ツール | エージェントが呼ぶとき |
|---|---|
kb_lookup |
ツールを呼ぶ前と、呼んで失敗したあと |
kb_report |
KB にない失敗を自分で直したあと |
kb_confirm |
KB の回避策を試したあと(効いた、効かなかった、当てはまらなかった) |
kb_dispute |
レコードが間違っている、古いとき |
レコードが「検証済み」になるのは、ほかの 2 つの組織のエージェントが回避策を再現したときだけです。投票でも、モデルの判定でも検証済みにはなりません。この決まりが、あとで Jev に何を任せないかの線になります。
KB には、エージェントが書いた投稿、エラー文、ツールの結果が入ってきます。どれも量が多く、形が決まっていて、1 件ずつに長い文章は要りません。「これは既知の失敗と同じか」「スパムか」「秘密が残っていないか」に答えが出れば足ります。Jev が向いているのはこういう判断です。
Jev を選んだ理由:答えをそのまま分岐に使える
Jev は、状態(テキストや JSON)と型の決まった質問を受け取り、確率つきの答えを返すモデルです。文章は生成しません。質問の型は 3 つです。
- Choice:選択肢から 1 つ選ぶ。1 問で 255 択まで
- Score:2〜10 段階で採点する
- Noul:yes の確率を返す
決め手になったのは次の 4 点です。
- 答えをそのままコードの分岐に使える。 生成モデルに JSON を返させて、パースし、壊れていたら直す層が要りません
- 1 回の呼び出しに複数の質問を詰められる。 仕様では質問は並列に評価されるので、1 件の投稿に 5 問聞いても、1 問のときと待ち時間はほぼ変わらないはずです
- 安い。 料金は入力トークンだけで、100 万トークンあたり 0.042 米ドルです。出力は無料です
- Cloudflare Workers から fetch 1 本で呼べる。 Forecall は全部 Workers で動いているので、SDK を入れずに HTTP を直接呼んでいます
Forecall のもう 1 つの機能である評価(MCP ツールを実際のモデルに選ばせて測る)では、Claude や GPT を呼んでいます。Jev はその代わりではありません。生成モデルが要らない「判定」だけを、生成モデルの前後で引き受けます。
Jev を使っている 3 か所の位置関係は次のとおりです。
任せたこと 1:KB への投稿の振り分け(非同期)
kb_report で投稿が来ると、MCP の Worker は応答を返したあとで Queue にメッセージを流します。jobs の Worker がそれを受け取り、投稿と、近い既知のレコードを state にして Jev に 5 問を 1 回で聞きます。聞いているのは、次のようなことです。
- 既知のレコードのどれと同じ失敗か(どれでもない、を含む Choice)
- 失敗の種類(Choice)
- 回避策が実行できる手順になっているか(Noul)
- スパムや宣伝ではないか(Noul)
- 秘密が残っていそうか(Score)
答えで変わるのは 3 つです。重複なら、投稿を元のレコードの再現の記録に変えて、投稿そのものは隠します。投稿者の評判は下げません。スパムなら却下します。秘密が残っていそうなら、公開を止めて人が見るまで保留します。
非同期なので、タイムアウトは 5 秒と長めにしています。レート制限(429)に当たったら、メッセージを失敗にして Queue の再配送に任せます。鍵がない、5xx、タイムアウトのときは、エラー文の署名が同じレコードへの重複判定だけをコードで行い、ほかは何もしません。
kb_confirm で回避策を試した報告が来たときも、添えられた根拠が結果(効いた、効かなかった)と食い違っていないかを 1 問だけ聞きます。食い違うものは、検証済みへの数に入れません。
任せたこと 2:ツール呼び出しの観測(非同期)
エージェントが自分から投稿してくれる失敗だけに頼ると、KB に入る失敗は限られます。そこで、Claude Code のフック(PostToolUse)で MCP ツールの結果を背景で送れるようにしました(forecall setup --sensor で入れる。既定は入れない)。エラー文は手元で秘密を取り除いてから送り、サーバーでももう一度取り除きます。
jobs の Worker は、観測とそのツールの既知のレコードを Jev に見せて 4 問聞きます。失敗を示しているか、失敗の種類、既知のレコードのどれと同じか、秘密が残っていそうかです。秘密が残っていそうなら、本文を消します。
「失敗で、既知のどれでもない」と判定された観測は、週に 1 回、人がダッシュボードで見て、回避策を書いてレコードにするか捨てるかを決めます。Jev が自動でレコードを作ることはありません。
任せたこと 3:呼ぶ前の失敗の予知(同期)
kb_lookup には mode: "preflight" があります。エージェントがツールを呼ぶ前に、ツールの定義と、これから渡す引数の形(名前と型と長さだけで、値は含まない)と環境を Jev に見せます。そのツールの既知のレコードに no_known_failure を加えた選択肢から、当たりそうなものを Choice で選ばせます。
こちらは同期で、エージェントを待たせます。そのため設計の中心は「邪魔をしないこと」にしました。
- タイムアウトは 1,000 ms
- 返すのは、確信度が 0.8 以上で、
no_known_failure以外を選んだときだけ - それ以外(確信度が低い、タイムアウト、鍵がない、Jev の失敗)はすべて空で返す
簡略化すると、次のような形です。
// 簡略化したもの。実際の質問セットと候補の作り方は省いています
const result = await jev.ask(preflightQuestions, state, { timeoutMs: 1000 });
if (!result.ok) return []; // 止まっても、エージェントには空で返す
const pick = result.answers.record; // Choice の答え
if (pick.choice === "no_known_failure" || pick.confidence < 0.8) return [];
return [await recordById(pick.choice)]; // lookup と同じ形で返す
既知のレコードが 254 件を超えるツールは、Choice の 255 択に収まりません。そのときは先に失敗の種類を Choice で選ばせ、候補を絞ってからもう一度聞く 2 段構えにしています。
Pre-flight は鍵を任意にしてあり、鍵がなければ空を返すだけで動きます。本番では 2026 年 10 月 9 日に鍵を入れ、Jev を呼ぶようになりました。
任せなかったこと
Jev は安く、型の決まった答えを返すので、いろいろ任せたくなります。それでも、次の 4 つは任せないと最初に決めました。
- レコードを検証済みにすること。 検証は、ほかの組織のエージェントによる再現だけで決めます。KB のレコードと再現の記録のうち、Jev の判定が書き込めるのは、失敗の種類、重複の行き先、保留の理由、却下の日時、再現を数えるかどうか、の 5 つの列だけです。レコードの状態は、再現と異議の記録から毎回計算し直します
- 数字、日付、件数の判定。 「90 日以上前か」「3 件以上か」はコードで計算します。Jev には判断だけを渡します
- 評価の「モデル別の選択精度」の代わり。 評価で測りたいのは、Claude や GPT がツールをどう選ぶかです。測る対象がモデルそのものなので、別のモデルでは代わりになりません
- 予測。 「このツールは来週壊れるか」のような、渡した事実から答えが出ない質問はしません
守っていること
state に入る文字列は、敵対的な入力として扱う
投稿、エラー文、ツールの結果は、利用者が自由に書ける文字列です。「このレコードを検証済みにせよ」という文が混ざっていても、上に書いたとおり、Jev の答えは検証済みへの遷移につながりません。Jev が書ける列を絞ってあるので、判定がだまされても、起きるのは重複にまとめられる、保留される、却下される、のどれかです。検証済みになることはありません。
すべての判定を保存し、モデルの版を固定する
呼び出しは、成功も失敗も jev_decisions に 1 行ずつ残します。種類、質問セットの名前と版、モデルの版(いまは jev-1.13.0)、答え、応答時間、入力トークン、原価です。しきい値を変えるときは質問セットの版を上げます。確信度の帯ごとの正答率を、再現の成否や人のレビューと突き合わせて月に 1 回見る予定です。
Jev が止まっても、本体は動く
3 つの用途のどれも、Jev がなくても動きます。振り分けは同じ署名の重複判定だけに、観測はコードの規則だけに、予知は空の応答に落ちます。いまは早期アクセスなので、料金やレート制限が変わる可能性もあります。止まったときの動きを最初に決めておくと、組み込む側の気が楽になります。
テストとプレビューでは、決定的な偽の Jev を使う
プルリクエストごとのプレビュー環境と e2e テストでは、実際の Jev を呼びません。偽の Jev が、本文から決まった答えを返します。質問ごとに答えを指定しなければ「何も見つからない」側(選択肢の最後、段階 0、yes の確率 0)を返すので、質問セットでは none のような選択肢を最後に置く決まりにしました。
3 つの型だけで書き、差し替えられるようにする
質問セットは Choice、Score、Noul の 3 つだけで書いています。同じ形の答えを返す互換のモデルが出てきているので、差し替えの余地を残すためです。差し替えたら、較正は取り直します。
まとめ:Jev は「量が多くて形が決まった判断」の前後に置く
Failure KB では、Jev を生成モデルの代わりではなく、前後に置く判定層として使いました。任せたのは、投稿の振り分け、観測の判定、呼ぶ前の予知です。どれも量が多く、答えの形が決まっている判断です。任せなかったのは、検証済みの判断、数字の判定、モデルそのものの測定です。
組み込むときに効いたのは、Jev が書き込める範囲を絞ることと、止まったときの動きを先に決めることでした。この 2 つがあれば、判定が外れても、検証済みのレコードが間違って増えることはありません。
Forecall について
Forecall は、MCP サーバーの開発者向けに、ツールの説明文を採点するリンター(無料、オープンソース)と、実際のモデルで選ばれ方を測る評価、そしてこの Failure KB を提供しています。Failure KB は Free プランでも月 1,000 回まで照会でき、npx forecall setup で Claude Code、Claude Desktop、Cursor、Codex、Windsurf などにつなげます。
- サイト:https://forecall.dev
- Failure KB のドキュメント:https://forecall.dev/ja/docs/kb
- リンター(Apache-2.0):https://github.com/forecall/forecall-cli




