このガイドの範囲:リクエスト形式とアプリケーションコードは、2026-09-25 に確認した TypeSafe 公式ドキュメントに基づいています。問い合わせ文、ラベル、しきい値は業務ルールを説明するための合成例です。モデルの出力、精度、速度、費用の比較は掲載していません。利用前に、自社のラベル付きデータで測定してください。
1. ルーターに任せる範囲を決める
ここで作るルーターが行うのは、担当キューの選択と情報不足の検出だけです。返信文の作成、返金、アカウント変更は行いません。そうした操作は通常の権限管理の後ろに置いてください。Jev は型付きの答えを返します。Choice は選ばれた選択肢、各選択肢の確率、confidence を返し、Noul は答えが「はい」である確率を 0 から 1 の数値で返します。この構造があるので、次の判断をコードで確実に行えます。
2. 4 つの担当の境界を書き出す
以下は説明用の業務ルールの例です。自社の運用に合わせて書き換えてください。
| 担当 | 扱う内容 | 他へ回す条件 |
|---|---|---|
billing | 既存の請求、請求書、返金、支払い方法、更新時の決済失敗 | 購入前に料金を尋ねている(sales へ) |
technical | 不具合、障害、エラーメッセージ、ログインの問題、連携エラー | 実際には発生済みの請求に関する問題(billing へ) |
sales | 料金の質問、プラン比較、新規購入、見積もり | すでに契約中で、特定の請求について尋ねている(billing へ) |
other | 提携、取材、採用への応募、一般的なご意見 | 自動では閉じず、必ず人が読む |
この境界を選択肢の説明文に書き込みます。TypeSafe の Jev 1.13 の既知の制約ページによると、Jev は指示を文字どおりに読みます。誤った答えを見て「本当はこういう意味だった」と説明したくなったら、その一文が criteria に足りなかった部分です。other は必ず本物の選択肢として残してください。どれにも当てはまらない問い合わせを、いちばん近い担当に無理やり入れずに済みます。
3. 実験室のリクエストから始める
実験室の support-routing の例 を開くと、次のリクエストが読み込まれます。本文を書き換えて JSON や cURL をコピーできます。API キーが必要なのは実際に送信するときだけです。
{
"model": "jev-1.13.0",
"state": {
"message": "今月、同じサブスクリプションの料金が二重に請求されました。"
},
"questions": {
"decision": {
"type": "choice",
"instructions": "この問い合わせはどのチームが担当すべきですか? 該当するチームがない場合は other を選んでください。",
"criteria": {
"billing": "支払い、請求、請求書、返金",
"technical": "不具合、障害、連携エラー",
"sales": "料金や新規購入の相談",
"other": "これらのチームの担当外の問い合わせ"
}
}
}
}
cURL では、キーを環境変数から読み、本文を引用符付きのヒアドキュメントで渡します。
curl --fail-with-body --max-time 20 https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JEV_ATLAS_REQUEST'
{
"model": "jev-1.13.0",
"state": {
"message": "今月、同じサブスクリプションの料金が二重に請求されました。"
},
"questions": {
"decision": {
"type": "choice",
"instructions": "この問い合わせはどのチームが担当すべきですか? 該当するチームがない場合は other を選んでください。",
"criteria": {
"billing": "支払い、請求、請求書、返金",
"technical": "不具合、障害、連携エラー",
"sales": "料金や新規購入の相談",
"other": "これらのチームの担当外の問い合わせ"
}
}
}
}
JEV_ATLAS_REQUEST
本番では、担当の判定と情報不足の判定を 1 回のリクエストにまとめます。2 つの質問は同じ state に対してそれぞれ独立に評価され、一方の答えがもう一方の前提になることはありません。組み合わせはコードで行います。team や needs_details は自分で付ける ID で、答えも同じ ID で返ります。
{
"model": "jev-1.13.0",
"state": {
"subject": "今月の請求が二重になっています",
"message": "今月、同じサブスクリプションの料金が二重に請求されました。請求書番号の末尾は 4471 と 4472 です。",
"channel": "email"
},
"questions": {
"team": {
"type": "choice",
"instructions": "このサポート依頼はどのチームが担当すべきですか? 顧客の主な依頼内容で判断してください。どの専門チームにも当てはまらない場合は other を選んでください。",
"criteria": {
"billing": "既存アカウントの請求、請求書、返金、支払い方法、支払いの失敗",
"technical": "不具合、障害、エラーメッセージ、ログインの問題、連携エラー",
"sales": "購入前の料金に関する質問、プランの比較、新規購入や見積もり",
"other": "これら 3 チームの担当外。提携、取材、一般的なご意見など"
}
},
"needs_details": {
"type": "noul",
"instructions": "サポート担当者が作業を始めるために必要な情報(どのアカウント、注文、製品、エラーか)がこの依頼に欠けていますか?",
"criteria": {
"true": "作業開始に必要な情報が少なくとも一つ欠けている",
"false": "作業を始められる程度に対象が特定されている"
}
}
}
}
4. 情報不足をはっきり扱う
needs-clarification の例 は、依頼に必要な情報が欠けているかを Noul で尋ねます。
{
"model": "jev-1.13.0",
"state": {
"request": "それを別の宛先に送ってください。",
"known_context": "文書も受取先のアドレスも指定されていません。"
},
"questions": {
"decision": {
"type": "noul",
"instructions": "送るものと送信先の両方を特定するために、この依頼には追加の情報が必要ですか?",
"criteria": {
"true": "必要な情報が少なくとも一つ欠けている",
"false": "送るものと送信先の両方が明示されている"
}
}
}
}
Noul は、答えが「はい」である確率の推定値を 0 から 1 で返し、confidence は付きません。値が高いときは担当を推測させず、足りない点を顧客に具体的に尋ねます。確実に判定できることはコードで確認してください。たとえばフォームで注文番号やアカウントのメールアドレスが必須なら、モデルを呼ぶ前にその項目をコードで検査します。
5. しきい値と人による確認はコードで決める
// Node 18+ or any runtime with fetch. Example thresholds: calibrate them on your
// own labeled tickets; they are starting points, not measured values.
const ENDPOINT = 'https://api.typesafe.ai/v1/systemone';
const ROUTE_AT_CONFIDENCE = 0.8;
const ASK_AT_MISSING = 0.7;
const TEAMS = new Set(['billing', 'technical', 'sales']);
export async function classifyTicket(request, apiKey) {
const response = await fetch(ENDPOINT, {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify(request),
signal: AbortSignal.timeout(20_000),
});
if (response.status === 429 || response.status === 529) {
// Back off; honor retry-after when present. Do not retry in a tight loop.
const error = new Error('typesafe_retry_later');
error.retryAfter = response.headers.get('retry-after');
throw error;
}
if (!response.ok) throw new Error(`typesafe_http_${response.status}`);
return response.json();
}
export function decideRoute(result) {
const team = result.answers.team;
const missing = result.answers.needs_details.noul;
if (missing >= ASK_AT_MISSING) return { action: 'ask_customer', reason: 'missing_details' };
if (!TEAMS.has(team.choice)) return { action: 'human_triage', reason: 'no_specific_team' };
if (team.confidence < ROUTE_AT_CONFIDENCE) {
return { action: 'human_triage', reason: 'low_confidence', suggestion: team.choice };
}
// Log the versioned model that answered, so threshold changes stay traceable.
return { action: 'route', queue: team.choice, confidence: team.confidence, model: result.model };
}
3 つのしきい値は出発点の例で、推奨値ではありません。TypeSafe は confidence を高・中・低の範囲に分け、リスクに応じてしきい値を変えることを勧めています。担当の振り分けを誤っても損失は限られますが、自動返金のように影響の大きい操作には、より厳しい条件が必要です。ラベル付きデータで調整し、判断ごとに result.model を記録してください。しきい値を調整したら、jev-1.13.0 のようにバージョンを固定します。jev-latest は新しいモデルに切り替わることがあります。
- 401:API キーまたは Authorization ヘッダーを確認します。
- 422:リクエストが検証に失敗しています。レスポンス本文が問題の項目を示します。
- 429 / 529:すぐに再送せず、指数的に間隔を空けて再試行します。retry-after ヘッダーがあれば従ってください。
6. 信頼する前に、小さなラベル付きデータを固定する
先に期待する結果を書き、そのあとでリクエストを実行して比べます。次の表は合成した問い合わせと、例のルールに従った場合の期待値です。モデルの結果ではありません。
| 合成した問い合わせ | 期待する担当(例のルール) | 情報不足? |
|---|---|---|
| 請求書 INV-2291 を返金してください。更新日の前に解約しました。 | billing | いいえ |
| 今朝のアップデート以降、エクスポートボタンが 500 エラーを返します。 | technical | いいえ |
| 年間プランで 40 席を契約すると割引はありますか? | sales | いいえ |
| 決済ページがタイムアウトしたのに、カードには請求されていました。 | billing(ルール:発生済みの請求は billing) | はい:どの請求か |
| 今のプランを年払いに変更できますか? 今日請求されますか? | billing(ルール:既存顧客は billing) | いいえ |
| 雑誌の記事のため、チームに取材をお願いしたいです。 | other | いいえ |
| 動きません。 | 判定しない:先に確認 | はい |
| それを別の宛先に送ってください。 | 判定しない:先に確認 | はい(needs-clarification の例) |
各問い合わせについて、選ばれた担当、confidence、Noul の値、そしてコードが振り分けたか、顧客に確認したか、人に回したかを記録します。担当ごとに不一致を数えて読み返すと、たいていは境界の文があいまいか、コードで処理すべきルールが見つかります。実際に届く言語の問い合わせも必ず含めてください。TypeSafe のモデルページ(2026-09-25 確認)では、英語が主な学習言語であり、ほかの言語は自社のデータで試すよう案内されています。
この考え方を使うプロジェクト
- Jev Ticket Router: Jev と明示的な業務ルールを使い、ペルシャ語・英語のサポートチケットを振り分けます。
- Triage Guard: チケット、運用アラート、デプロイのリスクに Jev を使うワークフローを試せます。
これらは 2026-09-18 に各 README で出典を確認したものです。Jev Atlas では実行、性能測定、セキュリティ監査を行っていません。
参考資料
- TypeSafe: API reference
- TypeSafe: Choice
- TypeSafe: Noul
- TypeSafe: Confidence
- TypeSafe: Confidence-gated routing
- TypeSafe: Intent routing
- TypeSafe: Jev 1.13 jaggedness
- TypeSafe: Models
TypeSafe のページは 2026-09-25 に確認しました。モデル、制限、料金は変わる可能性があるため、導入前に公式情報を確認してください。
試してみる
実験室で support-routing を開く · needs-clarification を開く · 判断しやすい質問の書き方