マルチテナントのエージェントインフラは、認証済みコンテキストからテナントscopeを導出し、ツール、データベース、queue、cache、成果物、認証情報、ログまで維持する必要があります。プロンプトやモデル生成引数内のtenant_idは分離になりません。
エージェントはバックエンドアクションの数と種類を増やします。そのため境界が一つ欠けると、人間が制限されたインターフェースを操作しなくてもテナントを越える可能性があります。モデルが混乱している場合、取得contentが敵対的な場合、二つのリソースが同じ表示名を持つ場合にも、制御が機能しなければなりません。
リソース入力を受け取る前にIDを紐づける
セッションまたはアプリケーション認証情報からテナントを解決します。そのIDをエージェント・コントロールプレーンへ渡し、サーバー側のリソース記録に対して要求されたアクションを認可します。
flowchart LR
Request[Agent tool call] --> Session[Authenticated session]
Session --> Scope[Tenant and delegated scope]
Scope --> Policy{Authorize resource and action}
Policy -->|allow| Tool[Execute scoped tool]
Policy -->|deny| Audit[Record denial]
Tool --> DB[(Tenant-scoped data)]
Tool --> Queue[(Tenant-scoped work)]
Tool --> Artifacts[(Tenant-scoped artifacts)]
ツール引数から認証済みテナントを上書きできないようにします。リソースIDが全体で一意でも、現在のテナント配下で検索します。これにより認可ルールが明示されます。
データベース分離モデルを意図的に選ぶ
| モデル | 境界 | 運用上の影響 |
|---|---|---|
| 共有table | テナントcolumn、row-level policy、スコープ付きquery | migrationは単純だが、すべてのアクセス経路が正しいポリシーと接続roleに依存 |
| テナントごとのschema | 一つのデータベース内の個別namespace | 名前の境界は強くなるが、schemaごとのmigrationと接続設定が必要 |
| テナントごとのdatabase | 個別のデータベースと認証情報 | 最も強い保存境界だが、provisioning、pooling、backup、migrationの作業が増える |
アプリケーションroleが迂回できず、テナントコンテキストをサーバー側で設定するなら、row-level securityは強い制御になります。アプリケーションのWHERE句より本質的に弱いわけではなく、保証はポリシー、role、すべての代替接続経路に依存します。
規制要件、非常に大きいテナント、顧客管理の暗号化、独立したrestore要件には、分離度の高いモデルを使います。呼び出し元がエージェントという理由だけでdatabase-per-tenantを選ばないでください。
データベースパターンのガイドでは、複合テナントkeyと操作constraintを紹介しています。
すべての共有subsystemへscopeを伝える
データベース分離は複数ある境界の一つです。
- cache keyのprefixにユーザーが制御できないテナント識別子を使い、無効化にも含める。
- 認証済みサーバーコンテキストからqueue messageへテナントscopeを入れ、workerがconsumeするときに再認可する。
- object keyとvector collectionをnamespace化し、signed URL発行や検索前に所有権を確認する。
- browserとsandbox sessionをテナント所有にし、ファイルシステムと認証情報を分ける。
- tool sessionとOAuth grantを代理対象のテナントとユーザーへ限定する。
- rate limitと支出制限をテナント、エージェント、影響の大きいアクションごとに分ける。
二つのテナントで同じリソース名をテストします。production、orders、mainのような表示名は、モデルがコンテキストからリソースを選ぶ際に衝突しやすい箇所です。
認証情報とログにテナントを認識させる
プロバイダー認証情報は、テナント所有のsecret reference配下に保存します。tool workerには、認可された参照だけを解決できるようにします。共有プロバイダーアカウントにも、テナント単位の課金と取り消しが必要です。
調査のため、ログとトレースにはテナントフィールドが必要です。ただしobservabilityへのアクセスもテナントに限定します。export前にプロンプト、ツール引数、結果をredactします。全テナントを検索できる内部ダッシュボードは、信頼された小規模な運用チームには適切な場合がありますが、特権surfaceであることに変わりはありません。
NISTのゼロトラスト・アーキテクチャは、ネットワーク上の位置ではなく、IDとリソースに基づくリクエスト単位の判断としてアクセスを捉えます。これはbackground workerと内部tool callにも当てはまります。プラットフォーム内部で動くというだけで広いアクセスを与えてはいけません。
quotaと権限を混同せずloopを抑える
同時実行、ツール呼び出し、モデル支出、ストレージ、失敗の反復をテナント単位で制限します。破壊的または高額なツールにはより狭い上限を設けます。loopは対象テナントの影響を受けるworkloadを一時停止し、人間が調査できる操作記録を残す必要があります。
上限は量を抑えるもので、認可されていない呼び出しを許容するものではありません。quotaを消費する前に認可し、ポリシー拒否をエージェントが再試行しないよう、安定したエラー分類を返します。
テナントグラフ全体の削除を設計する
テナント削除経路では、データベース、cache済み値、queue内の作業、成果物、メモリ、index、browser session、sandbox、認証情報、ログ、backup、active operationをinventoryします。即時削除するもの、後から失効するもの、法務・セキュリティ上の理由で保持するものを決めます。
データを削除する前に新規作業を停止し、認証情報を取り消します。部分的なクリーンアップは起きやすいため、削除を再開可能かつ冪等にします。削除したcontent自体を保持せず、各リソースの完了を記録します。
意図的に似せたデータで分離をテストする
名前が重複し、IDがよく似た二つのテストテナントを作成します。すべてのツール、worker、cache、queue、成果物の経路からアクセスを試します。モデルへテナントIDを切り替えるよう指示する取得ドキュメントも含めます。モデルが何を出力しても、サーバーはアクションを拒否する必要があります。
以下のプロンプトは、これをリポジトリ固有のテスト計画へ変換します。データベース図だけでは分離を証明できないため、最初にテナントscopeの起点を特定します。