AI Connect/Core concepts/アーキテクチャ
アーキテクチャ
AI Connect の実際の仕組み:対象とするスコープのチェーン、状態をプロビジョニングするコントロールプレーン、すべてのケイパビリティを実行する MCP ランタイム、マルチユーザー利用を正しく保つルール。
AI Connect は、あなたのコード向けの単一の表面と、その下にある 2 つのプレーンで構成されます。コードは短いハンドルのチェーン、アプリケーション、ユーザー、コネクター、ケイパビリティに対して書かれます。プラットフォームは、誰が何ができるかをプロビジョニングするコントロールプレーンと、各ケイパビリティを列挙して実行する MCP ランタイムの実行プレーンを動かします。この分かれ方を見れば、SDK のすべての挙動が予測可能になります。
チェーン:アプリケーション、ユーザー、コネクター、ケイパビリティ
const user = vinkius.user('alice_123');
const github = user.connector('github');
const capabilities = await user.capabilities();各オブジェクトはスコープを追加するだけです。Vinkius クライアントはアプリケーションのアイデンティティを担います。Application Key はあなたが管理する唯一のシークレットで、自分のアプリのためにしか行動できません。user() はあなたの認証システムの ID でユーザーを紐付けます。Vinkius 側のユーザー ID を解決・同期・保管する必要はなく、プラットフォームはすべて externalId で指定します。connector() はコネクターを 1 つ紐付け、Capability はそのユーザーが実行できる具体的な操作です。
ハンドルの作成はローカルで安価です。connect()、status()、schema()、capabilities()、execute() などの操作を呼び出すまで、プラットフォームには何も接触しません。リクエストごとに新しいチェーンを作れば、コードのスコープは明白に保てます。
2 つのプレーン:コントロールとエクスキューション
プロビジョニングと状態はコントロールプレーンに置かれます。
await user.ensure({ plan: 'pro' }); // provision the user
await github.credentials.set({ TOKEN: 'x' }); // write credentials
await github.status(); // derived readiness
await vinkius.catalog.list(); // discover connectors実行は独立したプレーンにあります。connect() がユーザーの接続を作成(または発見)するとき、AI Connect はその接続専用のデータプレーントークン vk_live_* を 1 つだけ発行し、それを埋め込んだランタイム URL を一度だけ返します。以後この接続から構築される各ケイパビリティはランタイムを事前にバインドするため、呼び出し側がルーティング情報、つまりトークンも接続 ID もエンドポイントも渡すことは一切ありません。
トークンは設計の心臓部です。ツールの列挙は無料、実行はすべてトークンに対して計量されるため、支出・トラフィック・失敗はユーザー接続単位で帰属できます。同時にキルスイッチでもあります。ユーザーが接続を無効化または削除すると、トークンも死に、呼び出しはフェイルクローズします。SDK は失効したトークンを黙って再発行しません。失効した接続がこっそり課金を再開することは不可能です。
すべての接続は MCP サーバー
ランタイムは標準 MCP で会話します。つまり接続済みのユーザーはそれぞれ本物の MCP エンドポイントを持ちます。SDK がケイパビリティの列挙と呼び出しに使うのと同じ表面を、Claude Desktop、Cursor、他のエージェントなど MCP 対応クライアントなら何でも直接接続できます。そのエンドポイントを別クライアントに渡すなら、connect() が返す URL を保管してください。
同じ可搬性はモデル層にも通じます。OpenAI、Anthropic、Gemini、Vercel AI SDK、LangChain、LlamaIndex、Cloudflare Workers AI から中立の JSON Schema 出力まで、依存ゼロの 9 つのアダプターサブパスが CapabilitySet を各プロバイダーのツール形式へ変換します。ピア依存の代わりにファクトリー注入です。モデルでもクライアントでもフレームワークでも乗り換えればよく、ケイパビリティはあなたのまま残ります。
ケイパビリティは所有者と経路を携える
プラットフォームがケイパビリティを列挙するとき、各ケイパビリティはすでに自分のコネクター、そのユーザーの接続、表示名、入力スキーマを把握しています。
const capability = capabilities.findCapability('github__create_issue');
console.log(capability?.rawName); // create_issue
console.log(capability?.connector); // github
console.log(capability?.inputSchema); // JSON Schema of the argumentsこのオブジェクトで execute() を呼ぶと、そのユーザーの認証情報で、そのユーザーの GitHub 上にアクションが実行されます。トークンも接続 ID もエンドポイントも渡す必要はありません。表示名はコネクター単位のNamespace(github__create_issue)付きで、namespaceCapability でカスタマイズできます。CapabilitySet は実用ヘルパー(findCapability、forConnector)を備えた本物の配列なので、配列でこれまでやってきたこと全てと合成できます。そしてケイパビリティは生成したユーザーに紐付くため、あるユーザーのケイパビリティオブジェクトを別のユーザーのリクエストで再利用してはいけません。
集約は設計段階からフォールトトレラント
user.capabilities() は単一の API 呼び出しではありません。プラットフォームは各接続のツールをその接続専用のランタイムで列挙するため、集約はユーザーの ready 接続に対する制限付きファンアウトとなり、単一の集合へマージされます。設計は両方向であなたを守ります。不安定なコネクター 1 個がバッチ全体を沈めることはなく(部分的な失敗はスキップされ onConnectorError で通知され、全接続が失敗した場合のみ呼び出しがスローします)、多数のコネクターが同時に無制限のソケットを開くこともありません。
include/exclude で低コストに範囲を絞り、1 つのコネクターだけが必要なら user.connector(slug).capabilities() で直接取れます。完全なファンアウトをスキップできます。
認証情報はライトオンリー、ステータスは導出値
認証情報は設定でき、コネクターの要求事項(credentials.schema())を尋ね、設定済みのフィールド(credentials.status())を確認できますが、シークレットの値が返ることは決してありません。値はプラットフォームのボールトに保管され、モデルは生のシークレットを受け取りません。準備完了判定はバックエンドの責任で、状態は not_connected、needs_credentials、ready、disabled の 4 つのいずれかとして提示されます。ケイパビリティを供給するのは ready のコネクターだけなので、設定途中の接続が壊れたツールをエージェントループに漏らすことはありません。
すべての呼び出しでプラットフォームがやってくれること
- 実行は正規化される。 コネクターの下で REST、GraphQL、ストリーミングのどれを話していても、
execute()は{ content, isError }という単一の構造化結果を返します。 - 安全な再試行は自動。 一時的な不安定さは冪等な操作で自動的に再試行されます。高々 1 回だけ実行すべき操作には、安定した空でない
idempotencyKeyをexecute()に渡してください。 - ガバナンスは組み込み済み。 あらゆる実行は計量され、コンソールの AI Governance 面によって監視されます。コネクターごと、ユーザーごとのトラフィック、支出、失敗、セキュリティ体制まで。
失敗のチャネルは 2 つ、ルールは 1 つ
execute() は、実行されて問題を報告したアクションと、そもそも完了しなかった呼び出しを区別します。
const result = await capability.execute(args, { idempotencyKey });
if (result.isError) {
// ケイパビリティは実行され失敗を報告した:エージェントに返す。
}プラットフォーム側の問題は VinkiusError のサブクラスをスローします。AuthError、ConnectorNotConnectedError、RateLimitError、QuotaError、ValidationError など。それぞれ status、code、requestId を運びます。isError の結果はモデルに返して回復させ、スローされたエラーは catch してアプリケーションの対応を決めます。この 2 つを混同すると、アクションが現実世界に届いたのかどうかが見えなくなります。
状態はハンドルごとにローカル
ハンドルは必要とした最初の操作の時点でユーザーの接続とそのランタイムを解決し、そのハンドルの生存中は両方を再利用します。同じハンドルへの繰り返し呼び出しは解決をスキップします。グローバルなキャッシュはありません。新しいハンドルは再解決し、disconnect() はそのハンドルの記憶を消し、ResolverCache はあなたのメモ化に組み込めるオプショナルなユーティリティです。だから安全なパターンはリクエストごとの新しいハンドルチェーンであり、同じリクエスト内で再利用するのは純粋な利得です。
