TypeScript SDK を始める
System One TypeScript SDK をインストールし、ホスト API に接続してモデルを選び、型付き意思決定を読みます。
このガイドでは、サーバー側の TypeScript アプリケーションを System One ホスト型意思決定 API に接続します。SDK をインストールし、プラットフォーム API キーとカタログのモデルを設定して、1 件のサポートメッセージを「担当チーム」「緊急度」「二重課金の可能性」として評価します。API は判断を返すだけで、チケットの振り分け、返金の実行、ツールの呼び出しは行いません。
よくある質問
Q: System One の TypeScript SDK のはじまり方は? A: System One TypeScript SDK をインストールし、API キーを設定して、Jev や Clef Flash などのモデルを選び、ホスト型の System One API から Choice、Score、Noul を呼んで型付き意思決定を受け取ります。
Q: クレジットは? A: 新規アカウントは登録時に 100 クレジットを受け取ります。クレジットの有効期限はありません。
SDK のセットアップと API の課金は別です
オープンソースの TypeScript SDKはクライアント、adapter、型付き結果を提供します。インストールしてもホスト型アカウントが作られるわけでも、推論が購入されるわけでもありません。ホスト型意思決定 APIへの呼び出しは、選択したモデルの現在の単価で System One アカウントのクレジットを消費します。意思決定を送る前に、その価格とリクエストサイズを確認してください。SDK のインストールは料金プランではありません。
このガイドで使うのは System One のプラットフォーム API キーであり、プロバイダのキーではありません。SDK を別のサービスへ直接接続したい場合は、SDK インストールと直接サービス用 adapterを参照してください。直接接続は、そのサービスの資格情報と課金を使います。プロバイダのキーを SYSTEM_ONE_API_KEY に設定しないでください。
1. API キーを作成してモデルを選ぶ
System Oneにサインインしてメール認証を完了し、コンソールの API keys を開きます。名前付きのキーを作成し、表示されたシークレットをコピーします。一覧には接頭辞しか表示されず、完全なシークレットは後から取得できません。サーバー上に保管し、プロンプト、ブラウザコード、ログ、バージョン管理の外に置いてください。
新規アカウントは登録時に 100 クレジットを受け取ります。コンソールの残高を確認してください。キーを増やしてもウェルカムクレジットは増えません。
モデルは現在のディレクトリまたは Playground のセレクターで選びます。セレクターの横にある Model information をクリックして、選択したモデルの単価と上限を確認します。正確な name をコピーし、Choice、Score、Noul に対応していることを確認してください。公開の GET /v1/models でもディレクトリを取得できます。以下の YOUR_MODEL_ID はプレースホルダーであり、対応するエイリアスではありません。SDK の既定値や他サービスで使うモデル ID を代用しないでください。
2. インストールと設定
SDK は Node.js 20+ に対応しています。以下のコマンドは Node.js 22.18+ を前提にしており、.mts の TypeScript ファイルを直接実行できます。
npm install @system-one-ai/core@0.8.0 @system-one-ai/adapter-system-one@0.7.0 @system-one-ai/transport-fetch@0.8.0このクイックスタートで使うのは現在のホスト用の 3 つのパッケージは core 0.8.0、adapter-system-one 0.7.0、transport-fetch 0.8.0 です。各パッケージは独立してリリースされ、すべて core@^0.8.0 に解決されます。systemOneAdapter は Clairic の extract()(画像を含む)をエンコードしますが、evaluate() の画像はエンコードしません。Clef/Clef Flash/Clef Omni の decision 画像は Fetch の例を使い、Clairic の抽出は Clairic 抽出を参照してください。
バージョン管理から除外した .env を作成します。
SYSTEM_ONE_API_KEY=replace-with-your-platform-key
SYSTEM_ONE_BASE_URL=https://system-one.dev/v1
SYSTEM_ONE_MODEL=YOUR_MODEL_IDAPI はドキュメントのホストではなく本体の Web サイトのオリジンを使います。API キーは System One のプラットフォーム資格情報です。操作キーは別物です。論理的に新しい評価ごとに新しい UUID を生成し、共有の環境設定にはしません。その操作をリトライするときは、同じキーと完全なリクエストを使います。
続ける前に .env の YOUR_MODEL_ID を、選んだカタログ項目の正確な name に置き換えてください。下のコマンドを実行するため、.env と decision.mts は同じ作業ディレクトリに置いてください。System One adapter のベース URL は https://system-one.dev/v1 で、意思決定は /v1/systemone へ送られます。別の HTTP クライアントを設定する場合は HTTP API の認証とエンドポイントを参照してください。
3. 最初の Choice を送る
例では、1 件の共有サポートメッセージを state として渡し、名前付きの質問を 3 つ置きます。choice() は候補チームを、score() は順序付きの緊急度ルーブリックを宣言し、booleanQuestion() は真偽の指示ではなく確率を求めます。質問の設計は Choice、Score、Noul の意思決定プリミティブを参照してください。
decision.mts として保存します。
import { createSystemOne, choice, score, booleanQuestion } from '@system-one-ai/core';
import { systemOneAdapter } from '@system-one-ai/adapter-system-one';
import { createFetchTransport } from '@system-one-ai/transport-fetch';
const apiKey = process.env.SYSTEM_ONE_API_KEY;
const baseURL = process.env.SYSTEM_ONE_BASE_URL;
const model = process.env.SYSTEM_ONE_MODEL;
if (!apiKey || !baseURL || !model || model === 'YOUR_MODEL_ID') {
throw new Error('Set the API key, base URL, and catalog model.');
}
const client = createSystemOne({
apiKey,
baseURL,
model,
adapter: systemOneAdapter,
transport: createFetchTransport(),
timeoutMs: 30_000,
maxRetries: 0,
});
const operation = {
idempotencyKey: crypto.randomUUID(),
request: {
model,
state: { message: 'I was charged twice for the same order.' },
questions: {
team: choice('Choose the team that should review this request.', {
billing: 'Payments, invoices, and refunds',
support: 'Technical troubleshooting',
review: 'More context is needed',
}),
urgency: score('Rate urgency using this ordered rubric.', [
'Can wait for normal review',
'Needs a timely response',
'Needs immediate human attention',
]),
duplicate: booleanQuestion('Does the message report a duplicate charge?', {
true: 'The same order was charged more than once',
false: 'No duplicate charge is reported',
}),
},
},
};
const result = await client.evaluate(operation.request, {
headers: { 'Idempotency-Key': operation.idempotencyKey },
});
console.log({
team: result.answers.team.choice,
distribution: result.answers.team.probabilities,
urgency: result.answers.urgency.score,
duplicateProbability: result.answers.duplicate.probability,
inputTokens: result.usage.inputTokens,
model: result.model,
requestId: result.response.requestId,
});node --env-file=.env decision.mtsこのスクリプトを実行するたびに新しい課金対象の操作が始まります。 入力が同じでも同じです。操作はメモリ上にしか存在せず、スクリプトの再実行はタイムアウトやクラッシュからの復旧ではありません。3 つの質問とリクエスト全体のサイズが、選択したモデルの現在の単価でコストに影響します。概算と残高を先に確認してください。固定の回答、コスト、レイテンシは約束されません。例は非 null の state、明示的な指示、通常の質問 ID、非 null の criteria、3 つの Choice オプション、3 段階の Score を使っています。将来のすべてのモデルが同じリクエストを受け付けるとは限りません。選択したモデルの現在の機能を確認してください。
4. 結果の読み方
team.choiceは宣言したオプション名のいずれかで、リテラル型が保たれます。urgency.scoreは、この 3 段階ルーブリックでは0から2の間で小数値になり得ます。duplicate.probabilityはP(true)で0から1の値です。JavaScript の boolean ではありません。- 任意の統計値とトークン数は、存在しない場合は不明のままです。0 で置き換えないでください。
core は adapter 間で結果を正規化します。ワイヤ上 booleanQuestion() は type: 'noul' になり、回答フィールドは noul という名前です。core は代わりに type: 'boolean' と probability を公開します。この型付き結果は HTTP のレスポンス本文そのものではなく、すべてのレスポンスヘッダーにも触れません。このホスト型 API への接続では明示的な HTTP adapter と Fetch transport を使ってください。SDK ドキュメントで説明している直接サービス用 adapter は別の統合です。
型付き回答は判断が正しいことを証明しません。チケットを振り分けるか人間レビューを要するかは、アプリケーションが決めます。回答を操作につなげる前にエージェント統合と実行境界を確認してください。
最初の例が出力するのは SDK のメタデータであり、請求の領収書ではありません。プラットフォームの会計 ID、消費クレジット、リプレイ状態が必要な場合は、最初のリクエストを実行し直すのではなく下のレスポンスヘッダーの例を使ってください。各例はそれぞれの操作を生成します。
公式 TypeSafe クライアントとレスポンスヘッダー
公式の @typesafe-ai/sdk は別の HTTP クライアントで、コンストラクタのオプション、型、結果のラップが異なります。ベース URL は /v1 を含まない API ルートです。/v1/systemone は自分で付加します。
npm install @typesafe-ai/sdk@0.6.0official-decision.mts として保存します。API キー、ベース URL、選択したモデルは上と同じです。この独立した例は新しい操作を 1 つ生成し、null ではない Noul の質問を 1 つだけ送ります。
import { TypeSafeClient } from '@typesafe-ai/sdk';
const apiKey = process.env.SYSTEM_ONE_API_KEY;
const baseURL = process.env.SYSTEM_ONE_BASE_URL;
const model = process.env.SYSTEM_ONE_MODEL;
if (!apiKey || !baseURL || !model || model === 'YOUR_MODEL_ID') {
throw new Error('Set the API key, base URL, and catalog model.');
}
const client = new TypeSafeClient({
apiKey,
baseURL: baseURL.replace(/\/v1\/?$/, ''),
defaultModel: model,
timeout: 30_000,
retry: { maxRetries: 0 },
logLevel: 'off',
});
const operation = {
idempotencyKey: crypto.randomUUID(),
request: {
model,
state: { message: 'I was charged twice for the same order.' },
questions: {
duplicate: {
type: 'noul' as const,
instructions: 'Does the message report a duplicate charge?',
criteria: {
true: 'The same order was charged more than once',
false: 'No duplicate charge is reported',
},
},
},
},
};
const { data, response, requestId: typeSafeRequestId } = await client.systemOne(
operation.request,
{ headers: { 'Idempotency-Key': operation.idempotencyKey } },
).withResponse();
const reportedCredits = response.headers.get('X-System-One-Credits');
const credits = reportedCredits !== null && /^\d+$/.test(reportedCredits)
&& Number.isSafeInteger(Number(reportedCredits)) ? Number(reportedCredits) : undefined;
console.log({
duplicateProbability: data.answers.duplicate.noul,
model: data.model,
inputTokens: data.usage?.input_tokens,
platformRequestId: response.headers.get('X-Request-Id'),
upstreamRequestId: response.headers.get('X-Upstream-Request-Id'),
typeSafeRequestId,
credits,
replayed: response.headers.get('X-Idempotency-Replayed') === 'true',
});node --env-file=.env official-decision.mts実行のたびに別の課金対象の評価が始まります。 入力が同じでそうな同じです。最初の呼び出しのオフライン代替ではなく、 再起動に強い復旧でもありません。この操作もメモリ上にあるだけです。
withResponse() は解析済みの data と、本文がすでに読み取られた Response を返します。その requestId は X-TypeSafe-Request-Id 由来で、プラットフォームの会計には X-Request-Id が使われます。課金とリプレイの情報は X-System-One-Credits と X-Idempotency-Replayed から読みます。クレジットが不明なら 0 ではなく不明のままです。billing や request_id のような本文のプロパティでこれらのヘッダーを上書きしてはいけません。成功したリプレイはヘッダー上で課金 0 を示します。
正確なレスポンス本文が必要な場合は、上と同じ client と operation をそのまま使い、withResponse() の呼び出しから console.log() までのブロック全体を次の形に置き換えます。2 回目の評価として追記しないでください。
const response = await client.systemOne(operation.request, {
headers: { 'Idempotency-Key': operation.idempotencyKey },
}).asResponse();
const text = await response.text();
console.log(text);asResponse() は本文の読み取りを自分で行います。同じ Promise で解析済みの結果も await しないでください。どちらの方法も 2xx 以外のレスポンスで reject します。 公式の APIError は status、headers、body を公開します。任意のエラー本文ではなく、ヘッダーで安定したエラー分類を確認してください。公式クライアントの models.list() は配列を解除しますが、生の GET /v1/models は { models } を返します。
公式 0.6.0 は TypeScript の契約で null の state、省略または null の指示、null の Noul criteria を許します。core 0.8.0 は非 null の state、明示的な指示、boolean criteria を渡”时は非 null を要求します。どちらのクライアントの型も選択したモデルの機能を上書きしません。公式の timeout は 1 試行あたり、core の timeoutMs は 評価全体の予算です。両方の例でリトライは無効にしています。
中断されたリクエストの復旧
このクイックスタートは送信前に操作を 1 回だけ生成し、メモリ上にしか保持しません。プロセス内のリトライでは、同じ operation.idempotencyKey と operation.request を再利用し、生成ブロックを再実行しないでください。アプリケーションのクラッシュや再起動からの復旧では、実アプリケーションが 最初の送信前に操作全体をジョブ記録へ永続保存し、新しい UUID を生成したりリクエストを組み立て直したりせず、その記録を読み込む必要があります。
結果が不明な場合は、復旧ウィンドウの中で同じ実効モデル、state、質問、拡張フィールド、数値、キーを保持してください。タイムアウトやキャンセルは、課金が回避されたことを証明しません。別のモデルへ黙って差し替えたり、新しい UUID でやり直したりしないでください。同じ入力を意図的に再評価するのは新しい操作であり、新しいキーが必要です。キーはアカウント全体で共有される名前空間を持ち、API キーを変えても操作の名前空間は変わりません。
409 request_in_progress は Retry-After に従って待ち、同じリクエストを復旧することを意味します。409 idempotency_failed は前回の試行が失敗して返金されたことを意味し、意図的な再試行には新しいキーが必要です。保持期限、期限切れ、競合、未確定の課金については 冪等キーとリトライを参照してください。
設定の確認とトラブルシューティング
次の項目を、意思決定を繰り返し送らずに確認してください。パッケージのインストールと設定の確認に推論は不要です。認証付きの モデルカタログのリクエストは、アクセスと利用可能なモデルを、意思決定クレジットを消費せずに確認できます。
| 確認項目 | 確認・修正する内容 |
|---|---|
| 実行環境とパッケージ | 文書どおりの .mts コマンドには Node.js 22.18+ を使い、core 0.8.0 / adapter-system-one 0.7.0 / transport-fetch 0.8.0 の組み合わせに揃えます。 |
| 環境変数が読めない | .env とスクリプトのあるディレクトリで実行し、キーとモデルのプレースホルダーを置き換えます。秘密情報はサーバー側に置き、ログに出しません。 |
| 認証が失敗する | 有効な System One API キーを使います。プロバイダのキーやブラウザセッションは使いません。サポート依頼にキー自体を含めてはいけません。 |
| エンドポイントや HTML が返る | core adapter には https://system-one.dev/v1 を使い、ドキュメントのホストは使いません。公式 TypeSafe クライアントは上のように /v1 を含まないルートを取ります。 |
| モデルやリクエストが拒否される | 現在のカタログの name を正確にコピーし、対応する質問型とリクエスト上限を確認します。3 問の例はテキスト専用のままにします。 |
| 型付き結果が返る | 名前付きの回答、返されたモデル、利用可能な使用量メタデータを確認します。任意の値が不明な場合は不明のままです。確率が操作の指示ではありません。 |
| 課金を照合したい | ヘッダー対応のある統合から X-Request-Id、X-System-One-Credits、X-Idempotency-Replayed を使い、コンソールの利用状況と比較します。 |
| タイムアウト・中断・API エラー | どちらのクイックスタートも再実行して復旧しないでください。元の操作を保持し、冪等キーとリトライのルールに従い、API エラーで判断します。 |
実際の価格と残高を確認してから、初めての本番の意思決定を送ってください。セットアップ完了は課金済みの評価の確認ではありません。
オプション:コードなしで Playground を試す
サインイン後に Playgroundを開きます。ブラウザセッションを使うため、API キーも SDK も不要です。モデルを選び、セレクターの横の Model information で価格と上限を確認してから、顧客サポートの例を読み込みます。State はコンテキスト、Questions は判断と選択肢の説明です。概算クレジットを確認したうえで、例をそのまま実行できます。
これも実際の評価です。回答、任意の分布、課金、所要時間、リクエスト ID を確認し、コンソールの最近の利用状況を見てください。接続が失敗した場合、Run を押しまくらないでください。次回の実行は別で課金される可能性があります。先に利用状況を確認し、必要ならリクエスト ID 付きで support@system-one.devへ連絡します。キーやサインインコードは送りません。