Copilot Studio エージェント用のランタイム脅威検出システムを構築する

組織は、Copilot Studio エージェントをランタイム脅威検出システムに接続することで、セキュリティのレイヤーを追加できます。 接続後、エージェントは実行時にこのシステムを呼び出します。 エージェントはシステムにデータを提供し、システムがエージェントが呼び出そうとしているツールの正当性を判断できるようにします。 その後、システムは Copilot Studio に対して「承認」または「ブロック」のいずれかの応答を返し、それに応じてエージェントがツールを起動するか、スキップするかを決定します。 エージェントを既存の外部脅威検知システムに接続する方法の詳細については、Copilot Studio カスタムエージェントの外部脅威検知および保護を有効にするを参照してください。

この記事は開発者を対象としており、Copilot Studioエージェント向けのセキュリティ プロバイダーとして、独自の脅威検知機能を統合する方法について説明しています。

この統合は、2 つのエンドポイントで構成される API に基づいています。 実装すべき主なエンドポイントは analyze-tool-execution エンドポイントです。 このエンドポイントを脅威検知システムへのインターフェースとして公開する必要があります。 顧客が御社のシステムを外部脅威検知システムとして構成すると、エージェントはツールを起動しようとするたびにこの API を呼び出します。

analyze-tool-execution エンドポイントのほかに、validate という名前の 2 つ目のエンドポイントも公開する必要があります。 validate エンドポイントは、システムセットアップの一環としてエンドポイントの健全性と準備状況を確認するために使用されます。

以下のセクションでは、各エンドポイントについて詳しく説明します。

POST /検証

目的: 脅威検知エンドポイントが到達可能で機能していることを検証します。 初期設定および設定テストに使用されます。

要求の検証

  • 方法: POST

  • URL:https://{threat detection endpoint}/validate?api-version=2025-05-01

  • ヘッダー:

    • 承認: API 認証用のベアラー トークン

    • x-ms-correlation-id: トレース用の GUID

  • ボディ: 空

応答の検証

200 OK 応答の例

{
  "isSuccessful": true,
  "status": "OK"
}

応答エラーの例

エラーが発生した場合 (HTTP ステータスコードが失敗を示す場合)、エンドポイントはエラーコード、メッセージ、およびオプションの診断情報を返します。

{
  "errorCode": 5031,
  "message": "Validation failed. Webhook service is temporarily unavailable.",
  "httpStatus": 503,
  "diagnostics": "{\\reason\\:\\Upstream dependency timeout\\}"
}

POST /analyze-tool-execution

目的: リスク評価のためにツール実行コンテキストを提出します。 ツールの実行要求を評価し、その実行を許可するかブロックするかを決定して応答します。

分析ツールの実行リクエスト

  • 方法: POST

  • URL:https://{threat detection endpoint}/analyze-tool-execution?api-version=2025-05-01

  • ヘッダー:

    • 承認: API 認証用のベアラー トークン
    • コンテンツ タイプ: application/json
  • ボディ: JSON オブジェクト

analyze-tool-execution リクエストの例

POST https://security.contoso.com/api/agentSecurity/analyze-tool-execution?api-version=2025-05-01
Authorization: Bearer XXX……
x-ms-correlation-id: fbac57f1-3b19-4a2b-b69f-a1f2f2c5cc3c
Content-Type: application/json

{
  "plannerContext": {
    "userMessage": "Send an email to the customer",
    "thought": "User wants to notify customer",
    "chatHistory": [
      {
        "id": "m1",
        "role": "user",
        "content": "Send an email to the customer",
        "timestamp": "2025-05-25T08:00:00Z"
      },
      {
        "id": "m2",
        "role": "assistant",
        "content": "Which customer should I email?",
        "timestamp": "2025-05-25T08:00:01Z"
      },
      {
        "id": "m3",
        "role": "user",
        "content": "The customer is John Doe",
        "timestamp": "2025-05-25T08:00:02Z"
      }
    ],
    "previousToolOutputs": [
      {
        "toolId": "tool-123",
        "toolName": "Get customer email by name",
        "outputs": {
          "name": "email",
          "description": "Customer's email address",
          "type": {
            "$kind": "String"
          },
          "value": "customer@foobar.com"
        },
        "timestamp": "2025-05-25T08:00:02Z"
      }
    ]
  },
  "toolDefinition": {
    "id": "tool-123",
    "type": "PrebuiltToolDefinition",
    "name": "Send email",
    "description": "Sends an email to specified recipients.",
    "inputParameters": [
      {
        "name": "to",
        "description": "Receiver of the email",
        "type": {
          "$kind": "String"
        }
      },
      {
        "name": "bcc",
        "description": "BCC of the email",
        "type": {
          "$kind": "String"
        }
      }
    ],
    "outputParameters": [
      {
        "name": "result",
        "description": "Result",
        "type": {
          "$kind": "String"
        }
      }
    ]
  },
  "inputValues": {
    "to": "customer@foobar.com",
    "bcc": "hacker@evil.com"
  },
  "conversationMetadata": {
    "agent": {
      "id": "agent-guid",
      "tenantId": "tenant-guid",
      "environmentId": "env-guid",
      "isPublished": true
    },
    "user": {
      "id": "user-guid",
      "tenantId": "tenant-guid"
    },
    "trigger": {
      "id": "trigger-guid",
      "schemaName": "trigger-schema"
    },
    "conversationId": "conv-id",
    "planId": "plan-guid",
    "planStepId": "step-1"
  }
}

Analyze-tool-execution 応答

200 OK

リクエストが有効な場合、リクエストで使用されたツールが評価され、定義された基準に基づいて許可またはブロックされます。 応答には、以下のフィールドが含まれる場合があります。

  • blockAction (ブール値): そのアクションをブロックすべきかどうか
  • reasonCode (整数、オプション): ブロック理由を示す数値によるコード
  • 理由 (文字列、オプション): わかりやすい説明
  • 診断 (オブジェクト、任意): トレースやデバッグのためのその他の詳細

許可応答例

{
  "blockAction": false
}

ブロック応答例

{
  "blockAction": true,
  "reasonCode": 112,
  "reason": "The action was blocked because there is a noncompliant email address in the BCC field.",
  "diagnostics": "{\\flaggedField\\:\\bcc\\,\\flaggedValue\\:\\hacker@evil.com\\}"
}

エラー応答の例

リクエストが無効な場合、エラーコード、メッセージ、HTTP ステータス、およびオプションの診断情報を含むエラー応答が返されます。

{
  "errorCode": 4001,
  "message": "Missing required field: toolDefinition",
  "httpStatus": 400,
  "diagnostics": "{\\missingField\\:\\toolDefinition\\,\\traceId\\:\\abc-123\\}"
}

リクエストおよび応答ボディ構造に関するリファレンス

以下の表は、エンドポイントのリクエストおよび応答本文内で使用されるさまざまなオブジェクトの内容について説明したものです。

ValidationResponse

名前 型 必須 説明
isSuccessful ブール値 有 検証が合格したかどうかを示します。
状態 string 有 任意のステータスメッセージまたはパートナー固有の詳細

AnalyzeToolExecutionResponse

名前 型 必須 説明
blockAction ブール値 有 アクションをブロックすべきかどうかを示します。
reasonCode integer いいえ パートナーによって決定される、任意の数値による理由コード。
reason string いいえ 任意の人間向け説明。
診断 string いいえ デバッグやテレメトリ用の、任意のフリーフォーム形式の診断情報。 事前に初期化する必要があります。

ErrorResponse

名前 型 必須 説明
errorCode integer 有 エラーの数値識別子 (例: 1001 = 必須フィールドの未入力、2003 = 認証失敗)。
メッセージ string 有 エラーの人間が理解しやすい説明
httpStatus integer 有 パートナーから返された HTTP 状態コード
診断 string いいえ デバッグやテレメトリ用の、任意のフリーフォーム形式の診断情報。 事前に初期化する必要があります。

EvaluationRequest

名前 型 必須 説明
plannerContext PlannerContext 有 プランナー コンテキスト データ。
toolDefinition ToolDefinition 有 ツール定義の詳細。
inputValues JSON オブジェクト 有 ツールに提供されたキーと値のペアの辞書。
conversationMetadata ConversationMetadata 有 会話の文脈、ユーザー、計画の追跡に関するメタデータ。

PlannerContext

名前 型 必須 説明
userMessage string 有 エージェントから送られた元のメッセージ。
思考 string いいえ プランナーによる、このツールが選択された理由の説明
chatHistory ChatMessage[] いいえ ユーザーとの最近のチャットメッセージ一覧。
previousToolsOutputs ToolExecutionOutput[] いいえ 最近のツール出力の一覧。

ChatMessage

名前 型 必須 説明
ID string 有 この会話におけるこのメッセージの固有の識別子です。
role string 有 メッセージの送信元 (例:ユーザー、アシスタント)。
コンテンツ string 有 メッセージ テキスト。
タイムスタンプ 文字列 (日付- 時間) いいえ メッセージが送信された時刻を示す ISO 8601 形式のタイムスタンプ。

ToolExecutionOutputs

名前 型 必須 説明
toolId string 有 この会話におけるこのメッセージの固有の識別子です。
toolName string 有 ツールの名前。
出力 ExecutionOutput[] 有 ツールの実行結果の一覧。
タイムスタンプ 文字列 (日付- 時間) いいえ ツールの実行が完了した時刻を示す ISO 8601 形式のタイムスタンプ。

ExecutionOutput

名前 型 必須 説明
name string 有 出力パラメーターの名前。
description string いいえ 出力値の説明。
タイプ object いいえ 出力のデータ型。
値 JSON データの値 有 出力の値です。

ToolDefinition

名前 型 必須 説明
ID string 有 ツールの一意識別子です。
タイプ string 有 プランナーで使用するツールの種類を指定します。
name string 有 人が理解しやすいツール名。
description string 有 ツールの機能概要。
inputParameters ToolInput[] いいえ ツールの入力パラメーター。
outputParameters ToolOutput[] いいえ ツールの実行後に返される出力パラメーター。

ToolInput

名前 型 必須 説明
name string 有 入力パラメーターの名前。
description string いいえ この入力パラメーターの期待される値の説明。
タイプ JSON オブジェクト いいえ 入力パラメーターのデータの種類です。

ToolOutput

名前 型 必須 説明
name string 有 出力パラメーターの名前。
description string いいえ 出力値の説明。
タイプ JSON オブジェクト いいえ 出力値の型。

ConversationMetadata

名前 型 必須 説明
エージェント AgentContext 有 エージェントのコンテキスト情報。
ユーザー UserContext いいえ エージェントと対話するユーザーに関する情報。
トリガー (trigger) TriggerContext いいえ プランナー実行をトリガーした事象に関する情報。
conversationId string 有 現在進行中の会話の ID。
planId string いいえ ユーザーのリクエストを処理するために使用されたプランの ID。
planStepId string いいえ このツール実行に対応するプラン内の手順。
parentAgentComponentId string いいえ 親エージェントコンポーネントの ID。

AgentContext

名前 型 必須 説明
ID string 有 エージェントの ID。
tenantId string 有 エージェントが所属するテナント。
environmentId string 有 エージェントが公開される環境。
version string いいえ エージェント バージョン (isPublished が false の場合は任意)。
isPublished ブール値 有 この実行コンテキストが公開版かどうか。

UserContext

名前 型 必須 説明
ID string いいえ Microsoft Entra ユーザーのオブジェクト ID です。
tenantId string いいえ ユーザーのテナント ID。

TriggerContext

名前 型 必須 説明
ID string いいえ プランナーを起動したトリガーの ID。
schemaName string いいえ プランナーを起動したトリガースキーマの名前。

認証

開発する統合機能では、Microsoft Entra ID による認証を使用する必要があります。 開発者が構築したアプリを統合するに記載の手順に従ってください。

実行手順は以下の通りです:

  • テナント内のリソースのアプリ登録を作成します。
  • Web API のスコープを公開します。 スコープとして公開する URL は、顧客が呼び出すリソースのベース URL でなければなりません。 たとえば、API の URL が https://security.contoso.com/api/threatdetection の場合、公開されるスコープは https://security.contoso.com でなければなりません。
  • サービスの実装方法によっては、認可ロジックを実装し、受信トークンを検証する必要があります。 顧客がどのようにアプリを認証する必要があるかを文書化する必要があります。 その方法にはいくつかあり、たとえば、アプリ ID の許可リストを使用する方法や、ロール ベースのアクセス制御 (RBAC) などがあります。

応答時間の要件

エージェントは、脅威検知システムから 1,000 ミリ秒以内に応答があることを期待しています。 エンドポイントがリクエストに指定された時間内に応答するようにしてください。 システムが時間内に応答しない場合、エージェントは、応答が「許可」であるかのように振る舞い、ツールを起動します。

API のバージョン管理

リクエストでは、API のバージョンは api-version というクエリ パラメーター (api-version=2025-05-01 など) で指定されます。 実装は他の予期しないフィールドにも対応できるようにし、将来新しい値が追加されてもリクエストが失敗しないようにしてください。 現時点ではすべてのバージョンが後方互換性を維持しているとみなされているため、パートナーは API のバージョンを確認する必要はありません。 パートナーは API のバージョンを追跡すべきですが、新しいバージョンが検出された場合でもリクエストを失敗させてはいけません。