listSources
実行しないディスカバリー。型付きフィールドを持つ接続済みソース、ケイパビリティモジュール、関数シグネチャ — 1つの入力から3つのモード。スペックは正確な名前を使用する。
エージェント向け — ガバナンス付きデータツール
SQAIはツール呼び出しモデルに、3つのガバナンス付きツールを通じて構造化データへの読み取り専用アクセスを提供する。モデルは型付きインテントを記述する。コントラクトとポリシーがそれを検証する。決定論的エンジンが実行する。すべての回答は、再現可能なハッシュとともに返される。
Iループの一ターン
“どの地域の総収益が最も高かったか?”ステップを計画し、インテントを記述する。データには触れない。
{ version:"1", kind:"query", spec:{ metric:"revenue", aggregation:"sum", group_by:"region", source:"sales" } }contractハッシュ固定されたケイパビリティコントラクトpolicy実行前にチェックされる許可リストengine決定論的、読み取り専用の実行status: ok · needs_clarification · rejected · erroreast — 2,130.50 · plan_hash f87610d8afeb…okループを抜ける。行または値 — そしてそれを再現するハッシュ。
needs_clarification ↺ループに戻る。質問と候補として見つかった項目 — モデルはスペックを絞り込んで再度呼び出す。カラムを推測することはない。
拒否とエラーは同じ返却レーンを通る — モデルが読める型付き結果であり、実行を中断する例外ではない。
IIツールセット
sqai.tools() が返すのは厳密に3つのツールのみ — 意図的に小さなサーフェスだ。ディスカバリとドライランは実行しない。実行は厳密に1か所でのみ行われる。
listSourcesディスカバリー。型付きフィールドを持つ接続済みソース、ケイパビリティモジュール、関数シグネチャ — 1つの入力から3つのモード。スペックは正確な名前を使用する。
queryDataバージョン管理された1つの入力 — kind による判別共用体: クエリまたは計算。4つの結果、常に型付き、例外なし。
explainQuery実行せずにインテントを解決・検証する。モデルは明確化のデバッグに使用し、開発者はプランのプレビューに使用する。
このセットは generateText または streamText にそのまま渡せる — 型付き、キャストなしで代入可能。 Vercel AI SDK セットアップ →
IIIエラー契約
例外はエージェントの実行を中断する。そのためここでは何も投げない: 曖昧さ、拒否、失敗はすべて型付きステータスとして返され、モデルはステップバジェット内でそれを読み取り、修正できる。
retryable 一時的なものにマークを付ける — network_error · timeout · rate_limited · service_unavailable
queryData — 4つの結果
ok結果: 行または値、出所ハッシュ、宣言済みの切り捨て。plan_hash · invocation_hash · computation_hash · truncatedneeds_clarificationインテントが曖昧だった。質問と候補一覧 — 推測はしない。question · candidates · explanationrejectedリゾルバーがインテントを拒否した。何も実行されていない。rejection_reason · candidates · explanationerror安定したコードを持つ構造化された失敗 — モデルが読み取り、調整する。code · message · retryable · nearest_matches?すべての分岐はデータ。ループはターンを維持する。
原則
コードによるポリシー · ツール入力にポリシーフィールドなし · 縮小のみ
IV原則の適用
業界はこれを本番環境で学んだ — 自律型コーディングエージェントが本番データベースを削除した事例は広く知られている。SQAI の答えは振る舞いではなく構造による: 公開されるサーフェスは設計上読み取り専用だ。書き込みおよび非決定論的カテゴリは生成されず、フラグ、ポリシー、モデル入力のいずれによっても有効化できない。
V配線
1つのパッケージがクライアントをツールにラップする。ソースは初回呼び出し時に遅延接続され、最初の計算でランタイムが一度プロビジョニングされ、その後ウォーム状態を維持する — 実測 0.83 ms。
import { generateText } from "ai";
import { createSQAI } from "@thyn-ai/sqai-ai-sdk";
const sqai = createSQAI({
sources: [{ data: "./data/sales.csv", name: "sales" }],
});
const { text, steps } = await generateText({
model, // any AI SDK model
tools: sqai.tools(), // listSources · queryData · explainQuery
prompt: "Which region had the highest total revenue?",
});サーバーサイド専用 — Next.js では Edge ではなく Node ランタイムを使用すること。
モデルに渡されるもの
切り捨ては常に宣言される — truncated: true、returned_rows < total_rows。サイレントな切り捨ては発生しない。完全な結果はアプリケーションコードから result_id で取得できる。
VIエージェント分析
エージェント分析は既知のパターンで失敗する: 不正なツール呼び出し、モデル自身による計算、誰も検証できない一見もっともな数値。それぞれに対する答えは構造的であり、プロンプトの改善ではない。
バージョン管理された1つの入力が、実行前に検証される。不正または曖昧なインテントは型付きステータスを返す — クラッシュせずにループが継続する。
ここでは違う。計算はエンジンが行う。16問の定量的セットで、エンジンが計算を担うことで同じモデルが 0/16 から 16/16 になった。
すべての回答にハッシュが付与される。同じインテントを同じデータに対して再実行すればハッシュが一致する — TypeScript と Python でバイト単位で同一。
ループはレイテンシを乗算する。クエリプレーンはインプロセスでサブミリ秒で動作し、ウォームコンピュートの実測値は 0.83 ms。
VIIよくある質問
SQL をフィルタリングするのではなく、生成しないこと。ソースを createSQAI() に接続し、モデルに sqai.tools() を渡す: モデルが到達できるサーフェスは設計上書き込みパスを持たない 4,574 の読み取り専用ケイパビリティとソースのみだ。ブロックすべき書き込みカテゴリは存在せず、それを再有効化するモデル入力もない。
queryData は needs_clarification を返し、質問と候補フィールドを提示します。列を推測することはありません。モデルはその質問に答えて再度呼び出します——ループがもう一周するだけです。
ありません。すべての失敗は、安定したコード・メッセージ・再試行フラグを持つ構造化された結果として返されます。曖昧さ、拒否、ポリシー違反、一時的な障害——いずれもモデルが読めるデータとして返ってきます。
できません。allowedSources・allowedFields・allowedFunctions はコードに記述され、createSQAI() 時に設定され、実行前に検査されます。ツールの入力スキーマにポリシーフィールドは存在しません。拒否された機能を指定すると、構造化された policy_denied エラーが返されます。
できます。@thyn-ai/sqai-ai-sdk は、generateText および streamText 向けに型付きツールセットとして3つのツールを提供します。ピア依存は ai ^7.0.0 と zod ^4.0.0、Node 20 以降のサーバーサイド専用です。内部クライアントは、任意のエージェントループに組み込める同一の SDK です。