GUIDES / はじめに

JS/TS SDK(@typesafe-ai/sdk)で Jev に最初の判定をさせる

公式の JS/TS SDK、@typesafe-ai/sdk で Jev を呼ぶ手順。インストール、choice・noul・score のヘルパー、型推論、例外、AI SDK との使い分けを実行結果つきで説明する。

Jevjs-sdktypescript

JavaScript / TypeScript から Jev を使う公式 SDK は @typesafe-ai/sdk です。choice() noul() score() のヘルパーで質問を書くと、答えの型が質問から推論されます

1. インストール

npm install @typesafe-ai/sdk
# pnpm add @typesafe-ai/sdk

公式の要件は Node.js 20 以上です。ESM・CommonJS・TypeScript の型定義が同梱されています。

Python 版は typesafe-sdk、JS 版は @typesafe-ai/sdk と、パッケージ名の付け方が違います。

2. API キー

TypeSafe のコンソールでキーを発行し、環境変数 TYPESAFE_API_KEY に入れます。.env.localTYPESAFE_API_KEY=… と書く場合、このファイルは Git に入れないでください。

下のコードを index.ts として保存し、次のように実行します。

node --env-file=.env.local index.ts

SDK 自体の要件は Node.js 20 以上ですが、.ts のファイルを node でそのまま実行できるのは Node.js 22.18 以降です(それより前は tsx などを使うか、.mjs として書きます)。このページの結果は Node.js 26 で実行したものです。

3. 最初の判定

TypeSafeClient を作り、判定したい内容(state)と質問(questions)を systemOne に渡します。質問は noulchoicescore の関数で組み立てます。

import { choice, noul, score, TypeSafeClient } from '@typesafe-ai/sdk';

const client = new TypeSafeClient();

const res = await client.systemOne({
  state: { message: '助けてください!3日前から入金がずっと失敗しています。' },
  questions: {
    isUrgent: noul('Does `message` convey urgency?'),
    department: choice('Which team should handle `message`?', {
      billing: 'Payments, invoicing, refunds',
      technical: 'Bugs, outages, integrations',
      other: null,
    }),
    frustration: score('How frustrated is the customer?', ['Calm', 'Frustrated', 'Very angry']),
  },
});

console.log(res.model);                          // jev-1.13.0
console.log(res.answers.isUrgent.noul);          // 0.96
console.log(res.answers.department.choice);      // billing
console.log(res.answers.department.confidence);  // 0.9
console.log(res.answers.frustration.score);      // 1.05
console.log(res.usage);                          // { input_tokens: 415, output_tokens: 72 }

コメントの値は 2026-09-21 に実際に返ってきたものです。往復は約 0.6 秒でした(1回の計測)。

レスポンスは REST API と同じ形(model / answers / usage)です。answers の中身も noulchoiceconfidencelegendprobabilities と、REST の項目名のままです(REST API の使い方)。

型が質問から決まる

choice() に渡した選択肢のキーが、そのまま答えの型になります。

const d = res.answers.department.choice; // 'billing' | 'technical' | 'other'

switch (d) {
  case 'billing':
    break;
  case 'technical':
    break;
  case 'other':
    break;
  // case 'sales': ← 選択肢に無い値なので、ここに書くとコンパイルエラー
  default: {
    const unreachable: never = d; // 選択肢を足して case を書き忘れると、ここがコンパイルエラーになる
    throw new Error(`未対応の選択肢: ${unreachable}`);
  }
}

存在しない選択肢を case に書く誤りは、型だけで防げます。選択肢を足したのに case を書き忘れる誤りは、そのままでは通ってしまうので、defaultnever への代入を置いて検出します。

確率を === で比べない

実行結果の probabilities には、billing: 0.9400000000000001 のような値が入っていました。浮動小数点の表現によるものです。確率やスコアは > < でしきい値と比べ、=== 0.94 のような一致の判定はしないでください。

説明の要らない選択肢は null

名前だけで意味が通る選択肢は、説明を null にできます。どれにも当てはまらない入力が来得るなら、上の例の other のような逃げ道を入れます(質問タイプの書き方)。

エラー

SDK は、ステータスごとの例外クラスを持っています。

例外状況確認
AuthenticationError(401)API キーが無い・誤っている実行して確認
BadRequestError(400)存在しないモデル名実行して確認
UnprocessableEntityError(422)リクエストの形が不正(例: Choice に選択肢が無い)実行して確認
RateLimitErrorレート制限の超過未確認(公式の一覧より)
APIConnectionError / APITimeoutError通信の失敗未確認(公式の一覧より)

例外は2系統に分かれています(@typesafe-ai/sdk 0.6.0 のクラスの継承を実際にたどって確認)。

  • HTTP のエラー(サーバーが応答を返した): AuthenticationErrorBadRequestErrorUnprocessableEntityErrorRateLimitError などは APIError を継承し、e.status にステータスが入る
  • 通信の失敗(応答が無い): APIConnectionErrorAPIError ではなく TypeSafeError の直下。APITimeoutErrorAPIConnectionError の派生。status はありません

だから e instanceof APIError だけで捕まえると、通信の失敗とタイムアウトを取りこぼします。SDK の例外をすべて捕まえるなら TypeSafeError です。

import { APIConnectionError, APIError, TypeSafeError } from '@typesafe-ai/sdk';

try {
  await client.systemOne({ state, questions });
} catch (e) {
  if (e instanceof APIError && e.status === 422) {
    // 質問の組み立てに不具合がある。再試行しても直らない
  } else if (e instanceof APIConnectionError) {
    // 応答が無かった(タイムアウトを含む)。e.status は無い
  } else if (e instanceof TypeSafeError) {
    // そのほかの SDK の例外
  }
  throw e;
}

422 のメッセージには 422 questions.c.choice.criteria: Field required のように、問題の場所が入っていました。

429529 は SDK が既定で間隔を空けて再試行する、と公式ドキュメントにあります。回数などは RetryPolicy で変えられます。例外クラスの一覧は公式の API reference にあります。

AI SDK(experimental_evaluate)との違い

比較項目@typesafe-ai/sdkAI SDK の experimental_evaluate
はい/いいえnoul()answers.x.noultype: 'boolean'answers.x.probability
確信度answers.x.confidenceproviderMetadata.typesafe.confidence.x
答えたバージョンres.modeljev-1.13.0Gateway 経由では入らなかった
環境変数TYPESAFE_API_KEY直結は TYPESAFE_AI_API_KEY、Gateway は AI_GATEWAY_API_KEY
安定性公式 SDK(0.x)experimental。patch リリースでも変わり得る
他社モデルへの差し替えできないできる

詳しくは AI SDK で使う

次に読むもの

よくある質問

npm のパッケージ名は typesafe-sdk ですか?

いいえ。公式の JS SDK は @typesafe-ai/sdk です。Python の typesafe-sdk と名前が違うので注意してください。

AI SDK の experimental_evaluate とどちらを使うべきですか?

すでに Vercel AI SDK を使っていて手早く試したいなら experimental_evaluate、TypeSafe の API の形(noul、confidence、legend、答えたバージョン ID)をそのまま扱いたいなら @typesafe-ai/sdk です。experimental_evaluate は patch リリースでも変わり得ると明記されています。

ブラウザから直接呼べますか?

API キーが利用者に見えてしまうので、ブラウザから直接呼ぶべきではありません。サーバー側(API ルートやサーバー関数)から呼んでください。

出典・参考リンク

  1. 一次情報 JavaScript SDK
  2. 一次情報 npm: @typesafe-ai/sdk
  3. 一次情報 typesafe-sdk-js