ネットワークスイッチに接続された青いイーサネットケーブル
現場の実践

AIエージェント運用の落とし穴、監視すべきは言語でなくツール呼び出し

目次を見る

社内でLangChainやOpenAI Agents SDKを使ったAIエージェント(目標を受け取り、自律的にツールを呼び出しながら処理を進めるプログラム)を導入し、これから本番運用や監視設計を担当するインフラ・SREの方に向けた内容です。

エージェントを「PythonかTypeScriptか」という開発言語の議論で語る記事は多くあります。しかし運用監視の現場で本当に問題になるのは、実装言語ではなく「エージェントが何を呼び出し、何を漏らしたか」を追えているかどうかです。この記事では、その見落としが具体的にどんな障害・インシデントにつながるかを整理します。

何が起きるか:ツール呼び出しの異常が「エラー」として見えない

AIエージェントは、モデルが目標を受け取り、行動を決め、外部ツール(API・DB・シェルコマンドなど)を呼び出し、結果を読んでまた次の行動を決めるというループで動きます。

このループの中で厄介なのは、プロンプトインジェクション(Webページやメールなど、エージェントが読み込む外部コンテンツに悪意ある指示を埋め込み、本来の指示を上書きする攻撃)が成立しても、システムログ上は「正常に処理を完了した」ように見えてしまう点です。

チャットボットへの攻撃なら被害は「おかしな回答」で済みます。しかしエージェントは実際にツールを呼び出し、権限を持って行動できるため、被害は「おかしな行動」として実インフラに波及します。たとえば顧客データを扱うRAG(検索拡張生成、外部文書を検索してモデルの回答に反映させる仕組み)連携エージェントが、汚染された文書を読み込んだ結果、意図しないAPIに機密情報を送信してしまうケースが考えられます。

この手の障害は、CPU使用率やレイテンシといった従来のAPM(アプリケーション性能監視)指標にはほぼ現れません。処理は「成功」として完了するからです。

なぜ起きるか:監視対象の設計がリクエスト単位のまま止まっている

原因を段階的に分解すると、まず監視の粒度がずれています。従来のWebサービス監視は「リクエスト→レスポンス」の単位で設計されています。しかしエージェントは1つのユーザーリクエストの裏で、モデル呼び出し・ツール呼び出し・外部データ取得を何段階も連鎖させます。1段階目だけ見ても異常は分かりません。

次に、ツール呼び出しのパラメータが検証されていません。エージェントがツールを呼ぶとき、そのパラメータは攻撃者が仕込んだ入力に誘導された値かもしれません。従来のAPI認証・認可の仕組みは「誰が呼んだか」は検証しますが、「なぜそのパラメータを送ろうとしたか」までは検証しません。

さらに、MCP(Model Context Protocol、モデルと外部ツールを言語に依存せず接続する標準規格)経由でツールを呼ぶ構成が増えており、TypeScriptで書かれたエージェントがPython製のツールサーバーを呼ぶ、といった混在環境も一般化しています。ツールがどの言語で書かれていても攻撃の起点になり得るため、「うちはPythonを使っていないから対象外」という判断はできません。

最後に、多くのチームがセキュリティ検証を「一度スキャンして終わり」にしています。実際の攻撃は、攻撃文を生成し送信し、応答を評価し、内容を変えて再送する、という多段階の対話型プロセスです。一度きりのチェックでは、複数ターンにわたって少しずつ指示を歪めていく「ゴールハイジャック」を検出できません。

自分のプロジェクトが該当するか確認する方法

以下の観点で、現状のエージェント運用を点検してみてください。

  • エージェントのログに「呼び出したツール名」「渡したパラメータ」「呼び出し元となったモデルの推論理由」の3点が記録されているか
  • 外部コンテンツ(Web検索結果・添付ファイル・RAGで取得した文書)を読み込む処理と、権限を持つツール呼び出し処理が同一エージェント内で分離されずに動いているか
  • MCPサーバーや外部ツールへの接続設定ファイル(多くはYAMLやJSON)で、ツールごとに許可される操作範囲が制限されているか
  • セキュリティ検証を導入済みの場合、それが単発スキャンか、複数ターンの対話をシミュレートする仕組みかどちらか

設定ファイルを確認する際は、エージェントフレームワークの設定にある toolsallowed_tools に類する項目を探し、ワイルドカードで全許可になっていないかを見るのが最初の一歩です。n8n(ノーコードでワークフローを組めるオートメーションツール)のような低コード基盤を使っている場合は、ワークフロー内でモデルの出力が直接シェルノードやHTTPリクエストノードに渡っていないかを確認してください。

対策の手順

1. ログの粒度を「ツール呼び出し単位」に上げる

リクエスト全体ではなく、モデルが下した各アクション判断とツール呼び出しごとに、入力・出力・パラメータをログへ残す設定に変更します。既存のAPMにトレースIDを持たせ、1リクエスト内の複数ツール呼び出しを時系列で追えるようにするのが現実的です。

2. スキャン型のセキュリティ検証をまず導入する

YAMLベースの設定で検証を書けるpromptfoo(Node.js製のLLM評価・レッドチーミングツール)なら、Pythonを書かずに直接・間接プロンプトインジェクションの基本的な検証を始められます。まずはここから始め、検証対象に「システムプロンプトの漏洩」「ツール誤用」「データ持ち出し」の3パターンを含めてください。

3. 多段階攻撃への耐性を評価する

スキャンだけでは、徐々に指示を歪めていく多段階攻撃は見つかりません。garak(モデルのjailbreakや漏洩耐性を調べるPython製スキャナ)やPyRIT(Microsoft製の多段階自動レッドチーミングフレームワーク)のような、対話を繰り返しながら攻撃を仕掛けるツールでの評価も検討してください。ここは正直なところPythonの知見がほぼ必須になる領域です。

4. インシデント対応手順にエージェント特有の項目を足す

既存の障害対応Runbookに、「エージェントがどのツールをどのパラメータで呼んだか」を確認する手順を追加します。これがないと、根本原因分析(RCA)の際に「なぜこの外部呼び出しが発生したか」を再現できません。

5. アプリ側の脆弱性診断(ペネトレーションテスト)とモデル挙動の検証を分けて管理する

認証・API・権限まわりの一般的なペネトレーションテストと、モデル自体の挙動を狙うレッドチーミングは目的が異なります。多くのエージェント運用では両方が必要になるため、担当と実施頻度を分けて管理表に記載しておくと運用が回りやすくなります。

まとめ

エージェントのセキュリティ問題は、CPUやレイテンシのグラフには出てきません。まずログの粒度をツール呼び出し単位に上げ、allowed_tools のような設定でワイルドカード許可になっていないかを見直してください。

そのうえでpromptfooによる単発スキャンから着手し、余力があればgarakやPyRITで多段階攻撃への耐性まで確認するのが現実的な進め方です。障害対応のRunbookにツール呼び出しの再現手順を足すことも忘れずに進めてください。

参考

Do You Really Need Python to Build AI Agents and Test Their Security?

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。