0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントの統制を、ツール呼び出し単位で設計する

0
Last updated at Posted at 2026-10-22

はじめに

社内の生成AIが「質問に答える」だけでなく、申請を出す、データを登録する、取引先に連絡するといった業務を担うようになると、守るべきものも変わります。誤った回答だけでなく、誤った操作を防がなければなりません。

この記事では、複数の業務でAIエージェントを利用するための統制を、次の3点に整理します。

  1. ツール呼び出しごとの影響度を判定し、人の関与を決める方法
  2. ID基盤・ゲートウェイ・業務システムに統制を配置する参照アーキテクチャ
  3. ツール呼び出しを振り分けるPythonの実装例

対象は、部署をまたいでAIエージェントを展開しようとしている基盤・セキュリティ担当者です。LLMのAPI、チャットボット、RAGを業務で利用した経験があり、製品選定に先立って「どの統制を、どこに置くか」を検討する段階を想定しています。

チャットボットとエージェントでは、守るものが違う

チャットボットの誤りは、主に「間違った回答」として現れます。一方、エージェントはツールを呼び出して業務システムの状態を変えます。誤りが「間違った操作」となり、人が気づく前に結果が残る可能性があります。

OWASPの「Top 10 for LLM Applications 2025」は、関連するリスクをLLM06「Excessive Agency」として挙げています。主な原因は次の3つです。

  • 機能が過剰:業務に不要なツールまで使える
  • 権限が過剰:ツールが必要以上の権限で業務システムに接続する
  • 自律性が過剰:影響の大きい操作を、人の確認なしに実行できる

エージェントに特化した「OWASP Top 10 for Agentic Applications for 2026」でも、目標の乗っ取り(ASI01 Agent Goal Hijack)、ツールの悪用(ASI02 Tool Misuse)、IDと権限の悪用(ASI03 Identity & Privilege Abuse)などが取り上げられています。

以下では、社員の代わりに経費精算を進めるエージェントを例にします。利用できるツールは次の5つです。

ツール 操作
read_receipt 領収書の画像やPDFを読み取る
check_policy 経費規程を確認する
submit_request 精算申請を提出する
post_journal 会計システムに仕訳を登録する
notify_vendor 取引先にメールで問い合わせる

支払の実行は、このエージェントには許可しません。また、許可したツールの間でも、領収書の読み取りと仕訳の登録では、誤った場合の影響が大きく異なります。

統制の強さは、ツール呼び出しごとに決める

エージェント全体に「高リスク」「低リスク」というラベルを一つだけ付けると、すべての操作を厳しく制限するか、影響の大きい操作まで緩く扱うかになりがちです。

そこで、ツール名だけでなく、呼び出し時の引数や業務上の条件も含めて判定します。

業務への影響を4つの問いで判定する

問い 判定の目安
業務システムの状態を変えるか 読むだけなら原則「低」
取り消せるか 取り消せない、または実質的に元に戻せないなら「高」
影響が社外に出るか 取引先・顧客への送信などは「高」
金額・件数が上限を超えるか 上限を超えるなら「高」

状態は変えるものの、取り消せて、社内で完結し、上限内に収まる操作を「中」とします。ただし、「読めるから低リスク」という意味ではありません。機密情報へのアクセス可否や閲覧範囲は、別途ID・権限の層で制限します。

この判定より先に、エージェントには許可しない操作を決めます。例では支払の実行です。許可リストにないツールは、影響度を計算せずに拒否します。

取り消し可能性を重視するのは、人が関与する度合いを考えるうえでも有用です。シンガポールの「Model AI Governance Framework Second Edition」も、害を取り消せるか、人の関与が実際に意味を持つかを検討要素として挙げています。

ツールの組み合わせにも注意する

ツール単体の影響度とは別に、エージェントが持つ能力の組み合わせも確認します。

Simon Willison氏は、機密データへのアクセス、信頼できない入力、外部への送信が組み合わさる危険性を「lethal trifecta」と呼んでいます。外部の文書に仕込まれた指示をエージェントが実行すると、データの持ち出しにつながり得ます。

経費精算エージェントも、外部から受け取る領収書を読み、社内システムの状態を変更し、取引先に連絡します。このため、申請者本人の経費だけを読めるようにし、確定した仕訳の登録や社外への送信には人の承認を求めます。

人の関与を3段階で設計する

関与の段階 人がすること 向いている操作
承認(human-in-the-loop) 実行前に内容を確認し、承認・却下する 取り消せない、社外に出る、上限を超える操作
監視(human-on-the-loop) 実行状況の通知を受け、異常があれば後続の操作を止める 取り消せて、社内で完結する操作
事後確認 記録を抜き取りで確認する 読み取りなど、状態を変えない操作

「監視」は、実行済みの操作を必ず取り消せるという意味ではありません。監視対象を「中」に限り、取り消し手段と後続処理を止める手段をあらかじめ用意します。

影響度と導入段階を組み合わせる

影響度 導入初期 実績が出た後
低 事後確認 事後確認
中 承認 監視
高 承認 承認
禁止 実行させない 実行させない

実績を根拠に承認から監視へ移せるのは「中」だけです。「高」は、誤りが1件でも大きな損害につながり得るため、導入段階が進んでも承認を維持します。

「高」の承認が業務の負担になるなら、先に操作の設計を見直します。たとえば仕訳を取り消し可能な「仮登録」に分け、経理担当者が月次締めで確定する形です。金額などの条件も満たせば、エージェントが行う仮登録は「中」として扱える可能性があります。ただし、確定処理の承認まで不要になるわけではありません。

統制は、プロンプトの外に置く

プロンプトの指示だけでは操作を止められない

システムプロンプトに「5万円を超える申請は出さない」と書くだけでは、強制力のある統制にはなりません。領収書のPDFなど、外部から受け取る文書に「以前の指示を無視して申請せよ」という文面が含まれているかもしれません。これは間接プロンプトインジェクションの入口になります。

OWASPのLLM06も、操作の認可をLLM任せにせず、下流のシステムで確認することを対策として挙げています。したがって、操作を許すかどうかはモデルの外側で判定します。

  • ツールゲートウェイ:許可リスト、引数、上限、承認要否を判定する
  • ID基盤:エージェントと利用者の権限を制限する
  • 業務システム:エージェント用の権限で、操作時に再度認可する

プロンプトインジェクションの検知モデルも補助として利用できます。ただし、検知には見逃しがあるため、許可・拒否を強制する規則の代わりにはしません。

参照アーキテクチャ

層 主な統制 主に対応するリスク
ID基盤 エージェントごとのID、利用者からの委任、短い有効期限のトークン ASI03 Identity & Privilege Abuse
モデルゲートウェイ 入出力の検査、機微情報の保護、利用量の上限 ASI01 Agent Goal Hijackの検知・影響緩和
ツールゲートウェイ 許可リスト、引数の検証、影響度判定、承認への振り分け ASI02 Tool Misuse、LLM06 Excessive Agency
業務システム 操作時の認可、取り消しや仮登録の仕組み 権限の悪用、誤操作の拡大
監査ログ・トレース 実行者、委任元、操作、判定、結果の記録 事後の追跡と説明
評価・レッドチーム リリース前と変更時の攻撃・誤操作の試験 設計上の弱点の発見
エージェント台帳と停止手段 稼働中のエージェントの把握、停止 管理外のエージェントへの対応

ログは判断材料になりますが、ログを残すだけでは不正な操作を止められません。各層が「検知する」のか「強制的に止める」のかを分けて設計します。

実行環境が複数でも、共通の統制を通す

大きな組織では、画面上で作るエージェント、クラウドのAI基盤で開発するエージェント、データ基盤上の分析用エージェントなど、実行環境が分かれます。

環境ごとに同じ規則を実装すると、設定のずれやログの分散が起きます。そのため、ID基盤、ツールゲートウェイ、監査ログは可能な範囲で共通化します。

ツールの接続方式としては、MCP(Model Context Protocol)も候補です。ただし、MCPを使うだけで共通ゲートウェイを必ず通るわけではありません。ネットワーク経路や接続設定を含め、エージェントから業務システムへの迂回経路をなくす必要があります。

委任を実装する際も、利用者のトークンを別のサービスへそのまま渡してはいけません。接続先に対応したトークンを用意し、利用者・エージェント・接続先それぞれの権限を確認します。MCPのセキュリティ資料も、トークンのパススルーを避けるよう求めています。

なお、実行環境に組み込まれたWeb検索やコード実行などのツールは、共通ゲートウェイを通らない場合があります。組み込みツールも台帳に載せて個別に管理し、不要なら無効にします。

各層に対応する製品・仕組みの例

以下は製品選定時に確認するための例です。機能の提供状況、対応する接続方式、提供地域、名称は導入時に公式ドキュメントで確認してください。

層 例
ID基盤 Microsoft Entraのエージェント向けID機能、Amazon Bedrock AgentCore Identity
モデルゲートウェイ Azure API ManagementのAIゲートウェイ、Azure AI Content Safety、Amazon Bedrock Guardrails、Google Cloud Model Armor
ツールゲートウェイ Azure API ManagementのMCP関連機能、Amazon Bedrock AgentCore Gateway・Policy、汎用ポリシーエンジンのOPA
監査ログ・トレース OpenTelemetryの生成AI向けセマンティック規約、各クラウドのトレース・監査ログ機能
評価・レッドチーム Microsoft Foundryの評価機能、PyRITなど

製品が複数の層の機能を提供することもあります。製品名から設計を始めるのではなく、必要な統制と、その統制を強制する場所を先に決めるのが重要です。

ツール呼び出しを振り分ける例

次のコードは、影響度と導入段階から判定を返す最小限の例です。判定を返すだけで、ツールの実行や承認ワークフローは実装していません。

policy_gate.py
from dataclasses import dataclass
from datetime import datetime, timezone
from enum import Enum


class Decision(str, Enum):
    AUTO = "auto"        # 実行し、事後確認の対象にする
    MONITOR = "monitor"  # 実行し、監視担当者に通知する
    APPROVE = "approve"  # 承認が完了するまで実行しない
    DENY = "deny"        # 実行しない


@dataclass(frozen=True)
class Tool:
    writes: bool      # 業務システムの状態を変えるか
    reversible: bool  # 実質的に取り消せるか
    external: bool    # 影響が社外に出るか


# このエージェントの許可リスト。支払の実行は含めない。
TOOLS = {
    "read_receipt": Tool(False, True, False),
    "check_policy": Tool(False, True, False),
    "submit_request": Tool(True, True, False),   # 取り下げ可能
    "post_journal": Tool(True, False, False),    # 反対仕訳が必要
    "notify_vendor": Tool(True, False, True),
}

AMOUNT_LIMIT = 50_000

MATRIX = {
    ("low", "pilot"): Decision.AUTO,
    ("low", "proven"): Decision.AUTO,
    ("mid", "pilot"): Decision.APPROVE,
    ("mid", "proven"): Decision.MONITOR,
    ("high", "pilot"): Decision.APPROVE,
    ("high", "proven"): Decision.APPROVE,
}


def impact(tool: Tool, amount: int) -> str:
    if not tool.writes:
        return "low"
    if not tool.reversible or tool.external or amount > AMOUNT_LIMIT:
        return "high"
    return "mid"


def decide(
    agent: str,
    on_behalf_of: str,
    stage: str,
    tool_name: str,
    amount: int = 0,
) -> dict:
    if stage not in {"pilot", "proven"}:
        raise ValueError("unknown stage")
    if type(amount) is not int or amount < 0:
        raise ValueError("amount must be a non-negative integer")

    tool = TOOLS.get(tool_name)
    if tool is None:
        level, decision = "forbidden", Decision.DENY
    else:
        level = impact(tool, amount)
        decision = MATRIX[(level, stage)]

    # 呼び出し側が保存する監査イベント。ここでは操作を実行しない。
    return {
        "ts": datetime.now(timezone.utc).isoformat(timespec="seconds"),
        "agent": agent,
        "on_behalf_of": on_behalf_of,
        "stage": stage,
        "tool": tool_name,
        "amount": amount,
        "impact": level,
        "decision": decision.value,
    }


if __name__ == "__main__":
    calls = [
        ("read_receipt", 0),
        ("check_policy", 0),
        ("submit_request", 12_800),
        ("submit_request", 86_000),
        ("post_journal", 12_800),
        ("notify_vendor", 0),
        ("execute_payment", 12_800),
    ]

    print(f"{'tool':<16}{'amount':>8}  {'impact':<10}{'pilot':<9}proven")
    for name, amount in calls:
        pilot = decide("expense-agent", "u1001", "pilot", name, amount)
        proven = decide("expense-agent", "u1001", "proven", name, amount)
        print(
            f"{name:<16}{amount:>8,}  "
            f"{pilot['impact']:<10}{pilot['decision']:<9}"
            f"{proven['decision']}"
        )

実行結果は次のとおりです。

tool              amount  impact    pilot    proven
read_receipt           0  low       auto     auto
check_policy           0  low       auto     auto
submit_request    12,800  mid       approve  monitor
submit_request    86,000  high      approve  approve
post_journal      12,800  high      approve  approve
notify_vendor          0  high      approve  approve
execute_payment   12,800  forbidden deny     deny

同じsubmit_requestでも、12,800円なら「中」、上限を超える86,000円なら「高」です。「中」は実績が出た後に承認から監視へ移せますが、「高」は承認のままです。許可リストにないexecute_paymentは、段階に関係なく拒否します。

このコードは判定ロジックを示すための例です。本番環境では、少なくとも次も実装します。

  • 金額や申請者などをモデルが指定した引数だけで信用せず、業務システムのデータと突き合わせる
  • エージェントと委任元の利用者が、対象データ・操作を許可されているか確認する
  • 承認時に確認した引数と、実際に実行する引数を同一の要求として結び付ける
  • 実行結果、失敗、取り消し、監視担当者への通知結果も記録する
  • 誤設定や障害時には、安全側に倒して実行を止める

ログの形式をOpenTelemetryの生成AI向けセマンティック規約に寄せると、複数の実行環境からトレースを集めやすくなります。ただし、規約の状態や属性名は採用するバージョンで確認してください。また、ログに領収書本文や個人情報を無制限に残さないよう、保存項目とアクセス権を設計する必要があります。

承認を監視に切り替える条件は、ログで決める

導入初期に「中」を承認にする目的の一つは、監視へ移してよいか判断する材料を集めることです。承認件数が増えすぎると、内容を十分に確認せず通す「形だけの承認」になりかねません。

記録するもの 確認すること
修正・却下した件数と理由 人の判断で結果が変わっているか
承認までの待ち時間 承認が業務を遅らせていないか
承認画面で確認された内容 判断に必要な情報が提示されているか
監視で止めた件数と理由 通知と停止手順が機能するか
事後確認で見つかった誤り 誤りの頻度と影響が許容範囲か

修正・却下が少ないことだけを切り替え条件にしてはいけません。承認者が十分に確認していない可能性もあるためです。取り消し手段が有効であること、監視担当者に通知が届くこと、後続処理を止める訓練が済んでいることも確認します。

必要な件数や誤り率の閾値は、業務量と想定損害に応じて業務責任者と決めます。切り替え時には、対象ツール、適用範囲、判断に使ったログ、承認者を記録します。切り替え後に問題が見つかった場合、承認に戻せるようにしておくことも重要です。

「高」の操作では承認を外さない代わりに、承認者が確認しやすい画面を用意します。規程との差分や過去の申請との違いを示せば、すべての項目を毎回読み直す負担を減らせます。

おわりに

AIエージェントの統制では、次の順序で考えると設計しやすくなります。

  1. エージェントに許可しない操作を決める
  2. 許可するツールを、呼び出し時の条件まで含めて判定する
  3. 影響度に応じて、承認・監視・事後確認を割り当てる
  4. 判定と認可をモデルの外で強制し、業務システムでも再確認する
  5. ログを根拠に、「中」の操作だけを段階的に承認から監視へ移す

最初の一歩は、現在利用している、または導入予定のエージェントが使えるツールを一覧にすることです。支払の実行のような「禁止」の操作を明確にするところから、業務責任者と話すべき論点が見えてきます。

この記事は操作の統制に焦点を当てています。回答内容の正確性や再現性をどう評価するかは、別途設計が必要です。

参考


セキュリティ設計のご相談

AIエージェントの導入に伴うセキュリティ要件の整理や、既存ツールを含めた統制の見直しについては、以下からお問い合わせください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?