なぜエージェントに認証が必要なのか
AIエージェントがデータベース、サードパーティAPI、クラウド関数などの外部サービスを呼び出すとき、自分自身の身元を証明する必要があります。その証明には主に2つの形式があります。1つは静的なAPIキー(サービスから一度発行される長いランダム文字列)、もう1つはOAuth 2.0(エージェントが資格情報を時間制限のあるアクセストークンと交換するプロトコル)を通じて発行される短命トークンです。どちらも目的は共通しており、リモートサーバーが資格情報を確認し、リクエストを受け入れるかどうかを判断します。
危険なのは資格情報そのものではなく、漏洩したときに何が起こるかです。チャットログ、エラートレース、LLMに送信されるpromptに含まれるAPIキーは、数分以内にスクレイピングされて悪用される可能性があります。本番データベースのパスワードと同じくらい慎重にシークレットを扱うことが、基本的な前提です。
シークレットをどこに保存するか
ソースファイルに資格情報をハードコードしないでください。promptテンプレートに貼り付けないでください。標準的なパターンはランタイムで環境変数から読み込むことで、これによりシークレットはコードベースではなくデプロイ環境に保管されます。
このスニペットでは、キーを環境から読み込み、HTTPヘッダーのBearerトークンとして付与し、ディスクへの書き込みやログへの出力は一切行っていません。環境変数が存在しない場合、エージェントは誤構成を隠すプレースホルダーに黙ってフォールバックするのではなく、明確な起動エラーで迅速に失敗する必要があります。
ローカル開発では、`.env`ファイル(`.gitignore`でバージョン管理から除外された、key=valueペアを保持するプレーンテキストファイル)が便利です。本番環境では、オーケストレーターまたはシークレットマネージャーが値を注入します。いずれにせよ、ルールは同じです。シークレットはコードの外に置くべきです。
OAuthトークンとリフレッシュフロー
静的なキーはシンプルですが柔軟性に欠けます。OAuthトークンは、エージェントがユーザーに代わって動作する場合(例:ユーザーのカレンダーを読み取ったり、アカウントに投稿したり)に適しています。フローは次のようになります。
エージェントはアクセストークンをメモリだけに保存し、リフレッシュトークンはセキュアストアに保存する必要があります。アクセストークンが期限切れになった場合(通常は401レスポンスで示されます)、リフレッシュトークンを使って新しいアクセストークンをバックグラウンドで交換します。ユーザーは再同意を求められません。このリフレッシュロジックを小さなヘルパー関数にまとめることで、呼び出し側のコードをきれいに保てます。
Promptやログでの漏洩を防ぐ
エージェントシステムにおける最も一般的な資格情報漏洩は、意図しないエコーバックです。エージェントがLLMに送信するprompt内にシークレットを含めてしまったり、ロガーがヘッダーを含むリクエスト全体を出力してしまうケースです。どちらも、気をつけることで簡単に防げます。
1つ目の関数は、名前にシークレットの兆候があるコンテキストフィールドをすべて除外します。2つ目は、出力前にAuthorizationヘッダーを黒塗りします。スタックトレース、エラーレポート、ユーザーに表示されるエラーメッセージにも同じサニタイズ処理を適用してください。スタックトレースにトークンが含まれていたら、その時点で既に漏洩しています。
まとめ
3つのルールで大抵のケースをカバーできます。まず、資格情報はコードやpromptではなく環境から読み込むこと。次に、サービスでOAuthがサポートされている場合は、長期間有効なキーよりも短命なトークンを優先し、自動でリフレッシュすること。そして3つ目に、すべてのログ行、エラーメッセージ、promptを潜在的な漏洩経路とみなし、書き出す前に黒塗り処理を行うこと。この3つのルールに従ってもシステムを万全にするわけではありませんが、実際に攻撃者が侵入してくる経路は塞ぐことができます。
レッスンのチェックポイント
学んだ内容を復習し、回答へのフィードバックを受けましょう。