组织可以通过将其连接到运行时威胁检测系统,向其Copilot工作室代理添加一层安全性。 连接后,代理在运行时调用此系统。 代理向系统提供数据,以便系统可以确定代理计划调用的工具是否合法。 然后,系统会回复 Copilot Studio,其响应为“批准”或“阻止”,导致代理相应地调用或跳过该工具。 有关如何将代理连接到现有外部威胁检测系统的详细信息,请参阅 为 Copilot Studio 自定义代理启用外部威胁检测和保护。
本文面向开发人员,介绍如何将您自己的威胁检测功能集成到 Copilot Studio 智能体中,作为安全提供商。
集成基于由两个终结点组成的 API。 需要实现的主要终结点是 analyze-tool-execution 终结点。 您需要将此终结点作为接口公开到您的威胁检测系统。 客户将系统配置为其外部威胁检测系统后,代理每次打算调用工具时都会调用此 API。
analyze-tool-execution除了终结点之外,还需要公开第二个终结点(称为validate)。 终结点 validate 用于在系统设置过程中检查终结点的运行状况和就绪情况。
以下部分详细介绍了每个终结点。
POST /验证
目的: 验证威胁检测终结点是否可访问且正常运行。 用于初始设置和配置测试。
验证请求
方法: POST
URL:
https://{threat detection endpoint}/validate?api-version=2025-05-01标题:
授权:用于 API 身份验证的持有者令牌
x-ms-correlation-id:用于跟踪的 GUID
身体: 空
验证响应
200 正常响应示例
{
"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 身份验证的持有者令牌
- Content-Type: 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 正常
当请求 有效时,根据定义的条件评估请求中所指定的工具使用,并对其 给予允许 或 给予阻止。 响应可以包含以下字段:
- 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\\}"
}
请求和响应主体结构参考
下表描述了终结点的请求和响应正文中使用的各种对象的内容。
验证响应
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| isSuccessful | 布尔 | 是的 | 指示验证是否已通过。 |
| 状态 | 字符串 | 是的 | 可选状态消息或特定于合作伙伴的详细信息。 |
AnalyzeToolExecutionResponse
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| blockAction | 布尔 | 是的 | 指示是否应阻止该操作。 |
| 原因代码 | 整数 | 否 | 由合作伙伴确定的可选数字原因代码。 |
| 原因 | 字符串 | 否 | 可选的人工可读说明。 |
| diagnostics | 字符串 | 否 | 用于调试或遥测的可选任意形式诊断信息。 必须预先序列化。 |
错误响应
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 错误代码 | 整数 | 是的 | 错误的数值标识符(例如,1001 = 缺少字段,2003 = 身份验证失败)。 |
| 消息 | 字符串 | 是的 | 错误的人工可读解释。 |
| httpStatus | 整数 | 是的 | 合作伙伴返回的 HTTP 状态代码。 |
| diagnostics | 字符串 | 否 | 用于调试或遥测的可选任意形式诊断信息。 必须预先序列化。 |
评估请求
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| plannerContext | PlannerContext | 是的 | Planner 上下文数据。 |
| 工具定义 | ToolDefinition | 是的 | 工具定义详细信息。 |
| 输入值 | JSON 对象 | 是的 | 提供给该工具的键值对字典。 |
| conversationMetadata | ConversationMetadata | 是的 | 有关聊天上下文、用户和计划跟踪的元数据。 |
PlannerContext
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 用户消息 | 字符串 | 是的 | 代理发送的原始消息。 |
| 思想 | 字符串 | 否 | 为什么选择此工具的计划员解释。 |
| 聊天记录 | ChatMessage[] | 否 | 与用户交换的最新聊天消息列表。 |
| 先前工具输出 | 工具执行输出[] | 否 | 最近工具输出的列表。 |
聊天消息
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | 字符串 | 是的 | 会话中此消息的唯一标识符。 |
| 角色 | 字符串 | 是的 | 消息来源(例如用户、助理)。 |
| 内容 | 字符串 | 是的 | 消息文本。 |
| 时间戳 | string (date-time) | 否 | ISO 8601 时间戳,指示消息何时发送。 |
工具执行输出
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 工具ID | 字符串 | 是的 | 会话中此消息的唯一标识符。 |
| toolName | 字符串 | 是的 | 工具的名称。 |
| 输出 | ExecutionOutput[] | 是的 | 工具执行输出的列表。 |
| 时间戳 | string (date-time) | 否 | ISO 8601 时间戳,指示工具执行完成的时间。 |
执行输出
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 姓名 | 字符串 | 是的 | 输出参数的名称。 |
| 说明 | 字符串 | 否 | 输出值的说明。 |
| 类型 | 对象 | 否 | 输出的数据类型。 |
| value | JSON 数据值 | 是的 | 输出值。 |
工具定义
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | 字符串 | 是的 | 工具的唯一标识符。 |
| 类型 | 字符串 | 是的 | 指定规划器中使用的工具类型。 |
| 姓名 | 字符串 | 是的 | 工具的可读名称。 |
| 说明 | 字符串 | 是的 | 该工具的作用摘要。 |
| 输入参数 | ToolInput[] | 否 | 工具的输入参数。 |
| 输出参数 | ToolOutput[] | 否 | 执行后工具返回的输出参数。 |
工具输入
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 姓名 | 字符串 | 是的 | 输入参数的名称。 |
| 说明 | 字符串 | 否 | 此输入参数的预期值的说明。 |
| 类型 | JSON 对象 | 否 | 输入参数的数据类型。 |
工具输出
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 姓名 | 字符串 | 是的 | 输出参数的名称。 |
| 说明 | 字符串 | 否 | 输出值的说明。 |
| 类型 | JSON 对象 | 否 | 输出值的类型。 |
对话元数据
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 代理 | AgentContext | 是的 | 代理上下文信息。 |
| 用户 | UserContext | 否 | 有关与代理交互的用户的信息。 |
| 触发 | TriggerContext | 否 | 有关触发了计划员执行的内容的信息。 |
| conversationId | 字符串 | 是的 | 正在进行的对话的 ID。 |
| planId | 字符串 | 否 | 用于满足用户请求的计划 ID。 |
| planStepId | 字符串 | 否 | 与此工具执行对应的计划中的步骤。 |
| parentAgentComponentId | 字符串 | 否 | 父代理组件的 ID。 |
AgentContext
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | 字符串 | 是的 | 代理的 ID。 |
| tenantId | 字符串 | 是的 | 代理所在的租户。 |
| environmentId | 字符串 | 是的 | 发布智能体的环境。 |
| 版本 | 字符串 | 否 | 代理版本(可选(如果 isPublished 为 false)。 |
| isPublished | 布尔 | 是的 | 此执行上下文是否为已发布版本。 |
用户上下文
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | 字符串 | 否 | 用户的 Microsoft Entra 对象 ID。 |
| tenantId | 字符串 | 否 | 用户的租户 ID。 |
触发上下文
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | 字符串 | 否 | 触发了计划员的触发器的 ID。 |
| schemaName | 字符串 | 否 | 触发了计划员的触发器架构的名称。 |
Authentication
开发的集成应使用Microsoft Entra ID身份验证。 按照集成开发人员创建的应用程序的说明进行操作。
要执行的步骤包括:
- 在您的租户中为资源创建应用注册。
-
公开 Web API 的范围。 公开的范围必须是客户调用的资源的基本 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 版本,但在看到新版本时不应让请求失败。